Merge tag 'drm-misc-next-fixes-2019-11-13' of git://anongit.freedesktop.org/drm/drm...
authorDave Airlie <airlied@redhat.com>
Wed, 13 Nov 2019 22:51:02 +0000 (08:51 +1000)
committerDave Airlie <airlied@redhat.com>
Wed, 13 Nov 2019 22:51:11 +0000 (08:51 +1000)
- Fix memory leak in gpu debugfs node's release (Johan)

Cc: Johan Hovold <johan@kernel.org>
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Sean Paul <sean@poorly.run>
Link: https://patchwork.freedesktop.org/patch/msgid/20191113211056.GA78440@art_vandelay
905 files changed:
.mailmap
Documentation/arm64/silicon-errata.rst
Documentation/devicetree/bindings/arm/rockchip.yaml
Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml
Documentation/devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml
Documentation/devicetree/bindings/regulator/fixed-regulator.yaml
Documentation/devicetree/bindings/riscv/cpus.yaml
Documentation/gpu/amdgpu.rst
Documentation/networking/device_drivers/intel/e100.rst
Documentation/networking/device_drivers/intel/e1000.rst
Documentation/networking/device_drivers/intel/e1000e.rst
Documentation/networking/device_drivers/intel/fm10k.rst
Documentation/networking/device_drivers/intel/i40e.rst
Documentation/networking/device_drivers/intel/iavf.rst
Documentation/networking/device_drivers/intel/ice.rst
Documentation/networking/device_drivers/intel/igb.rst
Documentation/networking/device_drivers/intel/igbvf.rst
Documentation/networking/device_drivers/intel/ixgbe.rst
Documentation/networking/device_drivers/intel/ixgbevf.rst
Documentation/networking/device_drivers/pensando/ionic.rst
Documentation/networking/ip-sysctl.txt
Documentation/networking/tls-offload.rst
MAINTAINERS
Makefile
arch/arc/boot/dts/hsdk.dts
arch/arc/configs/hsdk_defconfig
arch/arc/kernel/perf_event.c
arch/arm/boot/dts/am3874-iceboard.dts
arch/arm/boot/dts/bcm2835-rpi-zero-w.dts
arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi
arch/arm/boot/dts/imx6-logicpd-baseboard.dtsi
arch/arm/boot/dts/imx6-logicpd-som.dtsi
arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
arch/arm/boot/dts/imx7s.dtsi
arch/arm/boot/dts/logicpd-torpedo-som.dtsi
arch/arm/boot/dts/omap4-droid4-xt894.dts
arch/arm/boot/dts/omap4-panda-common.dtsi
arch/arm/boot/dts/omap4-sdp.dts
arch/arm/boot/dts/omap4-var-som-om44-wlan.dtsi
arch/arm/boot/dts/omap5-board-common.dtsi
arch/arm/boot/dts/omap54xx-clocks.dtsi
arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
arch/arm/boot/dts/stm32mp157c-ev1.dts
arch/arm/boot/dts/stm32mp157c.dtsi
arch/arm/boot/dts/sun7i-a20.dtsi
arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
arch/arm/boot/dts/vf610-zii-scu4-aib.dts
arch/arm/configs/davinci_all_defconfig
arch/arm/configs/imx_v6_v7_defconfig
arch/arm/configs/omap2plus_defconfig
arch/arm/include/asm/domain.h
arch/arm/include/asm/uaccess.h
arch/arm/kernel/head-common.S
arch/arm/kernel/head-nommu.S
arch/arm/mach-davinci/dm365.c
arch/arm/mach-omap2/pdata-quirks.c
arch/arm/mach-sunxi/mc_smp.c
arch/arm/mm/alignment.c
arch/arm/mm/proc-v7m.S
arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts
arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
arch/arm64/boot/dts/broadcom/stingray/stingray-pinctrl.dtsi
arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi
arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts
arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
arch/arm64/boot/dts/freescale/imx8mm.dtsi
arch/arm64/boot/dts/freescale/imx8mn.dtsi
arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi
arch/arm64/boot/dts/freescale/imx8mq.dtsi
arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts
arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
arch/arm64/boot/dts/rockchip/rk3399-hugsun-x99.dts
arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts
arch/arm64/include/asm/cputype.h
arch/arm64/include/asm/pgtable-prot.h
arch/arm64/include/asm/pgtable.h
arch/arm64/include/asm/vdso/vsyscall.h
arch/arm64/kernel/cpu_errata.c
arch/arm64/kvm/sys_regs.c
arch/mips/bcm63xx/prom.c
arch/mips/include/asm/bmips.h
arch/mips/include/asm/vdso/gettimeofday.h
arch/mips/include/asm/vdso/vsyscall.h
arch/mips/kernel/smp-bmips.c
arch/mips/mm/tlbex.c
arch/parisc/kernel/entry.S
arch/powerpc/include/asm/book3s/32/kup.h
arch/powerpc/include/asm/elf.h
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/prom_init_check.sh
arch/powerpc/kvm/book3s_xive.c
arch/powerpc/kvm/book3s_xive.h
arch/powerpc/kvm/book3s_xive_native.c
arch/powerpc/net/bpf_jit_comp64.c
arch/powerpc/platforms/powernv/eeh-powernv.c
arch/powerpc/platforms/powernv/smp.c
arch/riscv/include/asm/bug.h
arch/riscv/include/asm/io.h
arch/riscv/include/asm/irq.h
arch/riscv/include/asm/pgtable.h
arch/riscv/include/asm/switch_to.h
arch/riscv/kernel/cpufeature.c
arch/riscv/kernel/head.h [new file with mode: 0644]
arch/riscv/kernel/irq.c
arch/riscv/kernel/module-sections.c
arch/riscv/kernel/process.c
arch/riscv/kernel/ptrace.c
arch/riscv/kernel/reset.c
arch/riscv/kernel/setup.c
arch/riscv/kernel/signal.c
arch/riscv/kernel/smp.c
arch/riscv/kernel/smpboot.c
arch/riscv/kernel/syscall_table.c
arch/riscv/kernel/time.c
arch/riscv/kernel/traps.c
arch/riscv/kernel/vdso.c
arch/riscv/mm/context.c
arch/riscv/mm/fault.c
arch/riscv/mm/init.c
arch/riscv/mm/sifive_l2_cache.c
arch/s390/boot/startup.c
arch/s390/include/asm/unwind.h
arch/s390/kernel/idle.c
arch/s390/kernel/machine_kexec_reloc.c
arch/s390/kernel/unwind_bc.c
arch/s390/mm/cmm.c
arch/um/drivers/ubd_kern.c
arch/x86/boot/compressed/eboot.c
arch/x86/events/amd/ibs.c
arch/x86/events/intel/pt.c
arch/x86/events/intel/uncore.c
arch/x86/events/intel/uncore.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/vmware.h
arch/x86/kernel/apic/apic.c
arch/x86/kernel/cpu/resctrl/ctrlmondata.c
arch/x86/kernel/dumpstack_64.c
arch/x86/kernel/tsc.c
arch/x86/kvm/cpuid.c
arch/x86/kvm/lapic.c
arch/x86/kvm/lapic.h
arch/x86/kvm/svm.c
arch/x86/kvm/vmx/nested.c
arch/x86/kvm/vmx/nested.h
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/x86.c
arch/x86/xen/enlighten_pv.c
block/blk-cgroup.c
block/blk-iocost.c
drivers/acpi/nfit/core.c
drivers/acpi/processor_driver.c
drivers/acpi/processor_perflib.c
drivers/acpi/processor_thermal.c
drivers/amba/bus.c
drivers/android/binder.c
drivers/android/binder_alloc.c
drivers/ata/libahci_platform.c
drivers/base/power/qos.c
drivers/block/drbd/drbd_main.c
drivers/block/nbd.c
drivers/bus/ti-sysc.c
drivers/clk/at91/clk-main.c
drivers/clk/at91/sam9x60.c
drivers/clk/at91/sckc.c
drivers/clk/clk-ast2600.c
drivers/clk/imx/clk-imx8mm.c
drivers/clk/imx/clk-imx8mn.c
drivers/clk/meson/g12a.c
drivers/clk/meson/gxbb.c
drivers/clk/samsung/clk-exynos5420.c
drivers/clk/samsung/clk-exynos5433.c
drivers/clk/sunxi-ng/ccu-sun9i-a80.c
drivers/clk/sunxi/clk-sunxi.c
drivers/clk/ti/clk-dra7-atl.c
drivers/clk/ti/clkctrl.c
drivers/clocksource/sh_mtu2.c
drivers/clocksource/timer-mediatek.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/ppc_cbe_cpufreq_pmi.c
drivers/cpuidle/cpuidle-haltpoll.c
drivers/crypto/chelsio/chtls/chtls_cm.c
drivers/crypto/chelsio/chtls/chtls_io.c
drivers/dma/imx-sdma.c
drivers/dma/qcom/bam_dma.c
drivers/dma/sprd-dma.c
drivers/dma/tegra210-adma.c
drivers/dma/ti/cppi41.c
drivers/dma/xilinx/xilinx_dma.c
drivers/edac/ghes_edac.c
drivers/firmware/efi/Kconfig
drivers/firmware/efi/efi.c
drivers/firmware/efi/libstub/Makefile
drivers/firmware/efi/libstub/arm32-stub.c
drivers/firmware/efi/libstub/efi-stub-helper.c
drivers/firmware/efi/test/efi_test.c
drivers/firmware/efi/tpm.c
drivers/gpio/gpio-merrifield.c
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
drivers/gpu/drm/amd/amdgpu/amdgpu_test.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c
drivers/gpu/drm/amd/amdgpu/nv.c
drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
drivers/gpu/drm/amd/amdgpu/soc15.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/dc/calcs/Makefile
drivers/gpu/drm/amd/display/dc/core/dc_link.c
drivers/gpu/drm/amd/display/dc/dcn20/Makefile
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
drivers/gpu/drm/amd/display/dc/dcn21/Makefile
drivers/gpu/drm/amd/display/dc/dml/Makefile
drivers/gpu/drm/amd/display/dc/dsc/Makefile
drivers/gpu/drm/amd/include/kgd_pp_interface.h
drivers/gpu/drm/amd/powerplay/amd_powerplay.c
drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_arcturus.h
drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h
drivers/gpu/drm/amd/powerplay/navi10_ppt.c
drivers/gpu/drm/amd/powerplay/renoir_ppt.c
drivers/gpu/drm/amd/powerplay/smu_v11_0.c
drivers/gpu/drm/amd/powerplay/vega20_ppt.c
drivers/gpu/drm/arm/display/komeda/komeda_kms.c
drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/drm_self_refresh_helper.c
drivers/gpu/drm/etnaviv/etnaviv_dump.c
drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c
drivers/gpu/drm/etnaviv/etnaviv_mmu.c
drivers/gpu/drm/panfrost/panfrost_drv.c
drivers/gpu/drm/panfrost/panfrost_mmu.c
drivers/gpu/drm/panfrost/panfrost_perfcnt.c
drivers/gpu/drm/radeon/si_dpm.c
drivers/gpu/drm/scheduler/sched_entity.c
drivers/gpu/drm/scheduler/sched_main.c
drivers/gpu/drm/v3d/v3d_gem.c
drivers/hid/hid-axff.c
drivers/hid/hid-core.c
drivers/hid/hid-dr.c
drivers/hid/hid-emsff.c
drivers/hid/hid-gaff.c
drivers/hid/hid-google-hammer.c
drivers/hid/hid-holtekff.c
drivers/hid/hid-ids.h
drivers/hid/hid-lg2ff.c
drivers/hid/hid-lg3ff.c
drivers/hid/hid-lg4ff.c
drivers/hid/hid-lgff.c
drivers/hid/hid-logitech-hidpp.c
drivers/hid/hid-microsoft.c
drivers/hid/hid-prodikeys.c
drivers/hid/hid-sony.c
drivers/hid/hid-tmff.c
drivers/hid/hid-zpff.c
drivers/hid/i2c-hid/i2c-hid-core.c
drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c
drivers/hid/intel-ish-hid/ishtp/client-buffers.c
drivers/hid/wacom.h
drivers/hid/wacom_wac.c
drivers/hwmon/ina3221.c
drivers/hwmon/nct7904.c
drivers/hwtracing/intel_th/gth.c
drivers/hwtracing/intel_th/msu.c
drivers/hwtracing/intel_th/pci.c
drivers/i2c/busses/i2c-aspeed.c
drivers/i2c/busses/i2c-mt65xx.c
drivers/i2c/busses/i2c-stm32f7.c
drivers/iio/adc/stm32-adc.c
drivers/iio/imu/adis16480.c
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
drivers/iio/proximity/srf04.c
drivers/infiniband/core/core_priv.h
drivers/infiniband/core/device.c
drivers/infiniband/core/iwcm.c
drivers/infiniband/core/netlink.c
drivers/infiniband/core/nldev.c
drivers/infiniband/core/uverbs.h
drivers/infiniband/core/verbs.c
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/hw/hfi1/sdma.c
drivers/infiniband/hw/hfi1/tid_rdma.c
drivers/infiniband/hw/hfi1/verbs.c
drivers/infiniband/hw/hns/hns_roce_hw_v2.c
drivers/infiniband/hw/mlx5/mr.c
drivers/infiniband/hw/mlx5/qp.c
drivers/infiniband/hw/qedr/main.c
drivers/infiniband/sw/siw/siw_qp.c
drivers/infiniband/sw/siw/siw_verbs.c
drivers/input/touchscreen/st1232.c
drivers/interconnect/core.c
drivers/interconnect/qcom/qcs404.c
drivers/interconnect/qcom/sdm845.c
drivers/iommu/amd_iommu_quirks.c
drivers/iommu/intel-iommu.c
drivers/iommu/ipmmu-vmsa.c
drivers/irqchip/irq-gic-v3-its.c
drivers/irqchip/irq-sifive-plic.c
drivers/isdn/capi/capi.c
drivers/macintosh/windfarm_cpufreq_clamp.c
drivers/mfd/mt6397-core.c
drivers/mmc/host/cqhci.c
drivers/mmc/host/mxs-mmc.c
drivers/mmc/host/sdhci-omap.c
drivers/net/bonding/bond_alb.c
drivers/net/bonding/bond_main.c
drivers/net/can/c_can/c_can.c
drivers/net/can/c_can/c_can.h
drivers/net/can/dev.c
drivers/net/can/flexcan.c
drivers/net/can/rx-offload.c
drivers/net/can/spi/mcp251x.c
drivers/net/can/ti_hecc.c
drivers/net/can/usb/gs_usb.c
drivers/net/can/usb/mcba_usb.c
drivers/net/can/usb/peak_usb/pcan_usb.c
drivers/net/can/usb/peak_usb/pcan_usb_core.c
drivers/net/can/usb/usb_8dev.c
drivers/net/can/xilinx_can.c
drivers/net/dsa/bcm_sf2.c
drivers/net/dsa/sja1105/Kconfig
drivers/net/ethernet/arc/emac_rockchip.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h
drivers/net/ethernet/broadcom/genet/bcmgenet.c
drivers/net/ethernet/broadcom/genet/bcmgenet.h
drivers/net/ethernet/broadcom/genet/bcmmii.c
drivers/net/ethernet/cavium/octeon/octeon_mgmt.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c
drivers/net/ethernet/chelsio/cxgb4/sge.c
drivers/net/ethernet/cortina/gemini.h
drivers/net/ethernet/faraday/ftgmac100.c
drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.h
drivers/net/ethernet/freescale/dpaa2/dprtc-cmd.h
drivers/net/ethernet/freescale/dpaa2/dprtc.h
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/freescale/fec_ptp.c
drivers/net/ethernet/google/gve/gve_rx.c
drivers/net/ethernet/google/gve/gve_tx.c
drivers/net/ethernet/hisilicon/hip04_eth.c
drivers/net/ethernet/hisilicon/hns/hnae.c
drivers/net/ethernet/hisilicon/hns/hnae.h
drivers/net/ethernet/hisilicon/hns/hns_enet.c
drivers/net/ethernet/hisilicon/hns3/hnae3.h
drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
drivers/net/ethernet/intel/e1000/e1000_ethtool.c
drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
drivers/net/ethernet/intel/i40e/i40e_common.c
drivers/net/ethernet/intel/i40e/i40e_xsk.c
drivers/net/ethernet/intel/iavf/iavf_main.c
drivers/net/ethernet/intel/ice/ice_sched.c
drivers/net/ethernet/intel/igb/e1000_82575.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/igc/igc_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c
drivers/net/ethernet/marvell/mvneta_bm.h
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en/hv_vhca_stats.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.h
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_selftest.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_tx.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c
drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
drivers/net/ethernet/mellanox/mlx5/core/health.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c
drivers/net/ethernet/mellanox/mlxsw/core.c
drivers/net/ethernet/mscc/ocelot.c
drivers/net/ethernet/mscc/ocelot.h
drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
drivers/net/ethernet/pensando/ionic/ionic_lif.c
drivers/net/ethernet/pensando/ionic/ionic_main.c
drivers/net/ethernet/qlogic/qed/qed_main.c
drivers/net/ethernet/qlogic/qed/qed_sriov.c
drivers/net/ethernet/qlogic/qede/qede_main.c
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
drivers/net/ethernet/realtek/r8169_main.c
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
drivers/net/ethernet/stmicro/stmmac/mmc_core.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c
drivers/net/fjes/fjes_main.c
drivers/net/hamradio/bpqether.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/ipvlan/ipvlan_main.c
drivers/net/macsec.c
drivers/net/macvlan.c
drivers/net/netdevsim/dev.c
drivers/net/phy/phylink.c
drivers/net/phy/smsc.c
drivers/net/ppp/ppp_generic.c
drivers/net/team/team.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/cdc_ncm.c
drivers/net/usb/lan78xx.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/r8152.c
drivers/net/vrf.c
drivers/net/vxlan.c
drivers/net/wimax/i2400m/op-rfkill.c
drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
drivers/net/wireless/intel/iwlwifi/fw/file.h
drivers/net/wireless/intel/iwlwifi/iwl-csr.h
drivers/net/wireless/intel/iwlwifi/iwl-prph.h
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/mvm/scan.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.c
drivers/net/wireless/intel/iwlwifi/pcie/drv.c
drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
drivers/net/wireless/intersil/hostap/hostap_hw.c
drivers/net/wireless/mediatek/mt76/Makefile
drivers/net/wireless/mediatek/mt76/dma.c
drivers/net/wireless/mediatek/mt76/mt76.h
drivers/net/wireless/mediatek/mt76/mt76x2/pci.c
drivers/net/wireless/mediatek/mt76/pci.c [new file with mode: 0644]
drivers/net/wireless/realtek/rtlwifi/pci.c
drivers/net/wireless/realtek/rtlwifi/ps.c
drivers/net/wireless/virt_wifi.c
drivers/nfc/fdp/i2c.c
drivers/nfc/st21nfca/core.c
drivers/nvme/host/multipath.c
drivers/nvme/host/rdma.c
drivers/nvme/host/tcp.c
drivers/of/of_reserved_mem.c
drivers/of/unittest.c
drivers/opp/core.c
drivers/opp/of.c
drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
drivers/pinctrl/aspeed/pinmux-aspeed.h
drivers/pinctrl/bcm/pinctrl-iproc-gpio.c
drivers/pinctrl/bcm/pinctrl-ns2-mux.c
drivers/pinctrl/berlin/pinctrl-as370.c
drivers/pinctrl/intel/pinctrl-cherryview.c
drivers/pinctrl/intel/pinctrl-intel.c
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
drivers/pinctrl/pinctrl-stmfx.c
drivers/pwm/core.c
drivers/pwm/pwm-bcm-iproc.c
drivers/regulator/core.c
drivers/regulator/da9062-regulator.c
drivers/regulator/fixed.c
drivers/regulator/lochnagar-regulator.c
drivers/regulator/of_regulator.c
drivers/regulator/pfuze100-regulator.c
drivers/regulator/qcom-rpmh-regulator.c
drivers/regulator/ti-abb-regulator.c
drivers/reset/core.c
drivers/s390/crypto/zcrypt_api.c
drivers/scsi/Kconfig
drivers/scsi/ch.c
drivers/scsi/device_handler/scsi_dh_alua.c
drivers/scsi/hpsa.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_nportdisc.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_bsg.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/sd.c
drivers/scsi/sni_53c710.c
drivers/scsi/ufs/ufs_bsg.c
drivers/soc/imx/gpc.c
drivers/soc/imx/soc-imx-scu.c
drivers/soundwire/Kconfig
drivers/soundwire/intel.c
drivers/soundwire/slave.c
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/vboxsf/Kconfig [new file with mode: 0644]
drivers/staging/vboxsf/Makefile [new file with mode: 0644]
drivers/staging/vboxsf/TODO [new file with mode: 0644]
drivers/staging/vboxsf/dir.c [new file with mode: 0644]
drivers/staging/vboxsf/file.c [new file with mode: 0644]
drivers/staging/vboxsf/shfl_hostintf.h [new file with mode: 0644]
drivers/staging/vboxsf/super.c [new file with mode: 0644]
drivers/staging/vboxsf/utils.c [new file with mode: 0644]
drivers/staging/vboxsf/vboxsf_wrappers.c [new file with mode: 0644]
drivers/staging/vboxsf/vfsmod.h [new file with mode: 0644]
drivers/staging/wlan-ng/cfg80211.c
drivers/target/iscsi/cxgbit/cxgbit_cm.c
drivers/target/target_core_device.c
drivers/thermal/cpu_cooling.c
drivers/thunderbolt/nhi_ops.c
drivers/thunderbolt/switch.c
drivers/tty/serial/8250/8250_men_mcb.c
drivers/usb/cdns3/core.c
drivers/usb/cdns3/gadget.c
drivers/usb/cdns3/host-export.h
drivers/usb/cdns3/host.c
drivers/usb/class/usblp.c
drivers/usb/core/config.c
drivers/usb/dwc3/Kconfig
drivers/usb/dwc3/core.c
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/composite.c
drivers/usb/gadget/configfs.c
drivers/usb/gadget/udc/atmel_usba_udc.c
drivers/usb/gadget/udc/core.c
drivers/usb/gadget/udc/fsl_udc_core.c
drivers/usb/gadget/udc/lpc32xx_udc.c
drivers/usb/gadget/udc/renesas_usb3.c
drivers/usb/host/xhci-debugfs.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/misc/ldusb.c
drivers/usb/misc/legousbtower.c
drivers/usb/mtu3/mtu3_core.c
drivers/usb/renesas_usbhs/common.c
drivers/usb/renesas_usbhs/mod_gadget.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/serial/whiteheat.c
drivers/usb/serial/whiteheat.h
drivers/usb/storage/scsiglue.c
drivers/usb/storage/uas.c
drivers/usb/usbip/vhci_tx.c
drivers/vfio/vfio_iommu_type1.c
drivers/vhost/vringh.c
drivers/video/fbdev/c2p_core.h
drivers/virtio/virtio_ring.c
drivers/watchdog/bd70528_wdt.c
drivers/watchdog/cpwd.c
drivers/watchdog/imx_sc_wdt.c
drivers/watchdog/meson_gxbb_wdt.c
drivers/watchdog/pm8916_wdt.c
fs/btrfs/block-group.c
fs/btrfs/ctree.h
fs/btrfs/delalloc-space.c
fs/btrfs/disk-io.c
fs/btrfs/file.c
fs/btrfs/inode-map.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/qgroup.c
fs/btrfs/relocation.c
fs/btrfs/space-info.c
fs/btrfs/tree-checker.c
fs/btrfs/volumes.c
fs/ceph/caps.c
fs/ceph/dir.c
fs/ceph/file.c
fs/ceph/inode.c
fs/ceph/super.c
fs/cifs/cifsfs.c
fs/cifs/cifsglob.h
fs/cifs/cifsproto.h
fs/cifs/connect.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/smb1ops.c
fs/cifs/smb2file.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.h
fs/cifs/transport.c
fs/configfs/symlink.c
fs/dax.c
fs/fs-writeback.c
fs/fuse/Makefile
fs/fuse/dev.c
fs/fuse/dir.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/fuse/inode.c
fs/fuse/virtio_fs.c
fs/gfs2/ops_fstype.c
fs/io_uring.c
fs/nfs/delegation.c
fs/nfs/delegation.h
fs/nfs/nfs4proc.c
fs/ocfs2/file.c
include/acpi/processor.h
include/asm-generic/vdso/vsyscall.h
include/drm/drm_gem_shmem_helper.h
include/drm/drm_self_refresh_helper.h
include/drm/gpu_scheduler.h
include/linux/bpf.h
include/linux/cpufreq.h
include/linux/dynamic_debug.h
include/linux/efi.h
include/linux/export.h
include/linux/filter.h
include/linux/gfp.h
include/linux/idr.h
include/linux/if_macvlan.h
include/linux/if_team.h
include/linux/if_vlan.h
include/linux/mlx5/mlx5_ifc.h
include/linux/mm.h
include/linux/mm_types.h
include/linux/netdevice.h
include/linux/page-flags.h
include/linux/perf_event.h
include/linux/platform_data/dma-imx-sdma.h
include/linux/pm_qos.h
include/linux/radix-tree.h
include/linux/reset-controller.h
include/linux/reset.h
include/linux/security.h
include/linux/skbuff.h
include/linux/skmsg.h
include/linux/socket.h
include/linux/sunrpc/bc_xprt.h
include/linux/sysfs.h
include/linux/virtio_vsock.h
include/net/bonding.h
include/net/busy_poll.h
include/net/flow_dissector.h
include/net/fq.h
include/net/fq_impl.h
include/net/hwbm.h
include/net/ip.h
include/net/ip_vs.h
include/net/neighbour.h
include/net/net_namespace.h
include/net/netfilter/nf_tables.h
include/net/sch_generic.h
include/net/sock.h
include/net/tls.h
include/net/vxlan.h
include/rdma/ib_verbs.h
include/sound/simple_card_utils.h
include/trace/events/btrfs.h
include/uapi/linux/can.h
include/uapi/linux/can/bcm.h
include/uapi/linux/can/error.h
include/uapi/linux/can/gw.h
include/uapi/linux/can/j1939.h
include/uapi/linux/can/netlink.h
include/uapi/linux/can/raw.h
include/uapi/linux/can/vxcan.h
include/uapi/linux/fuse.h
include/uapi/linux/nvme_ioctl.h
include/uapi/linux/sched.h
kernel/bpf/cgroup.c
kernel/bpf/core.c
kernel/bpf/devmap.c
kernel/bpf/syscall.c
kernel/cgroup/cpuset.c
kernel/events/core.c
kernel/fork.c
kernel/irq/irqdomain.c
kernel/power/qos.c
kernel/sched/core.c
kernel/sched/deadline.c
kernel/sched/fair.c
kernel/sched/idle.c
kernel/sched/rt.c
kernel/sched/sched.h
kernel/sched/stop_task.c
kernel/sched/topology.c
kernel/stacktrace.c
kernel/time/posix-cpu-timers.c
kernel/time/sched_clock.c
kernel/time/vsyscall.c
kernel/trace/trace_event_perf.c
kernel/trace/trace_events_hist.c
lib/Kconfig
lib/dump_stack.c
lib/idr.c
lib/radix-tree.c
lib/test_xarray.c
lib/vdso/gettimeofday.c
lib/xarray.c
mm/khugepaged.c
mm/memcontrol.c
mm/memory_hotplug.c
mm/mmu_notifier.c
mm/page_alloc.c
mm/slab.h
mm/vmstat.c
net/8021q/vlan.c
net/8021q/vlan_dev.c
net/atm/common.c
net/batman-adv/bat_iv_ogm.c
net/batman-adv/bat_v_ogm.c
net/batman-adv/hard-interface.c
net/batman-adv/soft-interface.c
net/batman-adv/types.h
net/bluetooth/6lowpan.c
net/bluetooth/af_bluetooth.c
net/bridge/br_device.c
net/bridge/netfilter/ebt_dnat.c
net/bridge/netfilter/nf_conntrack_bridge.c
net/caif/caif_socket.c
net/can/j1939/socket.c
net/can/j1939/transport.c
net/core/datagram.c
net/core/dev.c
net/core/dev_addr_lists.c
net/core/ethtool.c
net/core/flow_dissector.c
net/core/lwt_bpf.c
net/core/net_namespace.c
net/core/rtnetlink.c
net/core/skmsg.c
net/core/sock.c
net/dccp/ipv4.c
net/decnet/af_decnet.c
net/dsa/master.c
net/dsa/slave.c
net/ieee802154/6lowpan/core.c
net/ipv4/datagram.c
net/ipv4/fib_frontend.c
net/ipv4/fib_semantics.c
net/ipv4/inet_hashtables.c
net/ipv4/ip_gre.c
net/ipv4/ip_output.c
net/ipv4/tcp.c
net/ipv4/tcp_ipv4.c
net/ipv4/udp.c
net/ipv6/addrconf_core.c
net/ipv6/inet6_hashtables.c
net/ipv6/ip6_gre.c
net/ipv6/route.c
net/ipv6/udp.c
net/l2tp/l2tp_eth.c
net/mac80211/main.c
net/mac80211/sta_info.c
net/netfilter/ipset/ip_set_core.c
net/netfilter/ipset/ip_set_hash_ipmac.c
net/netfilter/ipset/ip_set_hash_net.c
net/netfilter/ipset/ip_set_hash_netnet.c
net/netfilter/ipvs/ip_vs_app.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/ipvs/ip_vs_pe.c
net/netfilter/ipvs/ip_vs_sched.c
net/netfilter/ipvs/ip_vs_sync.c
net/netfilter/nf_flow_table_core.c
net/netfilter/nf_tables_api.c
net/netfilter/nf_tables_offload.c
net/netfilter/nft_bitwise.c
net/netfilter/nft_cmp.c
net/netfilter/nft_payload.c
net/netrom/af_netrom.c
net/nfc/llcp_sock.c
net/nfc/netlink.c
net/openvswitch/datapath.c
net/openvswitch/vport-internal_dev.c
net/phonet/socket.c
net/rose/af_rose.c
net/rxrpc/ar-internal.h
net/rxrpc/recvmsg.c
net/sched/cls_api.c
net/sched/cls_bpf.c
net/sched/sch_generic.c
net/sched/sch_hhf.c
net/sched/sch_sfb.c
net/sched/sch_sfq.c
net/sched/sch_taprio.c
net/sctp/socket.c
net/smc/af_smc.c
net/smc/smc_core.c
net/smc/smc_pnet.c
net/sunrpc/backchannel_rqst.c
net/sunrpc/xprt.c
net/sunrpc/xprtrdma/backchannel.c
net/tipc/socket.c
net/tls/tls_device.c
net/tls/tls_main.c
net/tls/tls_sw.c
net/unix/af_unix.c
net/vmw_vsock/af_vsock.c
net/vmw_vsock/virtio_transport_common.c
net/wireless/chan.c
net/wireless/nl80211.c
net/wireless/util.c
net/xdp/xdp_umem.c
samples/bpf/Makefile
scripts/gdb/linux/symbols.py
scripts/mod/modpost.c
scripts/mod/modpost.h
scripts/nsdeps
security/lockdown/lockdown.c
sound/core/compress_offload.c
sound/core/timer.c
sound/firewire/bebob/bebob_focusrite.c
sound/firewire/bebob/bebob_stream.c
sound/hda/hdac_controller.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/soc/codecs/hdac_hda.c
sound/soc/codecs/hdmi-codec.c
sound/soc/codecs/max98373.c
sound/soc/codecs/msm8916-wcd-analog.c
sound/soc/codecs/msm8916-wcd-digital.c
sound/soc/codecs/rt5651.c
sound/soc/codecs/rt5682.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm_adsp.c
sound/soc/intel/boards/sof_rt5682.c
sound/soc/kirkwood/kirkwood-i2s.c
sound/soc/rockchip/rockchip_i2s.c
sound/soc/rockchip/rockchip_max98090.c
sound/soc/samsung/arndale_rt5631.c
sound/soc/sh/rcar/core.c
sound/soc/sh/rcar/dma.c
sound/soc/soc-pcm.c
sound/soc/soc-topology.c
sound/soc/sof/control.c
sound/soc/sof/debug.c
sound/soc/sof/intel/Kconfig
sound/soc/sof/intel/bdw.c
sound/soc/sof/intel/byt.c
sound/soc/sof/intel/hda-ctrl.c
sound/soc/sof/intel/hda-loader.c
sound/soc/sof/intel/hda-stream.c
sound/soc/sof/intel/hda.c
sound/soc/sof/intel/hda.h
sound/soc/sof/ipc.c
sound/soc/sof/loader.c
sound/soc/sof/pcm.c
sound/soc/sof/topology.c
sound/soc/stm/stm32_sai_sub.c
sound/soc/ti/sdma-pcm.c
sound/usb/quirks.c
sound/usb/validate.c
tools/arch/x86/include/uapi/asm/svm.h
tools/arch/x86/include/uapi/asm/vmx.h
tools/gpio/Makefile
tools/include/uapi/linux/kvm.h
tools/include/uapi/linux/sched.h
tools/perf/builtin-c2c.c
tools/perf/builtin-kmem.c
tools/perf/jvmti/Build
tools/perf/perf-sys.h
tools/perf/util/annotate.c
tools/perf/util/copyfile.c
tools/perf/util/evlist.c
tools/perf/util/header.c
tools/perf/util/hist.c
tools/perf/util/scripting-engines/trace-event-perl.c
tools/perf/util/scripting-engines/trace-event-python.c
tools/perf/util/trace-event-parse.c
tools/perf/util/trace-event.h
tools/perf/util/util.c
tools/testing/selftests/bpf/test_offload.py
tools/testing/selftests/bpf/test_sysctl.c
tools/testing/selftests/bpf/test_tc_edt.sh
tools/testing/selftests/kvm/.gitignore
tools/testing/selftests/kvm/include/x86_64/vmx.h
tools/testing/selftests/kvm/lib/x86_64/vmx.c
tools/testing/selftests/kvm/x86_64/sync_regs_test.c
tools/testing/selftests/kvm/x86_64/vmx_close_while_nested_test.c
tools/testing/selftests/kvm/x86_64/vmx_dirty_log_test.c
tools/testing/selftests/kvm/x86_64/vmx_set_nested_state_test.c
tools/testing/selftests/kvm/x86_64/vmx_tsc_adjust_test.c
tools/testing/selftests/net/fib_tests.sh
tools/testing/selftests/net/l2tp.sh [changed mode: 0644->0755]
tools/testing/selftests/net/reuseport_dualstack.c
tools/testing/selftests/net/tls.c
tools/testing/selftests/vm/gup_benchmark.c
tools/usb/usbip/libsrc/usbip_device_driver.c
virt/kvm/arm/pmu.c
virt/kvm/kvm_main.c

index edcac87e76c8c7fe9020943bdce012f7e47dc962..fd62192930570694a6a7badfc54f9dc184d584e4 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -108,6 +108,10 @@ Jason Gunthorpe <jgg@ziepe.ca> <jgg@mellanox.com>
 Jason Gunthorpe <jgg@ziepe.ca> <jgunthorpe@obsidianresearch.com>
 Javi Merino <javi.merino@kernel.org> <javi.merino@arm.com>
 <javier@osg.samsung.com> <javier.martinez@collabora.co.uk>
+Jayachandran C <c.jayachandran@gmail.com> <jayachandranc@netlogicmicro.com>
+Jayachandran C <c.jayachandran@gmail.com> <jchandra@broadcom.com>
+Jayachandran C <c.jayachandran@gmail.com> <jchandra@digeo.com>
+Jayachandran C <c.jayachandran@gmail.com> <jnair@caviumnetworks.com>
 Jean Tourrilhes <jt@hpl.hp.com>
 <jean-philippe@linaro.org> <jean-philippe.brucker@arm.com>
 Jeff Garzik <jgarzik@pretzel.yyz.us>
@@ -196,7 +200,8 @@ Oleksij Rempel <linux@rempel-privat.de> <o.rempel@pengutronix.de>
 Oleksij Rempel <linux@rempel-privat.de> <ore@pengutronix.de>
 Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
 Patrick Mochel <mochel@digitalimplant.org>
-Paul Burton <paul.burton@mips.com> <paul.burton@imgtec.com>
+Paul Burton <paulburton@kernel.org> <paul.burton@imgtec.com>
+Paul Burton <paulburton@kernel.org> <paul.burton@mips.com>
 Peter A Jonsson <pj@ludd.ltu.se>
 Peter Oruba <peter@oruba.de>
 Peter Oruba <peter.oruba@amd.com>
@@ -229,6 +234,7 @@ Shuah Khan <shuah@kernel.org> <shuahkhan@gmail.com>
 Shuah Khan <shuah@kernel.org> <shuah.khan@hp.com>
 Shuah Khan <shuah@kernel.org> <shuahkh@osg.samsung.com>
 Shuah Khan <shuah@kernel.org> <shuah.kh@samsung.com>
+Simon Arlott <simon@octiron.net> <simon@fire.lp0.eu>
 Simon Kelley <simon@thekelleys.org.uk>
 Stéphane Witzmann <stephane.witzmann@ubpmes.univ-bpclermont.fr>
 Stephen Hemminger <shemminger@osdl.org>
index ab7ed2fd072f34a83eb551558ea8b0b5e36db2d4..5a09661330fccfceedcb4e5879535d30b51697d3 100644 (file)
@@ -91,6 +91,11 @@ stable kernels.
 | ARM            | MMU-500         | #841119,826419  | N/A                         |
 +----------------+-----------------+-----------------+-----------------------------+
 +----------------+-----------------+-----------------+-----------------------------+
+| Broadcom       | Brahma-B53      | N/A             | ARM64_ERRATUM_845719        |
++----------------+-----------------+-----------------+-----------------------------+
+| Broadcom       | Brahma-B53      | N/A             | ARM64_ERRATUM_843419        |
++----------------+-----------------+-----------------+-----------------------------+
++----------------+-----------------+-----------------+-----------------------------+
 | Cavium         | ThunderX ITS    | #22375,24313    | CAVIUM_ERRATUM_22375        |
 +----------------+-----------------+-----------------+-----------------------------+
 | Cavium         | ThunderX ITS    | #23144          | CAVIUM_ERRATUM_23144        |
@@ -126,7 +131,7 @@ stable kernels.
 +----------------+-----------------+-----------------+-----------------------------+
 | Qualcomm Tech. | Kryo/Falkor v1  | E1003           | QCOM_FALKOR_ERRATUM_1003    |
 +----------------+-----------------+-----------------+-----------------------------+
-| Qualcomm Tech. | Falkor v1       | E1009           | QCOM_FALKOR_ERRATUM_1009    |
+| Qualcomm Tech. | Kryo/Falkor v1  | E1009           | QCOM_FALKOR_ERRATUM_1009    |
 +----------------+-----------------+-----------------+-----------------------------+
 | Qualcomm Tech. | QDF2400 ITS     | E0065           | QCOM_QDF2400_ERRATUM_0065   |
 +----------------+-----------------+-----------------+-----------------------------+
index c82c5e57d44c828c979eddd9ec43eaaf4e5fd53b..9c7e70335ac0f50d1c1678441a5a560491812fba 100644 (file)
@@ -496,12 +496,12 @@ properties:
 
       - description: Theobroma Systems RK3368-uQ7 with Haikou baseboard
         items:
-          - const: tsd,rk3368-uq7-haikou
+          - const: tsd,rk3368-lion-haikou
           - const: rockchip,rk3368
 
       - description: Theobroma Systems RK3399-Q7 with Haikou baseboard
         items:
-          - const: tsd,rk3399-q7-haikou
+          - const: tsd,rk3399-puma-haikou
           - const: rockchip,rk3399
 
       - description: Tronsmart Orion R68 Meta
index 27f38eed389e4830b8fb37794ac1fc89f6c962a4..d3e423fcb6c2ee643529f67527eda8ba88c3d32c 100644 (file)
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
 %YAML 1.2
 ---
-$id: http://devicetree.org/schemas/arm/allwinner,sun4i-a10-csi.yaml#
+$id: http://devicetree.org/schemas/media/allwinner,sun4i-a10-csi.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Allwinner A10 CMOS Sensor Interface (CSI) Device Tree Bindings
@@ -27,14 +27,12 @@ properties:
   clocks:
     items:
       - description: The CSI interface clock
-      - description: The CSI module clock
       - description: The CSI ISP clock
       - description: The CSI DRAM clock
 
   clock-names:
     items:
       - const: bus
-      - const: mod
       - const: isp
       - const: ram
 
@@ -89,9 +87,8 @@ examples:
         compatible = "allwinner,sun7i-a20-csi0";
         reg = <0x01c09000 0x1000>;
         interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
-        clocks = <&ccu CLK_AHB_CSI0>, <&ccu CLK_CSI0>,
-                 <&ccu CLK_CSI_SCLK>, <&ccu CLK_DRAM_CSI0>;
-        clock-names = "bus", "mod", "isp", "ram";
+        clocks = <&ccu CLK_AHB_CSI0>, <&ccu CLK_CSI_SCLK>, <&ccu CLK_DRAM_CSI0>;
+        clock-names = "bus", "isp", "ram";
         resets = <&ccu RST_CSI0>;
 
         port {
index f83d888176cc1316a7ea95ab89a71e85984fbe74..064b7dfc4252c51cebfb1e124b56a41f364eb89b 100644 (file)
@@ -33,13 +33,13 @@ patternProperties:
           allOf:
             - $ref: "/schemas/types.yaml#/definitions/string"
             - enum: [ ADC0, ADC1, ADC10, ADC11, ADC12, ADC13, ADC14, ADC15,
-              ADC2, ADC3, ADC4, ADC5, ADC6, ADC7, ADC8, ADC9, BMCINT, ESPI,
-              ESPIALT, FSI1, FSI2, FWSPIABR, FWSPID, FWSPIWP, GPIT0, GPIT1,
-              GPIT2, GPIT3, GPIT4, GPIT5, GPIT6, GPIT7, GPIU0, GPIU1, GPIU2,
-              GPIU3, GPIU4, GPIU5, GPIU6, GPIU7, I2C1, I2C10, I2C11, I2C12,
-              I2C13, I2C14, I2C15, I2C16, I2C2, I2C3, I2C4, I2C5, I2C6, I2C7,
-              I2C8, I2C9, I3C3, I3C4, I3C5, I3C6, JTAGM, LHPD, LHSIRQ, LPC,
-              LPCHC, LPCPD, LPCPME, LPCSMI, LSIRQ, MACLINK1, MACLINK2,
+              ADC2, ADC3, ADC4, ADC5, ADC6, ADC7, ADC8, ADC9, BMCINT, EMMC,
+              ESPI, ESPIALT, FSI1, FSI2, FWSPIABR, FWSPID, FWSPIWP, GPIT0,
+              GPIT1, GPIT2, GPIT3, GPIT4, GPIT5, GPIT6, GPIT7, GPIU0, GPIU1,
+              GPIU2, GPIU3, GPIU4, GPIU5, GPIU6, GPIU7, I2C1, I2C10, I2C11,
+              I2C12, I2C13, I2C14, I2C15, I2C16, I2C2, I2C3, I2C4, I2C5, I2C6,
+              I2C7, I2C8, I2C9, I3C3, I3C4, I3C5, I3C6, JTAGM, LHPD, LHSIRQ,
+              LPC, LPCHC, LPCPD, LPCPME, LPCSMI, LSIRQ, MACLINK1, MACLINK2,
               MACLINK3, MACLINK4, MDIO1, MDIO2, MDIO3, MDIO4, NCTS1, NCTS2,
               NCTS3, NCTS4, NDCD1, NDCD2, NDCD3, NDCD4, NDSR1, NDSR2, NDSR3,
               NDSR4, NDTR1, NDTR2, NDTR3, NDTR4, NRI1, NRI2, NRI3, NRI4, NRTS1,
@@ -48,47 +48,45 @@ patternProperties:
               PWM8, PWM9, RGMII1, RGMII2, RGMII3, RGMII4, RMII1, RMII2, RMII3,
               RMII4, RXD1, RXD2, RXD3, RXD4, SALT1, SALT10, SALT11, SALT12,
               SALT13, SALT14, SALT15, SALT16, SALT2, SALT3, SALT4, SALT5,
-              SALT6, SALT7, SALT8, SALT9, SD1, SD2, SD3, SD3DAT4, SD3DAT5,
-              SD3DAT6, SD3DAT7, SGPM1, SGPS1, SIOONCTRL, SIOPBI, SIOPBO,
-              SIOPWREQ, SIOPWRGD, SIOS3, SIOS5, SIOSCI, SPI1, SPI1ABR, SPI1CS1,
-              SPI1WP, SPI2, SPI2CS1, SPI2CS2, TACH0, TACH1, TACH10, TACH11,
-              TACH12, TACH13, TACH14, TACH15, TACH2, TACH3, TACH4, TACH5,
-              TACH6, TACH7, TACH8, TACH9, THRU0, THRU1, THRU2, THRU3, TXD1,
-              TXD2, TXD3, TXD4, UART10, UART11, UART12, UART13, UART6, UART7,
-              UART8, UART9, VB, VGAHS, VGAVS, WDTRST1, WDTRST2, WDTRST3,
-              WDTRST4, ]
+              SALT6, SALT7, SALT8, SALT9, SD1, SD2, SGPM1, SGPS1, SIOONCTRL,
+              SIOPBI, SIOPBO, SIOPWREQ, SIOPWRGD, SIOS3, SIOS5, SIOSCI, SPI1,
+              SPI1ABR, SPI1CS1, SPI1WP, SPI2, SPI2CS1, SPI2CS2, TACH0, TACH1,
+              TACH10, TACH11, TACH12, TACH13, TACH14, TACH15, TACH2, TACH3,
+              TACH4, TACH5, TACH6, TACH7, TACH8, TACH9, THRU0, THRU1, THRU2,
+              THRU3, TXD1, TXD2, TXD3, TXD4, UART10, UART11, UART12, UART13,
+              UART6, UART7, UART8, UART9, VB, VGAHS, VGAVS, WDTRST1, WDTRST2,
+              WDTRST3, WDTRST4, ]
         groups:
           allOf:
             - $ref: "/schemas/types.yaml#/definitions/string"
             - enum: [ ADC0, ADC1, ADC10, ADC11, ADC12, ADC13, ADC14, ADC15,
-              ADC2, ADC3, ADC4, ADC5, ADC6, ADC7, ADC8, ADC9, BMCINT, ESPI,
-              ESPIALT, FSI1, FSI2, FWSPIABR, FWSPID, FWQSPID, FWSPIWP, GPIT0,
-              GPIT1, GPIT2, GPIT3, GPIT4, GPIT5, GPIT6, GPIT7, GPIU0, GPIU1,
-              GPIU2, GPIU3, GPIU4, GPIU5, GPIU6, GPIU7, HVI3C3, HVI3C4, I2C1,
-              I2C10, I2C11, I2C12, I2C13, I2C14, I2C15, I2C16, I2C2, I2C3,
-              I2C4, I2C5, I2C6, I2C7, I2C8, I2C9, I3C3, I3C4, I3C5, I3C6,
-              JTAGM, LHPD, LHSIRQ, LPC, LPCHC, LPCPD, LPCPME, LPCSMI, LSIRQ,
-              MACLINK1, MACLINK2, MACLINK3, MACLINK4, MDIO1, MDIO2, MDIO3,
-              MDIO4, NCTS1, NCTS2, NCTS3, NCTS4, NDCD1, NDCD2, NDCD3, NDCD4,
-              NDSR1, NDSR2, NDSR3, NDSR4, NDTR1, NDTR2, NDTR3, NDTR4, NRI1,
-              NRI2, NRI3, NRI4, NRTS1, NRTS2, NRTS3, NRTS4, OSCCLK, PEWAKE,
-              PWM0, PWM1, PWM10G0, PWM10G1, PWM11G0, PWM11G1, PWM12G0, PWM12G1,
-              PWM13G0, PWM13G1, PWM14G0, PWM14G1, PWM15G0, PWM15G1, PWM2, PWM3,
-              PWM4, PWM5, PWM6, PWM7, PWM8G0, PWM8G1, PWM9G0, PWM9G1, QSPI1,
-              QSPI2, RGMII1, RGMII2, RGMII3, RGMII4, RMII1, RMII2, RMII3,
-              RMII4, RXD1, RXD2, RXD3, RXD4, SALT1, SALT10G0, SALT10G1,
-              SALT11G0, SALT11G1, SALT12G0, SALT12G1, SALT13G0, SALT13G1,
-              SALT14G0, SALT14G1, SALT15G0, SALT15G1, SALT16G0, SALT16G1,
-              SALT2, SALT3, SALT4, SALT5, SALT6, SALT7, SALT8, SALT9G0,
-              SALT9G1, SD1, SD2, SD3, SD3DAT4, SD3DAT5, SD3DAT6, SD3DAT7,
-              SGPM1, SGPS1, SIOONCTRL, SIOPBI, SIOPBO, SIOPWREQ, SIOPWRGD,
-              SIOS3, SIOS5, SIOSCI, SPI1, SPI1ABR, SPI1CS1, SPI1WP, SPI2,
-              SPI2CS1, SPI2CS2, TACH0, TACH1, TACH10, TACH11, TACH12, TACH13,
-              TACH14, TACH15, TACH2, TACH3, TACH4, TACH5, TACH6, TACH7, TACH8,
-              TACH9, THRU0, THRU1, THRU2, THRU3, TXD1, TXD2, TXD3, TXD4,
-              UART10, UART11, UART12G0, UART12G1, UART13G0, UART13G1, UART6,
-              UART7, UART8, UART9, VB, VGAHS, VGAVS, WDTRST1, WDTRST2, WDTRST3,
-              WDTRST4, ]
+              ADC2, ADC3, ADC4, ADC5, ADC6, ADC7, ADC8, ADC9, BMCINT, EMMCG1,
+              EMMCG4, EMMCG8, ESPI, ESPIALT, FSI1, FSI2, FWSPIABR, FWSPID,
+              FWQSPID, FWSPIWP, GPIT0, GPIT1, GPIT2, GPIT3, GPIT4, GPIT5,
+              GPIT6, GPIT7, GPIU0, GPIU1, GPIU2, GPIU3, GPIU4, GPIU5, GPIU6,
+              GPIU7, HVI3C3, HVI3C4, I2C1, I2C10, I2C11, I2C12, I2C13, I2C14,
+              I2C15, I2C16, I2C2, I2C3, I2C4, I2C5, I2C6, I2C7, I2C8, I2C9,
+              I3C3, I3C4, I3C5, I3C6, JTAGM, LHPD, LHSIRQ, LPC, LPCHC, LPCPD,
+              LPCPME, LPCSMI, LSIRQ, MACLINK1, MACLINK2, MACLINK3, MACLINK4,
+              MDIO1, MDIO2, MDIO3, MDIO4, NCTS1, NCTS2, NCTS3, NCTS4, NDCD1,
+              NDCD2, NDCD3, NDCD4, NDSR1, NDSR2, NDSR3, NDSR4, NDTR1, NDTR2,
+              NDTR3, NDTR4, NRI1, NRI2, NRI3, NRI4, NRTS1, NRTS2, NRTS3, NRTS4,
+              OSCCLK, PEWAKE, PWM0, PWM1, PWM10G0, PWM10G1, PWM11G0, PWM11G1,
+              PWM12G0, PWM12G1, PWM13G0, PWM13G1, PWM14G0, PWM14G1, PWM15G0,
+              PWM15G1, PWM2, PWM3, PWM4, PWM5, PWM6, PWM7, PWM8G0, PWM8G1,
+              PWM9G0, PWM9G1, QSPI1, QSPI2, RGMII1, RGMII2, RGMII3, RGMII4,
+              RMII1, RMII2, RMII3, RMII4, RXD1, RXD2, RXD3, RXD4, SALT1,
+              SALT10G0, SALT10G1, SALT11G0, SALT11G1, SALT12G0, SALT12G1,
+              SALT13G0, SALT13G1, SALT14G0, SALT14G1, SALT15G0, SALT15G1,
+              SALT16G0, SALT16G1, SALT2, SALT3, SALT4, SALT5, SALT6, SALT7,
+              SALT8, SALT9G0, SALT9G1, SD1, SD2, SD3, SGPM1, SGPS1, SIOONCTRL,
+              SIOPBI, SIOPBO, SIOPWREQ, SIOPWRGD, SIOS3, SIOS5, SIOSCI, SPI1,
+              SPI1ABR, SPI1CS1, SPI1WP, SPI2, SPI2CS1, SPI2CS2, TACH0, TACH1,
+              TACH10, TACH11, TACH12, TACH13, TACH14, TACH15, TACH2, TACH3,
+              TACH4, TACH5, TACH6, TACH7, TACH8, TACH9, THRU0, THRU1, THRU2,
+              THRU3, TXD1, TXD2, TXD3, TXD4, UART10, UART11, UART12G0,
+              UART12G1, UART13G0, UART13G1, UART6, UART7, UART8, UART9, VB,
+              VGAHS, VGAVS, WDTRST1, WDTRST2, WDTRST3, WDTRST4, ]
 
 required:
   - compatible
index a78150c47aa2a67b8759c7a7c450e9edd20a375b..f3241696819722e3ea0d2b68799f589803f66d4b 100644 (file)
@@ -30,8 +30,8 @@ if:
 properties:
   compatible:
     enum:
-      - const: regulator-fixed
-      - const: regulator-fixed-clock
+      - regulator-fixed
+      - regulator-fixed-clock
 
   regulator-name: true
 
index b261a3015f84f3c7982397123d908beabe45e9cd..04819ad379c2d1d7bd1d91445c575455f8bb4b84 100644 (file)
@@ -24,15 +24,17 @@ description: |
 
 properties:
   compatible:
-    items:
-      - enum:
-          - sifive,rocket0
-          - sifive,e5
-          - sifive,e51
-          - sifive,u54-mc
-          - sifive,u54
-          - sifive,u5
-      - const: riscv
+    oneOf:
+      - items:
+          - enum:
+              - sifive,rocket0
+              - sifive,e5
+              - sifive,e51
+              - sifive,u54-mc
+              - sifive,u54
+              - sifive,u5
+          - const: riscv
+      - const: riscv    # Simulator only
     description:
       Identifies that the hart uses the RISC-V instruction set
       and identifies the type of the hart.
@@ -66,12 +68,8 @@ properties:
       insensitive, letters in the riscv,isa string must be all
       lowercase to simplify parsing.
 
-  timebase-frequency:
-    type: integer
-    minimum: 1
-    description:
-      Specifies the clock frequency of the system timer in Hz.
-      This value is common to all harts on a single system image.
+  # RISC-V requires 'timebase-frequency' in /cpus, so disallow it here
+  timebase-frequency: false
 
   interrupt-controller:
     type: object
@@ -93,7 +91,6 @@ properties:
 
 required:
   - riscv,isa
-  - timebase-frequency
   - interrupt-controller
 
 examples:
index 5b9eaf23558ee7236ff3b1c93086e06e316a9178..0efede580039cdcbb074983521731f59d3a7b946 100644 (file)
@@ -82,12 +82,21 @@ AMDGPU XGMI Support
 AMDGPU RAS Support
 ==================
 
+The AMDGPU RAS interfaces are exposed via sysfs (for informational queries) and
+debugfs (for error injection).
+
 RAS debugfs/sysfs Control and Error Injection Interfaces
 --------------------------------------------------------
 
 .. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
    :doc: AMDGPU RAS debugfs control interface
 
+RAS Reboot Behavior for Unrecoverable Errors
+--------------------------------------------------------
+
+.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+   :doc: AMDGPU RAS Reboot Behavior for Unrecoverable Errors
+
 RAS Error Count sysfs Interface
 -------------------------------
 
@@ -109,6 +118,32 @@ RAS VRAM Bad Pages sysfs Interface
 .. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
    :internal:
 
+Sample Code
+-----------
+Sample code for testing error injection can be found here:
+https://cgit.freedesktop.org/mesa/drm/tree/tests/amdgpu/ras_tests.c
+
+This is part of the libdrm amdgpu unit tests which cover several areas of the GPU.
+There are four sets of tests:
+
+RAS Basic Test
+
+The test verifies the RAS feature enabled status and makes sure the necessary sysfs and debugfs files
+are present.
+
+RAS Query Test
+
+This test checks the RAS availability and enablement status for each supported IP block as well as
+the error counts.
+
+RAS Inject Test
+
+This test injects errors for each IP.
+
+RAS Disable Test
+
+This test tests disabling of RAS features for each IP block.
+
 
 GPU Power/Thermal Controls and Monitoring
 =========================================
index 2b9f4887beda8970e18d7f93feef61504307668a..caf023cc88dead5ccf6a4f9bb4d95a4e6eb5296f 100644 (file)
@@ -1,8 +1,8 @@
 .. SPDX-License-Identifier: GPL-2.0+
 
-==============================================================
-Linux* Base Driver for the Intel(R) PRO/100 Family of Adapters
-==============================================================
+=============================================================
+Linux Base Driver for the Intel(R) PRO/100 Family of Adapters
+=============================================================
 
 June 1, 2018
 
@@ -21,7 +21,7 @@ Contents
 In This Release
 ===============
 
-This file describes the Linux* Base Driver for the Intel(R) PRO/100 Family of
+This file describes the Linux Base Driver for the Intel(R) PRO/100 Family of
 Adapters. This driver includes support for Itanium(R)2-based systems.
 
 For questions related to hardware requirements, refer to the documentation
@@ -138,9 +138,9 @@ version 1.6 or later is required for this functionality.
 The latest release of ethtool can be found from
 https://www.kernel.org/pub/software/network/ethtool/
 
-Enabling Wake on LAN* (WoL)
----------------------------
-WoL is provided through the ethtool* utility.  For instructions on
+Enabling Wake on LAN (WoL)
+--------------------------
+WoL is provided through the ethtool utility.  For instructions on
 enabling WoL with ethtool, refer to the ethtool man page.  WoL will be
 enabled on the system during the next shut down or reboot.  For this
 driver version, in order to enable WoL, the e100 driver must be loaded
index 956560b6e745ce6f45130fd24cbd0593f946c327..4aaae0f7d6ba7fb3b5290a05599605bff586193a 100644 (file)
@@ -1,8 +1,8 @@
 .. SPDX-License-Identifier: GPL-2.0+
 
-===========================================================
-Linux* Base Driver for Intel(R) Ethernet Network Connection
-===========================================================
+==========================================================
+Linux Base Driver for Intel(R) Ethernet Network Connection
+==========================================================
 
 Intel Gigabit Linux driver.
 Copyright(c) 1999 - 2013 Intel Corporation.
@@ -438,10 +438,10 @@ ethtool
   The latest release of ethtool can be found from
   https://www.kernel.org/pub/software/network/ethtool/
 
-Enabling Wake on LAN* (WoL)
----------------------------
+Enabling Wake on LAN (WoL)
+--------------------------
 
-  WoL is configured through the ethtool* utility.
+  WoL is configured through the ethtool utility.
 
   WoL will be enabled on the system during the next shut down or reboot.
   For this driver version, in order to enable WoL, the e1000 driver must be
index 01999f05509c425010b5c944d4ac2932da00ad5a..f49cd370e7bf622d3c8bae7a56a86f4360499400 100644 (file)
@@ -1,8 +1,8 @@
 .. SPDX-License-Identifier: GPL-2.0+
 
-======================================================
-Linux* Driver for Intel(R) Ethernet Network Connection
-======================================================
+=====================================================
+Linux Driver for Intel(R) Ethernet Network Connection
+=====================================================
 
 Intel Gigabit Linux driver.
 Copyright(c) 2008-2018 Intel Corporation.
@@ -338,7 +338,7 @@ and higher cannot be forced. Use the autonegotiation advertising setting to
 manually set devices for 1 Gbps and higher.
 
 Speed, duplex, and autonegotiation advertising are configured through the
-ethtool* utility.
+ethtool utility.
 
 Caution: Only experienced network administrators should force speed and duplex
 or change autonegotiation advertising manually. The settings at the switch must
@@ -351,9 +351,9 @@ will not attempt to auto-negotiate with its link partner since those adapters
 operate only in full duplex and only at their native speed.
 
 
-Enabling Wake on LAN* (WoL)
----------------------------
-WoL is configured through the ethtool* utility.
+Enabling Wake on LAN (WoL)
+--------------------------
+WoL is configured through the ethtool utility.
 
 WoL will be enabled on the system during the next shut down or reboot. For
 this driver version, in order to enable WoL, the e1000e driver must be loaded
index ac3269e34f552206f206a31231e8338f5426f60d..4d279e64e221e6475b291e98c7fde7a3a882caaf 100644 (file)
@@ -1,8 +1,8 @@
 .. SPDX-License-Identifier: GPL-2.0+
 
-==============================================================
-Linux* Base Driver for Intel(R) Ethernet Multi-host Controller
-==============================================================
+=============================================================
+Linux Base Driver for Intel(R) Ethernet Multi-host Controller
+=============================================================
 
 August 20, 2018
 Copyright(c) 2015-2018 Intel Corporation.
@@ -120,8 +120,8 @@ rx-flow-hash tcp4|udp4|ah4|esp4|sctp4|tcp6|udp6|ah6|esp6|sctp6 m|v|t|s|d|f|n|r
 Known Issues/Troubleshooting
 ============================
 
-Enabling SR-IOV in a 64-bit Microsoft* Windows Server* 2012/R2 guest OS under Linux KVM
----------------------------------------------------------------------------------------
+Enabling SR-IOV in a 64-bit Microsoft Windows Server 2012/R2 guest OS under Linux KVM
+-------------------------------------------------------------------------------------
 KVM Hypervisor/VMM supports direct assignment of a PCIe device to a VM. This
 includes traditional PCIe devices, as well as SR-IOV-capable devices based on
 the Intel Ethernet Controller XL710.
index 848fd388fa6e01403f7d1f67d2256463f4ebe228..8a9b18573688d87c9fc521d00b129bd7ae7c61b7 100644 (file)
@@ -1,8 +1,8 @@
 .. SPDX-License-Identifier: GPL-2.0+
 
-==================================================================
-Linux* Base Driver for the Intel(R) Ethernet Controller 700 Series
-==================================================================
+=================================================================
+Linux Base Driver for the Intel(R) Ethernet Controller 700 Series
+=================================================================
 
 Intel 40 Gigabit Linux driver.
 Copyright(c) 1999-2018 Intel Corporation.
@@ -384,7 +384,7 @@ NOTE: You cannot set the speed for devices based on the Intel(R) Ethernet
 Network Adapter XXV710 based devices.
 
 Speed, duplex, and autonegotiation advertising are configured through the
-ethtool* utility.
+ethtool utility.
 
 Caution: Only experienced network administrators should force speed and duplex
 or change autonegotiation advertising manually. The settings at the switch must
index cfc08842e32c6e4c00839c13a2861c5e32bb890d..84ac7e75f36313a5343709f65b1bc9bcef8fdc19 100644 (file)
@@ -1,8 +1,8 @@
 .. SPDX-License-Identifier: GPL-2.0+
 
-==================================================================
-Linux* Base Driver for Intel(R) Ethernet Adaptive Virtual Function
-==================================================================
+=================================================================
+Linux Base Driver for Intel(R) Ethernet Adaptive Virtual Function
+=================================================================
 
 Intel Ethernet Adaptive Virtual Function Linux driver.
 Copyright(c) 2013-2018 Intel Corporation.
@@ -19,7 +19,7 @@ Contents
 Overview
 ========
 
-This file describes the iavf Linux* Base Driver. This driver was formerly
+This file describes the iavf Linux Base Driver. This driver was formerly
 called i40evf.
 
 The iavf driver supports the below mentioned virtual function devices and
index c220aa2711c67c3983ae1090a54973868837b95a..ee43ea57d4430ca78b98efa2e7807a3ec4dbaa42 100644 (file)
@@ -1,8 +1,8 @@
 .. SPDX-License-Identifier: GPL-2.0+
 
-===================================================================
-Linux* Base Driver for the Intel(R) Ethernet Connection E800 Series
-===================================================================
+==================================================================
+Linux Base Driver for the Intel(R) Ethernet Connection E800 Series
+==================================================================
 
 Intel ice Linux driver.
 Copyright(c) 2018 Intel Corporation.
index fc8cfaa5dcfaca38d70b31f2a0e1df8134d380a7..87e560fe5eaaba65bfe1840504129afb533671ae 100644 (file)
@@ -1,8 +1,8 @@
 .. SPDX-License-Identifier: GPL-2.0+
 
-===========================================================
-Linux* Base Driver for Intel(R) Ethernet Network Connection
-===========================================================
+==========================================================
+Linux Base Driver for Intel(R) Ethernet Network Connection
+==========================================================
 
 Intel Gigabit Linux driver.
 Copyright(c) 1999-2018 Intel Corporation.
@@ -129,9 +129,9 @@ version is required for this functionality. Download it at:
 https://www.kernel.org/pub/software/network/ethtool/
 
 
-Enabling Wake on LAN* (WoL)
----------------------------
-WoL is configured through the ethtool* utility.
+Enabling Wake on LAN (WoL)
+--------------------------
+WoL is configured through the ethtool utility.
 
 WoL will be enabled on the system during the next shut down or reboot. For
 this driver version, in order to enable WoL, the igb driver must be loaded
index 9cddabe8108ead0e2bcd93d71626ba8214244f8a..557fc020ef31e0f3c403bd38dedb75c0582d2fe5 100644 (file)
@@ -1,8 +1,8 @@
 .. SPDX-License-Identifier: GPL-2.0+
 
-============================================================
-Linux* Base Virtual Function Driver for Intel(R) 1G Ethernet
-============================================================
+===========================================================
+Linux Base Virtual Function Driver for Intel(R) 1G Ethernet
+===========================================================
 
 Intel Gigabit Virtual Function Linux driver.
 Copyright(c) 1999-2018 Intel Corporation.
index c7d25483fedb20c049c645835ec13ad7600acfce..f1d5233e5e510929ba6d3f4f8cd049dc8767677c 100644 (file)
@@ -1,8 +1,8 @@
 .. SPDX-License-Identifier: GPL-2.0+
 
-=============================================================================
-Linux* Base Driver for the Intel(R) Ethernet 10 Gigabit PCI Express Adapters
-=============================================================================
+===========================================================================
+Linux Base Driver for the Intel(R) Ethernet 10 Gigabit PCI Express Adapters
+===========================================================================
 
 Intel 10 Gigabit Linux driver.
 Copyright(c) 1999-2018 Intel Corporation.
@@ -519,8 +519,8 @@ The offload is also supported for ixgbe's VFs, but the VF must be set as
 Known Issues/Troubleshooting
 ============================
 
-Enabling SR-IOV in a 64-bit Microsoft* Windows Server* 2012/R2 guest OS
------------------------------------------------------------------------
+Enabling SR-IOV in a 64-bit Microsoft Windows Server 2012/R2 guest OS
+---------------------------------------------------------------------
 Linux KVM Hypervisor/VMM supports direct assignment of a PCIe device to a VM.
 This includes traditional PCIe devices, as well as SR-IOV-capable devices based
 on the Intel Ethernet Controller XL710.
index 5d4977360157ed87b87b001c74bbe314c9fbe0d5..76bbde736f21546071167609294a83a91a2307fd 100644 (file)
@@ -1,8 +1,8 @@
 .. SPDX-License-Identifier: GPL-2.0+
 
-=============================================================
-Linux* Base Virtual Function Driver for Intel(R) 10G Ethernet
-=============================================================
+============================================================
+Linux Base Virtual Function Driver for Intel(R) 10G Ethernet
+============================================================
 
 Intel 10 Gigabit Virtual Function Linux driver.
 Copyright(c) 1999-2018 Intel Corporation.
index 13935896bee635d093272c66f230f54c3f350191..c17d680cf334aeebcb7aa905b01151b99e2a68f9 100644 (file)
@@ -1,8 +1,8 @@
 .. SPDX-License-Identifier: GPL-2.0+
 
-==========================================================
-Linux* Driver for the Pensando(R) Ethernet adapter family
-==========================================================
+========================================================
+Linux Driver for the Pensando(R) Ethernet adapter family
+========================================================
 
 Pensando Linux Ethernet driver.
 Copyright(c) 2019 Pensando Systems, Inc
index 49e95f438ed7571a93bceffdc17846c35dd64fca..8d4ad1d1ae26f11ffe0ff1db61c61f20b573b8b8 100644 (file)
@@ -207,8 +207,8 @@ TCP variables:
 
 somaxconn - INTEGER
        Limit of socket listen() backlog, known in userspace as SOMAXCONN.
-       Defaults to 128.  See also tcp_max_syn_backlog for additional tuning
-       for TCP sockets.
+       Defaults to 4096. (Was 128 before linux-5.4)
+       See also tcp_max_syn_backlog for additional tuning for TCP sockets.
 
 tcp_abort_on_overflow - BOOLEAN
        If listening service is too slow to accept new connections,
@@ -408,11 +408,14 @@ tcp_max_orphans - INTEGER
        up to ~64K of unswappable memory.
 
 tcp_max_syn_backlog - INTEGER
-       Maximal number of remembered connection requests, which have not
-       received an acknowledgment from connecting client.
+       Maximal number of remembered connection requests (SYN_RECV),
+       which have not received an acknowledgment from connecting client.
+       This is a per-listener limit.
        The minimal value is 128 for low memory machines, and it will
        increase in proportion to the memory of machine.
        If server suffers from overload, try increasing this number.
+       Remember to also check /proc/sys/net/core/somaxconn
+       A SYN_RECV request socket consumes about 304 bytes of memory.
 
 tcp_max_tw_buckets - INTEGER
        Maximal number of timewait sockets held by system simultaneously.
index 0dd3f748239f2858f49ec24590433ea3c8843230..f914e81fd3a64e518fecb0595c138bd87dca0d58 100644 (file)
@@ -436,6 +436,10 @@ by the driver:
    encryption.
  * ``tx_tls_ooo`` - number of TX packets which were part of a TLS stream
    but did not arrive in the expected order.
+ * ``tx_tls_skip_no_sync_data`` - number of TX packets which were part of
+   a TLS stream and arrived out-of-order, but skipped the HW offload routine
+   and went to the regular transmit flow as they were retransmissions of the
+   connection handshake.
  * ``tx_tls_drop_no_sync_data`` - number of TX packets which were part of
    a TLS stream dropped, because they arrived out of order and associated
    record could not be found.
index b63c291ad0296a0fbfdd2ca54a4ad8f65da56713..741e3f433f6e4072d5122de5227e19709a4064d3 100644 (file)
@@ -2326,11 +2326,13 @@ F:      drivers/edac/altera_edac.
 
 ARM/SPREADTRUM SoC SUPPORT
 M:     Orson Zhai <orsonzhai@gmail.com>
-M:     Baolin Wang <baolin.wang@linaro.org>
+M:     Baolin Wang <baolin.wang7@gmail.com>
 M:     Chunyan Zhang <zhang.lyra@gmail.com>
 S:     Maintained
 F:     arch/arm64/boot/dts/sprd
 N:     sprd
+N:     sc27xx
+N:     sc2731
 
 ARM/STI ARCHITECTURE
 M:     Patrice Chotard <patrice.chotard@st.com>
@@ -3054,6 +3056,7 @@ M:        Daniel Borkmann <daniel@iogearbox.net>
 R:     Martin KaFai Lau <kafai@fb.com>
 R:     Song Liu <songliubraving@fb.com>
 R:     Yonghong Song <yhs@fb.com>
+R:     Andrii Nakryiko <andriin@fb.com>
 L:     netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf.git
@@ -3099,7 +3102,7 @@ S:        Supported
 F:     arch/arm64/net/
 
 BPF JIT for MIPS (32-BIT AND 64-BIT)
-M:     Paul Burton <paul.burton@mips.com>
+M:     Paul Burton <paulburton@kernel.org>
 L:     netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
 S:     Maintained
@@ -3186,7 +3189,7 @@ N:        bcm216*
 N:     kona
 F:     arch/arm/mach-bcm/
 
-BROADCOM BCM2835 ARM ARCHITECTURE
+BROADCOM BCM2711/BCM2835 ARM ARCHITECTURE
 M:     Eric Anholt <eric@anholt.net>
 M:     Stefan Wahren <wahrenst@gmx.net>
 L:     bcm-kernel-feedback-list@broadcom.com
@@ -3194,6 +3197,7 @@ L:        linux-rpi-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 T:     git git://github.com/anholt/linux
 S:     Maintained
+N:     bcm2711
 N:     bcm2835
 F:     drivers/staging/vc04_services
 
@@ -3240,8 +3244,6 @@ S:        Maintained
 F:     drivers/usb/gadget/udc/bcm63xx_udc.*
 
 BROADCOM BCM7XXX ARM ARCHITECTURE
-M:     Brian Norris <computersforpeace@gmail.com>
-M:     Gregory Fong <gregory.0xf0@gmail.com>
 M:     Florian Fainelli <f.fainelli@gmail.com>
 M:     bcm-kernel-feedback-list@broadcom.com
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -3739,7 +3741,6 @@ F:        drivers/crypto/cavium/cpt/
 
 CAVIUM THUNDERX2 ARM64 SOC
 M:     Robert Richter <rrichter@cavium.com>
-M:     Jayachandran C <jnair@caviumnetworks.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm64/boot/dts/cavium/thunder2-99xx*
@@ -8014,7 +8015,7 @@ S:        Maintained
 F:     drivers/usb/atm/ueagle-atm.c
 
 IMGTEC ASCII LCD DRIVER
-M:     Paul Burton <paul.burton@mips.com>
+M:     Paul Burton <paulburton@kernel.org>
 S:     Maintained
 F:     Documentation/devicetree/bindings/auxdisplay/img-ascii-lcd.txt
 F:     drivers/auxdisplay/img-ascii-lcd.c
@@ -10531,8 +10532,12 @@ F:     mm/memblock.c
 F:     Documentation/core-api/boot-time-mm.rst
 
 MEMORY MANAGEMENT
+M:     Andrew Morton <akpm@linux-foundation.org>
 L:     linux-mm@kvack.org
 W:     http://www.linux-mm.org
+T:     quilt https://ozlabs.org/~akpm/mmotm/
+T:     quilt https://ozlabs.org/~akpm/mmots/
+T:     git git://github.com/hnaz/linux-mm.git
 S:     Maintained
 F:     include/linux/mm.h
 F:     include/linux/gfp.h
@@ -10841,7 +10846,7 @@ F:      drivers/usb/image/microtek.*
 
 MIPS
 M:     Ralf Baechle <ralf@linux-mips.org>
-M:     Paul Burton <paul.burton@mips.com>
+M:     Paul Burton <paulburton@kernel.org>
 M:     James Hogan <jhogan@kernel.org>
 L:     linux-mips@vger.kernel.org
 W:     http://www.linux-mips.org/
@@ -10855,7 +10860,7 @@ F:      arch/mips/
 F:     drivers/platform/mips/
 
 MIPS BOSTON DEVELOPMENT BOARD
-M:     Paul Burton <paul.burton@mips.com>
+M:     Paul Burton <paulburton@kernel.org>
 L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/clock/img,boston-clock.txt
@@ -10865,7 +10870,7 @@ F:      drivers/clk/imgtec/clk-boston.c
 F:     include/dt-bindings/clock/boston-clock.h
 
 MIPS GENERIC PLATFORM
-M:     Paul Burton <paul.burton@mips.com>
+M:     Paul Burton <paulburton@kernel.org>
 L:     linux-mips@vger.kernel.org
 S:     Supported
 F:     Documentation/devicetree/bindings/power/mti,mips-cpc.txt
@@ -11420,7 +11425,6 @@ F:      include/trace/events/tcp.h
 NETWORKING [TLS]
 M:     Boris Pismenny <borisp@mellanox.com>
 M:     Aviad Yehezkel <aviadye@mellanox.com>
-M:     Dave Watson <davejwatson@fb.com>
 M:     John Fastabend <john.fastabend@gmail.com>
 M:     Daniel Borkmann <daniel@iogearbox.net>
 M:     Jakub Kicinski <jakub.kicinski@netronome.com>
@@ -13918,7 +13922,7 @@ F:      drivers/mtd/nand/raw/r852.h
 
 RISC-V ARCHITECTURE
 M:     Paul Walmsley <paul.walmsley@sifive.com>
-M:     Palmer Dabbelt <palmer@sifive.com>
+M:     Palmer Dabbelt <palmer@dabbelt.com>
 M:     Albert Ou <aou@eecs.berkeley.edu>
 L:     linux-riscv@lists.infradead.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux.git
@@ -14795,7 +14799,7 @@ F:      drivers/media/usb/siano/
 F:     drivers/media/mmc/siano/
 
 SIFIVE DRIVERS
-M:     Palmer Dabbelt <palmer@sifive.com>
+M:     Palmer Dabbelt <palmer@dabbelt.com>
 M:     Paul Walmsley <paul.walmsley@sifive.com>
 L:     linux-riscv@lists.infradead.org
 T:     git git://github.com/sifive/riscv-linux.git
@@ -14805,7 +14809,7 @@ N:      sifive
 
 SIFIVE FU540 SYSTEM-ON-CHIP
 M:     Paul Walmsley <paul.walmsley@sifive.com>
-M:     Palmer Dabbelt <palmer@sifive.com>
+M:     Palmer Dabbelt <palmer@dabbelt.com>
 L:     linux-riscv@lists.infradead.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/pjw/sifive.git
 S:     Supported
@@ -17347,6 +17351,12 @@ F:     include/linux/vbox_utils.h
 F:     include/uapi/linux/vbox*.h
 F:     drivers/virt/vboxguest/
 
+VIRTUAL BOX SHARED FOLDER VFS DRIVER:
+M:     Hans de Goede <hdegoede@redhat.com>
+L:     linux-fsdevel@vger.kernel.org
+S:     Maintained
+F:     drivers/staging/vboxsf/*
+
 VIRTUAL SERIO DEVICE DRIVER
 M:     Stephen Chandler Paul <thatslyude@gmail.com>
 S:     Maintained
@@ -18047,6 +18057,7 @@ F:      Documentation/vm/zsmalloc.rst
 ZSWAP COMPRESSED SWAP CACHING
 M:     Seth Jennings <sjenning@redhat.com>
 M:     Dan Streetman <ddstreet@ieee.org>
+M:     Vitaly Wool <vitaly.wool@konsulko.com>
 L:     linux-mm@kvack.org
 S:     Maintained
 F:     mm/zswap.c
index 5475cdb6d57d41171018846f49f89363b694fa84..1d5298356ea8c75ce4441de8c373555ceea93b46 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,8 +2,8 @@
 VERSION = 5
 PATCHLEVEL = 4
 SUBLEVEL = 0
-EXTRAVERSION = -rc4
-NAME = Nesting Opossum
+EXTRAVERSION = -rc7
+NAME = Kleptomaniac Octopus
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
index bfc7f5f5d6f26907121ddc20c4782a5d73f50265..9acbeba832c0b532ca1c4a2623f215335edcd481 100644 (file)
                clock-frequency = <33333333>;
        };
 
+       reg_5v0: regulator-5v0 {
+               compatible = "regulator-fixed";
+
+               regulator-name = "5v0-supply";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+       };
+
        cpu_intc: cpu-interrupt-controller {
                compatible = "snps,archs-intc";
                interrupt-controller;
                        clocks = <&input_clk>;
                        cs-gpios = <&creg_gpio 0 GPIO_ACTIVE_LOW>,
                                   <&creg_gpio 1 GPIO_ACTIVE_LOW>;
+
+                       spi-flash@0 {
+                               compatible = "sst26wf016b", "jedec,spi-nor";
+                               reg = <0>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               spi-max-frequency = <4000000>;
+                       };
+
+                       adc@1 {
+                               compatible = "ti,adc108s102";
+                               reg = <1>;
+                               vref-supply = <&reg_5v0>;
+                               spi-max-frequency = <1000000>;
+                       };
                };
 
                creg_gpio: gpio@14b0 {
index 9b9a74444ce27455dd5f403e476de3b78d771a23..0974226fab550ff384d59c8514fcb79139e7c1d4 100644 (file)
@@ -32,6 +32,8 @@ CONFIG_INET=y
 CONFIG_DEVTMPFS=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_MTD=y
+CONFIG_MTD_SPI_NOR=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_NETDEVICES=y
@@ -55,6 +57,8 @@ CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_DWAPB=y
 CONFIG_GPIO_SNPS_CREG=y
 # CONFIG_HWMON is not set
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_DRM=y
 # CONFIG_DRM_FBDEV_EMULATION is not set
 CONFIG_DRM_UDL=y
@@ -72,6 +76,8 @@ CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_DW=y
 CONFIG_DMADEVICES=y
 CONFIG_DW_AXI_DMAC=y
+CONFIG_IIO=y
+CONFIG_TI_ADC108S102=y
 CONFIG_EXT3_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
index 861a8aea51f9fe0c086665dd84677f7ee80ea838..661fd842ea97db7ad4f3871b2a1038d715a44130 100644 (file)
@@ -614,8 +614,8 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
        /* loop thru all available h/w condition indexes */
        for (i = 0; i < cc_bcr.c; i++) {
                write_aux_reg(ARC_REG_CC_INDEX, i);
-               cc_name.indiv.word0 = read_aux_reg(ARC_REG_CC_NAME0);
-               cc_name.indiv.word1 = read_aux_reg(ARC_REG_CC_NAME1);
+               cc_name.indiv.word0 = le32_to_cpu(read_aux_reg(ARC_REG_CC_NAME0));
+               cc_name.indiv.word1 = le32_to_cpu(read_aux_reg(ARC_REG_CC_NAME1));
 
                arc_pmu_map_hw_event(i, cc_name.str);
                arc_pmu_add_raw_event_attr(i, cc_name.str);
index 883fb85135d4645ad449b4581080f1334942702f..1b4b2b0500e4c0214d8c057559dd3003bfedf13f 100644 (file)
                reg = <0x70>;
                #address-cells = <1>;
                #size-cells = <0>;
+               i2c-mux-idle-disconnect;
 
                i2c@0 {
                        /* FMC A */
                        #address-cells = <1>;
                        #size-cells = <0>;
                        reg = <0>;
-                       i2c-mux-idle-disconnect;
                };
 
                i2c@1 {
                        #address-cells = <1>;
                        #size-cells = <0>;
                        reg = <1>;
-                       i2c-mux-idle-disconnect;
                };
 
                i2c@2 {
                        #address-cells = <1>;
                        #size-cells = <0>;
                        reg = <2>;
-                       i2c-mux-idle-disconnect;
                };
 
                i2c@3 {
                        #address-cells = <1>;
                        #size-cells = <0>;
                        reg = <3>;
-                       i2c-mux-idle-disconnect;
                };
 
                i2c@4 {
                        #address-cells = <1>;
                        #size-cells = <0>;
                        reg = <4>;
-                       i2c-mux-idle-disconnect;
                };
 
                i2c@5 {
                        #address-cells = <1>;
                        #size-cells = <0>;
                        reg = <5>;
-                       i2c-mux-idle-disconnect;
 
                        ina230@40 { compatible = "ti,ina230"; reg = <0x40>; shunt-resistor = <5000>; };
                        ina230@41 { compatible = "ti,ina230"; reg = <0x41>; shunt-resistor = <5000>; };
                        #address-cells = <1>;
                        #size-cells = <0>;
                        reg = <6>;
-                       i2c-mux-idle-disconnect;
                };
 
                i2c@7 {
                        #address-cells = <1>;
                        #size-cells = <0>;
                        reg = <7>;
-                       i2c-mux-idle-disconnect;
 
                        u41: pca9575@20 {
                                compatible = "nxp,pca9575";
index 09a088f98566178bbb4d5df30f44d03ca7280357..b75af21069f95d4b2bd4187d08cb2e974cbf6e5c 100644 (file)
        #address-cells = <1>;
        #size-cells = <0>;
        pinctrl-0 = <&emmc_gpio34 &gpclk2_gpio43>;
+       bus-width = <4>;
        mmc-pwrseq = <&wifi_pwrseq>;
        non-removable;
        status = "okay";
index 7c3cb7ece6cbf87c2f2e668fb7287968f95a44ee..925cb37c22f06b4f18e73f54b28bca45338c8b51 100644 (file)
@@ -9,6 +9,14 @@
                reg = <0 0x40000000>;
        };
 
+       leds {
+               /*
+                * Since there is no upstream GPIO driver yet,
+                * remove the incomplete node.
+                */
+               /delete-node/ act;
+       };
+
        reg_3v3: fixed-regulator {
                compatible = "regulator-fixed";
                regulator-name = "3V3";
index 2a6ce87071f9eec7709de4f39b3d571dc6201edf..9e027b9a5f91f76c1de66fc2638a3abbdb49f029 100644 (file)
        pinctrl-0 = <&pinctrl_pwm3>;
 };
 
+&snvs_pwrkey {
+       status = "okay";
+};
+
 &ssi2 {
        status = "okay";
 };
index 7ceae357324860c9ff79bf41c5deb34d6fff3cc1..547fb141ec0c9f4f2aace5f2095bfbd2d921d2dd 100644 (file)
        vin-supply = <&sw1c_reg>;
 };
 
+&snvs_poweroff {
+       status = "okay";
+};
+
 &iomuxc {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_hog>;
index f3404dd1053779c131486166619ee788f1c2e1e0..cf628465cd0a39b55376dadee7a7d6c72c80d296 100644 (file)
                        accelerometer@1c {
                                compatible = "fsl,mma8451";
                                reg = <0x1c>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_mma8451_int>;
                                interrupt-parent = <&gpio6>;
                                interrupts = <31 IRQ_TYPE_LEVEL_LOW>;
                        };
                        >;
                };
 
+               pinctrl_mma8451_int: mma8451intgrp {
+                       fsl,pins = <
+                               MX6QDL_PAD_EIM_BCLK__GPIO6_IO31         0xb0b1
+                       >;
+               };
+
                pinctrl_pwm3: pwm1grp {
                        fsl,pins = <
                                MX6QDL_PAD_SD4_DAT1__PWM3_OUT           0x1b0b1
index 710f850e785c6cbb465faa1697e15a52de378171..e2e604d6ba0b452d328a9488e956fffddd543c01 100644 (file)
                                compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt";
                                reg = <0x302d0000 0x10000>;
                                interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks IMX7D_CLK_DUMMY>,
+                               clocks = <&clks IMX7D_GPT1_ROOT_CLK>,
                                         <&clks IMX7D_GPT1_ROOT_CLK>;
                                clock-names = "ipg", "per";
                        };
                                compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt";
                                reg = <0x302e0000 0x10000>;
                                interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks IMX7D_CLK_DUMMY>,
+                               clocks = <&clks IMX7D_GPT2_ROOT_CLK>,
                                         <&clks IMX7D_GPT2_ROOT_CLK>;
                                clock-names = "ipg", "per";
                                status = "disabled";
                                compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt";
                                reg = <0x302f0000 0x10000>;
                                interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks IMX7D_CLK_DUMMY>,
+                               clocks = <&clks IMX7D_GPT3_ROOT_CLK>,
                                         <&clks IMX7D_GPT3_ROOT_CLK>;
                                clock-names = "ipg", "per";
                                status = "disabled";
                                compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt";
                                reg = <0x30300000 0x10000>;
                                interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks IMX7D_CLK_DUMMY>,
+                               clocks = <&clks IMX7D_GPT4_ROOT_CLK>,
                                         <&clks IMX7D_GPT4_ROOT_CLK>;
                                clock-names = "ipg", "per";
                                status = "disabled";
index 3fdd0a72f87f795b43d049a262ae5e3d7df2b967..506b118e511a6705007b4fe3decdcb8656eb65f2 100644 (file)
 &twl_gpio {
        ti,use-leds;
 };
+
+&twl_keypad {
+       status = "disabled";
+};
index 4454449de00c0a784ad2b1a55e5238408ed32902..a40fe8d49da6469a573b43d1b0fa8e7d3ae08ada 100644 (file)
                compatible = "ti,wl1285", "ti,wl1283";
                reg = <2>;
                /* gpio_100 with gpmc_wait2 pad as wakeirq */
-               interrupts-extended = <&gpio4 4 IRQ_TYPE_EDGE_RISING>,
+               interrupts-extended = <&gpio4 4 IRQ_TYPE_LEVEL_HIGH>,
                                      <&omap4_pmx_core 0x4e>;
                interrupt-names = "irq", "wakeup";
                ref-clock-frequency = <26000000>;
index 14be2ecb62b1f311aba87ad3e2dfd2b1b39ab834..55ea8b6189af56aa6956fc24306b90339a2fcb9a 100644 (file)
                compatible = "ti,wl1271";
                reg = <2>;
                /* gpio_53 with gpmc_ncs3 pad as wakeup */
-               interrupts-extended = <&gpio2 21 IRQ_TYPE_EDGE_RISING>,
+               interrupts-extended = <&gpio2 21 IRQ_TYPE_LEVEL_HIGH>,
                                      <&omap4_pmx_core 0x3a>;
                interrupt-names = "irq", "wakeup";
                ref-clock-frequency = <38400000>;
index 3c274965ff40a24ab6aa3439c6b7f344b6d37757..91480ac1f32867bda4a26f0f61d81fe36b5ff29f 100644 (file)
                compatible = "ti,wl1281";
                reg = <2>;
                interrupt-parent = <&gpio1>;
-               interrupts = <21 IRQ_TYPE_EDGE_RISING>; /* gpio 53 */
+               interrupts = <21 IRQ_TYPE_LEVEL_HIGH>; /* gpio 53 */
                ref-clock-frequency = <26000000>;
                tcxo-clock-frequency = <26000000>;
        };
index 6dbbc9b3229cc0eec363a96754cddf371638138c..d0032213101e652dd4b7ce54615178ce5bf44e98 100644 (file)
@@ -69,7 +69,7 @@
                compatible = "ti,wl1271";
                reg = <2>;
                interrupt-parent = <&gpio2>;
-               interrupts = <9 IRQ_TYPE_EDGE_RISING>; /* gpio 41 */
+               interrupts = <9 IRQ_TYPE_LEVEL_HIGH>; /* gpio 41 */
                ref-clock-frequency = <38400000>;
        };
 };
index 7fff555ee39435435ed1f023648b8b36a6af4dd1..68ac04641bdb10ef8a5af855cba5234fecb33a7c 100644 (file)
                pinctrl-names = "default";
                pinctrl-0 = <&wlcore_irq_pin>;
                interrupt-parent = <&gpio1>;
-               interrupts = <14 IRQ_TYPE_EDGE_RISING>; /* gpio 14 */
+               interrupts = <14 IRQ_TYPE_LEVEL_HIGH>;  /* gpio 14 */
                ref-clock-frequency = <26000000>;
        };
 };
index fac2e57dcca905e6dd8af4bebcb57d89aa727805..4791834dacb2ef1814c195a85912941d8a28123e 100644 (file)
                };
        };
 
-       gpu_cm: clock-controller@1500 {
+       gpu_cm: gpu_cm@1500 {
                compatible = "ti,omap4-cm";
                reg = <0x1500 0x100>;
                #address-cells = <1>;
index e4a0d51ec3a8cde7003099dcc29f008f82704e74..0a3a7d66737b60dd4f3ff991e5ffc68629660e4b 100644 (file)
                                                 <STM32_PINMUX('F', 6, AF9)>; /* QSPI_BK1_IO3 */
                                        bias-disable;
                                        drive-push-pull;
-                                       slew-rate = <3>;
+                                       slew-rate = <1>;
                                };
                                pins2 {
                                        pinmux = <STM32_PINMUX('B', 6, AF10)>; /* QSPI_BK1_NCS */
                                        bias-pull-up;
                                        drive-push-pull;
-                                       slew-rate = <3>;
+                                       slew-rate = <1>;
                                };
                        };
 
                                                 <STM32_PINMUX('G', 7, AF11)>; /* QSPI_BK2_IO3 */
                                        bias-disable;
                                        drive-push-pull;
-                                       slew-rate = <3>;
+                                       slew-rate = <1>;
                                };
                                pins2 {
                                        pinmux = <STM32_PINMUX('C', 0, AF10)>; /* QSPI_BK2_NCS */
                                        bias-pull-up;
                                        drive-push-pull;
-                                       slew-rate = <3>;
+                                       slew-rate = <1>;
                                };
                        };
 
index 89d29b50c3f46df13ba252fa914aee8de50a0dfc..91fc0a315c491ec66e3f35ab8dc53d7984584513 100644 (file)
 
        ov5640: camera@3c {
                compatible = "ovti,ov5640";
-               pinctrl-names = "default";
-               pinctrl-0 = <&ov5640_pins>;
                reg = <0x3c>;
                clocks = <&clk_ext_camera>;
                clock-names = "xclk";
                DOVDD-supply = <&v2v8>;
-               powerdown-gpios = <&stmfx_pinctrl 18 GPIO_ACTIVE_HIGH>;
-               reset-gpios = <&stmfx_pinctrl 19 GPIO_ACTIVE_LOW>;
+               powerdown-gpios = <&stmfx_pinctrl 18 (GPIO_ACTIVE_HIGH | GPIO_PUSH_PULL)>;
+               reset-gpios = <&stmfx_pinctrl 19 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>;
                rotation = <180>;
                status = "okay";
 
 
                        joystick_pins: joystick {
                                pins = "gpio0", "gpio1", "gpio2", "gpio3", "gpio4";
-                               drive-push-pull;
                                bias-pull-down;
                        };
-
-                       ov5640_pins: camera {
-                               pins = "agpio2", "agpio3"; /* stmfx pins 18 & 19 */
-                               drive-push-pull;
-                               output-low;
-                       };
                };
        };
 };
index 9b11654a0a3977e62efb6f427ee1d49eb1af5bd2..f98e0370c0bce28eb38e10b6b1cc041a37a5d5fd 100644 (file)
                        interrupt-names = "int0", "int1";
                        clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>;
                        clock-names = "hclk", "cclk";
-                       bosch,mram-cfg = <0x1400 0 0 32 0 0 2 2>;
+                       bosch,mram-cfg = <0x0 0 0 32 0 0 2 2>;
                        status = "disabled";
                };
 
                        interrupt-names = "int0", "int1";
                        clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>;
                        clock-names = "hclk", "cclk";
-                       bosch,mram-cfg = <0x0 0 0 32 0 0 2 2>;
+                       bosch,mram-cfg = <0x1400 0 0 32 0 0 2 2>;
                        status = "disabled";
                };
 
index 874231be04e4608a8e6fb337a06e3ae6719e1af3..8aebefd6accfee08a67dd7a12ecb41a7576f470d 100644 (file)
                        compatible = "allwinner,sun7i-a20-csi0";
                        reg = <0x01c09000 0x1000>;
                        interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&ccu CLK_AHB_CSI0>, <&ccu CLK_CSI0>,
-                                <&ccu CLK_CSI_SCLK>, <&ccu CLK_DRAM_CSI0>;
-                       clock-names = "bus", "mod", "isp", "ram";
+                       clocks = <&ccu CLK_AHB_CSI0>, <&ccu CLK_CSI_SCLK>, <&ccu CLK_DRAM_CSI0>;
+                       clock-names = "bus", "isp", "ram";
                        resets = <&ccu RST_CSI0>;
                        status = "disabled";
                };
index 568b90ece34273c147b9a177cf6965335ebc922f..3bec3e0a81b2c6d4b4fededfb97db8836470a091 100644 (file)
        vqmmc-supply = <&reg_dldo1>;
        non-removable;
        wakeup-source;
+       keep-power-in-suspend;
        status = "okay";
 
        brcmf: wifi@1 {
index dc8a5f37a1ef2a6029bfcbd1d77e46d4b1936a7c..c8ebb23c4e02b03c2401db216d990ec3d63dd3d7 100644 (file)
                #address-cells = <1>;
                #size-cells = <0>;
                reg = <0x70>;
+               i2c-mux-idle-disconnect;
 
                sff0_i2c: i2c@1 {
                        #address-cells = <1>;
                reg = <0x71>;
                #address-cells = <1>;
                #size-cells = <0>;
+               i2c-mux-idle-disconnect;
 
                sff5_i2c: i2c@1 {
                        #address-cells = <1>;
index 01e3c0f4be92341c4c8a9a499661b2181d902a05..231f8973bbb2d8ca242eef675b2c4fbed6ba554b 100644 (file)
@@ -167,6 +167,7 @@ CONFIG_FB=y
 CONFIG_FIRMWARE_EDID=y
 CONFIG_FB_DA8XX=y
 CONFIG_BACKLIGHT_PWM=m
+CONFIG_BACKLIGHT_GPIO=m
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 CONFIG_SOUND=m
index 9bfffbe22d53cd9732b98415477aa61bd97c430e..0f7381ee0c375ff16db8ab7efe57d12dc9b88cd7 100644 (file)
@@ -276,6 +276,7 @@ CONFIG_VIDEO_OV5640=m
 CONFIG_VIDEO_OV5645=m
 CONFIG_IMX_IPUV3_CORE=y
 CONFIG_DRM=y
+CONFIG_DRM_MSM=y
 CONFIG_DRM_PANEL_LVDS=y
 CONFIG_DRM_PANEL_SIMPLE=y
 CONFIG_DRM_PANEL_SEIKO_43WVF1G=y
index d3f50971e451a4234da97cb09bcd05cf3fad60e1..40d7f1a4fc458b5b9b777cfaee99a995f2bddfac 100644 (file)
@@ -356,15 +356,15 @@ CONFIG_DRM_OMAP_CONNECTOR_HDMI=m
 CONFIG_DRM_OMAP_CONNECTOR_ANALOG_TV=m
 CONFIG_DRM_OMAP_PANEL_DPI=m
 CONFIG_DRM_OMAP_PANEL_DSI_CM=m
-CONFIG_DRM_OMAP_PANEL_SONY_ACX565AKM=m
-CONFIG_DRM_OMAP_PANEL_LGPHILIPS_LB035Q02=m
-CONFIG_DRM_OMAP_PANEL_SHARP_LS037V7DW01=m
-CONFIG_DRM_OMAP_PANEL_TPO_TD028TTEC1=m
-CONFIG_DRM_OMAP_PANEL_TPO_TD043MTEA1=m
-CONFIG_DRM_OMAP_PANEL_NEC_NL8048HL11=m
 CONFIG_DRM_TILCDC=m
 CONFIG_DRM_PANEL_SIMPLE=m
 CONFIG_DRM_TI_TFP410=m
+CONFIG_DRM_PANEL_LG_LB035Q02=m
+CONFIG_DRM_PANEL_NEC_NL8048HL11=m
+CONFIG_DRM_PANEL_SHARP_LS037V7DW01=m
+CONFIG_DRM_PANEL_SONY_ACX565AKM=m
+CONFIG_DRM_PANEL_TPO_TD028TTEC1=m
+CONFIG_DRM_PANEL_TPO_TD043MTEA1=m
 CONFIG_FB=y
 CONFIG_FIRMWARE_EDID=y
 CONFIG_FB_MODE_HELPERS=y
index 567dbede4785ce96b89718cc9f1725150d13d4eb..f1d0a7807cd0e13beca85a00ea9a34ef504b104a 100644 (file)
@@ -82,7 +82,7 @@
 #ifndef __ASSEMBLY__
 
 #ifdef CONFIG_CPU_CP15_MMU
-static inline unsigned int get_domain(void)
+static __always_inline unsigned int get_domain(void)
 {
        unsigned int domain;
 
@@ -94,7 +94,7 @@ static inline unsigned int get_domain(void)
        return domain;
 }
 
-static inline void set_domain(unsigned val)
+static __always_inline void set_domain(unsigned int val)
 {
        asm volatile(
        "mcr    p15, 0, %0, c3, c0      @ set domain"
@@ -102,12 +102,12 @@ static inline void set_domain(unsigned val)
        isb();
 }
 #else
-static inline unsigned int get_domain(void)
+static __always_inline unsigned int get_domain(void)
 {
        return 0;
 }
 
-static inline void set_domain(unsigned val)
+static __always_inline void set_domain(unsigned int val)
 {
 }
 #endif
index 303248e5b990f5ae4698432050aa53a6f0014340..98c6b91be4a8addd8212a3f170927e259ffb0e0d 100644 (file)
@@ -22,7 +22,7 @@
  * perform such accesses (eg, via list poison values) which could then
  * be exploited for priviledge escalation.
  */
-static inline unsigned int uaccess_save_and_enable(void)
+static __always_inline unsigned int uaccess_save_and_enable(void)
 {
 #ifdef CONFIG_CPU_SW_DOMAIN_PAN
        unsigned int old_domain = get_domain();
@@ -37,7 +37,7 @@ static inline unsigned int uaccess_save_and_enable(void)
 #endif
 }
 
-static inline void uaccess_restore(unsigned int flags)
+static __always_inline void uaccess_restore(unsigned int flags)
 {
 #ifdef CONFIG_CPU_SW_DOMAIN_PAN
        /* Restore the user access mask */
index a7810be07da1c56c1502a72b60d7bc3da8075d91..4a3982812a401f1259909df4e1d05ead3f29dd9c 100644 (file)
@@ -68,7 +68,7 @@ ENDPROC(__vet_atags)
  * The following fragment of code is executed with the MMU on in MMU mode,
  * and uses absolute addresses; this is not position independent.
  *
- *  r0  = cp#15 control register
+ *  r0  = cp#15 control register (exc_ret for M-class)
  *  r1  = machine ID
  *  r2  = atags/dtb pointer
  *  r9  = processor ID
@@ -137,7 +137,8 @@ __mmap_switched_data:
 #ifdef CONFIG_CPU_CP15
        .long   cr_alignment                    @ r3
 #else
-       .long   0                               @ r3
+M_CLASS(.long  exc_ret)                        @ r3
+AR_CLASS(.long 0)                              @ r3
 #endif
        .size   __mmap_switched_data, . - __mmap_switched_data
 
index afa350f44dea3308609754e279e040c10c711f95..0fc814bbc34b171e43e55a57b081220b15fe70a2 100644 (file)
@@ -201,6 +201,8 @@ M_CLASS(streq       r3, [r12, #PMSAv8_MAIR1])
        bic     r0, r0, #V7M_SCB_CCR_IC
 #endif
        str     r0, [r12, V7M_SCB_CCR]
+       /* Pass exc_ret to __mmap_switched */
+       mov     r0, r10
 #endif /* CONFIG_CPU_CP15 elif CONFIG_CPU_V7M */
        ret     lr
 ENDPROC(__after_proc_init)
index 8062412be70f06dc8d252ca45f9f5ff86bba262e..9fc5c73cc0be2d0644036eaa9ed15b9083af7ea5 100644 (file)
@@ -462,8 +462,8 @@ static s8 dm365_queue_priority_mapping[][2] = {
 };
 
 static const struct dma_slave_map dm365_edma_map[] = {
-       { "davinci-mcbsp.0", "tx", EDMA_FILTER_PARAM(0, 2) },
-       { "davinci-mcbsp.0", "rx", EDMA_FILTER_PARAM(0, 3) },
+       { "davinci-mcbsp", "tx", EDMA_FILTER_PARAM(0, 2) },
+       { "davinci-mcbsp", "rx", EDMA_FILTER_PARAM(0, 3) },
        { "davinci_voicecodec", "tx", EDMA_FILTER_PARAM(0, 2) },
        { "davinci_voicecodec", "rx", EDMA_FILTER_PARAM(0, 3) },
        { "spi_davinci.2", "tx", EDMA_FILTER_PARAM(0, 10) },
index d942a335709076fe743935e3331d65388d270707..2efd18e8824c78e597eb28aa2332d85193660167 100644 (file)
@@ -89,6 +89,13 @@ static struct iommu_platform_data omap3_iommu_pdata = {
        .reset_name = "mmu",
        .assert_reset = omap_device_assert_hardreset,
        .deassert_reset = omap_device_deassert_hardreset,
+       .device_enable = omap_device_enable,
+       .device_idle = omap_device_idle,
+};
+
+static struct iommu_platform_data omap3_iommu_isp_pdata = {
+       .device_enable = omap_device_enable,
+       .device_idle = omap_device_idle,
 };
 
 static int omap3_sbc_t3730_twl_callback(struct device *dev,
@@ -424,6 +431,8 @@ static struct iommu_platform_data omap4_iommu_pdata = {
        .reset_name = "mmu_cache",
        .assert_reset = omap_device_assert_hardreset,
        .deassert_reset = omap_device_deassert_hardreset,
+       .device_enable = omap_device_enable,
+       .device_idle = omap_device_idle,
 };
 #endif
 
@@ -617,6 +626,8 @@ static struct of_dev_auxdata omap_auxdata_lookup[] = {
 #ifdef CONFIG_ARCH_OMAP3
        OF_DEV_AUXDATA("ti,omap2-iommu", 0x5d000000, "5d000000.mmu",
                       &omap3_iommu_pdata),
+       OF_DEV_AUXDATA("ti,omap2-iommu", 0x480bd400, "480bd400.mmu",
+                      &omap3_iommu_isp_pdata),
        OF_DEV_AUXDATA("ti,omap3-smartreflex-core", 0x480cb000,
                       "480cb000.smartreflex", &omap_sr_pdata[OMAP_SR_CORE]),
        OF_DEV_AUXDATA("ti,omap3-smartreflex-mpu-iva", 0x480c9000,
index 239084cf8192d3b30c7e00fd0aa5c0bbb8c2a11b..26cbce1353387af67e366c3c03c8995384f8c496 100644 (file)
@@ -481,14 +481,18 @@ static void sunxi_mc_smp_cpu_die(unsigned int l_cpu)
 static int sunxi_cpu_powerdown(unsigned int cpu, unsigned int cluster)
 {
        u32 reg;
+       int gating_bit = cpu;
 
        pr_debug("%s: cluster %u cpu %u\n", __func__, cluster, cpu);
        if (cpu >= SUNXI_CPUS_PER_CLUSTER || cluster >= SUNXI_NR_CLUSTERS)
                return -EINVAL;
 
+       if (is_a83t && cpu == 0)
+               gating_bit = 4;
+
        /* gate processor power */
        reg = readl(prcm_base + PRCM_PWROFF_GATING_REG(cluster));
-       reg |= PRCM_PWROFF_GATING_REG_CORE(cpu);
+       reg |= PRCM_PWROFF_GATING_REG_CORE(gating_bit);
        writel(reg, prcm_base + PRCM_PWROFF_GATING_REG(cluster));
        udelay(20);
 
index 04b36436cbc04877a060b10670bf453dd2ed0e2d..788c5cf46de593a8e53265c7de3842496fe21dc1 100644 (file)
@@ -324,7 +324,7 @@ union offset_union {
        __put32_unaligned_check("strbt", val, addr)
 
 static void
-do_alignment_finish_ldst(unsigned long addr, unsigned long instr, struct pt_regs *regs, union offset_union offset)
+do_alignment_finish_ldst(unsigned long addr, u32 instr, struct pt_regs *regs, union offset_union offset)
 {
        if (!LDST_U_BIT(instr))
                offset.un = -offset.un;
@@ -337,7 +337,7 @@ do_alignment_finish_ldst(unsigned long addr, unsigned long instr, struct pt_regs
 }
 
 static int
-do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *regs)
+do_alignment_ldrhstrh(unsigned long addr, u32 instr, struct pt_regs *regs)
 {
        unsigned int rd = RD_BITS(instr);
 
@@ -386,8 +386,7 @@ do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *r
 }
 
 static int
-do_alignment_ldrdstrd(unsigned long addr, unsigned long instr,
-                     struct pt_regs *regs)
+do_alignment_ldrdstrd(unsigned long addr, u32 instr, struct pt_regs *regs)
 {
        unsigned int rd = RD_BITS(instr);
        unsigned int rd2;
@@ -449,7 +448,7 @@ do_alignment_ldrdstrd(unsigned long addr, unsigned long instr,
 }
 
 static int
-do_alignment_ldrstr(unsigned long addr, unsigned long instr, struct pt_regs *regs)
+do_alignment_ldrstr(unsigned long addr, u32 instr, struct pt_regs *regs)
 {
        unsigned int rd = RD_BITS(instr);
 
@@ -498,7 +497,7 @@ do_alignment_ldrstr(unsigned long addr, unsigned long instr, struct pt_regs *reg
  * PU = 10             A                    B
  */
 static int
-do_alignment_ldmstm(unsigned long addr, unsigned long instr, struct pt_regs *regs)
+do_alignment_ldmstm(unsigned long addr, u32 instr, struct pt_regs *regs)
 {
        unsigned int rd, rn, correction, nr_regs, regbits;
        unsigned long eaddr, newaddr;
@@ -539,7 +538,7 @@ do_alignment_ldmstm(unsigned long addr, unsigned long instr, struct pt_regs *reg
         * processor for us.
         */
        if (addr != eaddr) {
-               pr_err("LDMSTM: PC = %08lx, instr = %08lx, "
+               pr_err("LDMSTM: PC = %08lx, instr = %08x, "
                        "addr = %08lx, eaddr = %08lx\n",
                         instruction_pointer(regs), instr, addr, eaddr);
                show_regs(regs);
@@ -716,10 +715,10 @@ thumb2arm(u16 tinstr)
  * 2. Register name Rt from ARMv7 is same as Rd from ARMv6 (Rd is Rt)
  */
 static void *
-do_alignment_t32_to_handler(unsigned long *pinstr, struct pt_regs *regs,
+do_alignment_t32_to_handler(u32 *pinstr, struct pt_regs *regs,
                            union offset_union *poffset)
 {
-       unsigned long instr = *pinstr;
+       u32 instr = *pinstr;
        u16 tinst1 = (instr >> 16) & 0xffff;
        u16 tinst2 = instr & 0xffff;
 
@@ -767,17 +766,48 @@ do_alignment_t32_to_handler(unsigned long *pinstr, struct pt_regs *regs,
        return NULL;
 }
 
+static int alignment_get_arm(struct pt_regs *regs, u32 *ip, u32 *inst)
+{
+       u32 instr = 0;
+       int fault;
+
+       if (user_mode(regs))
+               fault = get_user(instr, ip);
+       else
+               fault = probe_kernel_address(ip, instr);
+
+       *inst = __mem_to_opcode_arm(instr);
+
+       return fault;
+}
+
+static int alignment_get_thumb(struct pt_regs *regs, u16 *ip, u16 *inst)
+{
+       u16 instr = 0;
+       int fault;
+
+       if (user_mode(regs))
+               fault = get_user(instr, ip);
+       else
+               fault = probe_kernel_address(ip, instr);
+
+       *inst = __mem_to_opcode_thumb16(instr);
+
+       return fault;
+}
+
 static int
 do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 {
        union offset_union uninitialized_var(offset);
-       unsigned long instr = 0, instrptr;
-       int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs);
+       unsigned long instrptr;
+       int (*handler)(unsigned long addr, u32 instr, struct pt_regs *regs);
        unsigned int type;
-       unsigned int fault;
+       u32 instr = 0;
        u16 tinstr = 0;
        int isize = 4;
        int thumb2_32b = 0;
+       int fault;
 
        if (interrupts_enabled(regs))
                local_irq_enable();
@@ -786,15 +816,14 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 
        if (thumb_mode(regs)) {
                u16 *ptr = (u16 *)(instrptr & ~1);
-               fault = probe_kernel_address(ptr, tinstr);
-               tinstr = __mem_to_opcode_thumb16(tinstr);
+
+               fault = alignment_get_thumb(regs, ptr, &tinstr);
                if (!fault) {
                        if (cpu_architecture() >= CPU_ARCH_ARMv7 &&
                            IS_T32(tinstr)) {
                                /* Thumb-2 32-bit */
-                               u16 tinst2 = 0;
-                               fault = probe_kernel_address(ptr + 1, tinst2);
-                               tinst2 = __mem_to_opcode_thumb16(tinst2);
+                               u16 tinst2;
+                               fault = alignment_get_thumb(regs, ptr + 1, &tinst2);
                                instr = __opcode_thumb32_compose(tinstr, tinst2);
                                thumb2_32b = 1;
                        } else {
@@ -803,8 +832,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
                        }
                }
        } else {
-               fault = probe_kernel_address((void *)instrptr, instr);
-               instr = __mem_to_opcode_arm(instr);
+               fault = alignment_get_arm(regs, (void *)instrptr, &instr);
        }
 
        if (fault) {
@@ -926,7 +954,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
         * Oops, we didn't handle the instruction.
         */
        pr_err("Alignment trap: not handling instruction "
-               "%0*lx at [<%08lx>]\n",
+               "%0*x at [<%08lx>]\n",
                isize << 1,
                isize == 2 ? tinstr : instr, instrptr);
        ai_skipped += 1;
@@ -936,7 +964,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
        ai_user += 1;
 
        if (ai_usermode & UM_WARN)
-               printk("Alignment trap: %s (%d) PC=0x%08lx Instr=0x%0*lx "
+               printk("Alignment trap: %s (%d) PC=0x%08lx Instr=0x%0*x "
                       "Address=0x%08lx FSR 0x%03x\n", current->comm,
                        task_pid_nr(current), instrptr,
                        isize << 1,
index 1448f144e7fb9c441902e2728f572aa91f405157..1a49d503eafc80b461d256f4f068e9a54c6d85f6 100644 (file)
@@ -132,13 +132,11 @@ __v7m_setup_cont:
        dsb
        mov     r6, lr                  @ save LR
        ldr     sp, =init_thread_union + THREAD_START_SP
-       stmia   sp, {r0-r3, r12}
        cpsie   i
        svc     #0
 1:     cpsid   i
-       ldr     r0, =exc_ret
-       orr     lr, lr, #EXC_RET_THREADMODE_PROCESSSTACK
-       str     lr, [r0]
+       /* Calculate exc_ret */
+       orr     r10, lr, #EXC_RET_THREADMODE_PROCESSSTACK
        ldmia   sp, {r0-r3, r12}
        str     r5, [r12, #11 * 4]      @ restore the original SVC vector entry
        mov     lr, r6                  @ restore LR
index 24f1aac366d64355f5b6b37bb8e263bcce7f2e2d..d5b6e8159a335a0fde372e68f84e2101fc448560 100644 (file)
                reg = <1>;
        };
 };
+
+&reg_dc1sw {
+       /*
+        * Ethernet PHY needs 30ms to properly power up and some more
+        * to initialize. 100ms should be plenty of time to finish
+        * whole process.
+        */
+       regulator-enable-ramp-delay = <100000>;
+};
index e6fb9683f21355ea7e3a947b20b3ea4fc7900d61..25099202c52c99d37b06ca3127dcc9b9b8214b4b 100644 (file)
 };
 
 &reg_dc1sw {
+       /*
+        * Ethernet PHY needs 30ms to properly power up and some more
+        * to initialize. 100ms should be plenty of time to finish
+        * whole process.
+        */
+       regulator-enable-ramp-delay = <100000>;
        regulator-name = "vcc-phy";
 };
 
index 3eccbdba7154939e965e6f14faeeb5c8123ff64b..70f4cce6be43e1707aa5b0a3b682c281683d1857 100644 (file)
                clock-output-names = "ext-osc32k";
        };
 
-       pmu {
-               compatible = "arm,cortex-a53-pmu";
-               interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>,
-                            <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
-                            <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>,
-                            <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
-               interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
-       };
-
        psci {
                compatible = "arm,psci-0.2";
                method = "smc";
index 8a3a770e8f2ce62bb99fc9fd74461073cfa7780a..56789ccf94545f39cde28c34f9dba8af495322a7 100644 (file)
 
                pinmux: pinmux@14029c {
                        compatible = "pinctrl-single";
-                       reg = <0x0014029c 0x250>;
+                       reg = <0x0014029c 0x26c>;
                        #address-cells = <1>;
                        #size-cells = <1>;
                        pinctrl-single,register-width = <32>;
                        pinctrl-single,function-mask = <0xf>;
                        pinctrl-single,gpio-range = <
-                               &range 0 154 MODE_GPIO
+                               &range 0  91 MODE_GPIO
+                               &range 95 60 MODE_GPIO
                                >;
                        range: gpio-range {
                                #pinctrl-single,gpio-range-cells = <3>;
index 71e2e34400d40dab63f864f347bb1203ec6873eb..0098dfdef96c0285db363155f0bdb72706193d1c 100644 (file)
                                        <&pinmux 108 16 27>,
                                        <&pinmux 135 77 6>,
                                        <&pinmux 141 67 4>,
-                                       <&pinmux 145 149 6>,
-                                       <&pinmux 151 91 4>;
+                                       <&pinmux 145 149 6>;
                };
 
                i2c1: i2c@e0000 {
index d98346da01df5d7ab4f7081e14151ec29210cd7b..078a5010228cd7f55cc161b82f46ea65bf9dfd5d 100644 (file)
        status = "okay";
 
        i2c-mux@77 {
-               compatible = "nxp,pca9847";
+               compatible = "nxp,pca9547";
                reg = <0x77>;
                #address-cells = <1>;
                #size-cells = <0>;
index 408e0ecdce6a5b2024fb89bed1cc7902dafb5180..b032f3890c8c61c0b4e8fa92e94ef57981a18118 100644 (file)
@@ -33,7 +33,7 @@
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster0_l2>;
-                       cpu-idle-states = <&cpu_pw20>;
+                       cpu-idle-states = <&cpu_pw15>;
                };
 
                cpu@1 {
@@ -49,7 +49,7 @@
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster0_l2>;
-                       cpu-idle-states = <&cpu_pw20>;
+                       cpu-idle-states = <&cpu_pw15>;
                };
 
                cpu@100 {
@@ -65,7 +65,7 @@
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster1_l2>;
-                       cpu-idle-states = <&cpu_pw20>;
+                       cpu-idle-states = <&cpu_pw15>;
                };
 
                cpu@101 {
@@ -81,7 +81,7 @@
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster1_l2>;
-                       cpu-idle-states = <&cpu_pw20>;
+                       cpu-idle-states = <&cpu_pw15>;
                };
 
                cpu@200 {
@@ -97,7 +97,7 @@
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster2_l2>;
-                       cpu-idle-states = <&cpu_pw20>;
+                       cpu-idle-states = <&cpu_pw15>;
                };
 
                cpu@201 {
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster2_l2>;
-                       cpu-idle-states = <&cpu_pw20>;
+                       cpu-idle-states = <&cpu_pw15>;
                };
 
                cpu@300 {
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster3_l2>;
-                       cpu-idle-states = <&cpu_pw20>;
+                       cpu-idle-states = <&cpu_pw15>;
                };
 
                cpu@301 {
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster3_l2>;
-                       cpu-idle-states = <&cpu_pw20>;
+                       cpu-idle-states = <&cpu_pw15>;
                };
 
                cpu@400 {
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster4_l2>;
-                       cpu-idle-states = <&cpu_pw20>;
+                       cpu-idle-states = <&cpu_pw15>;
                };
 
                cpu@401 {
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster4_l2>;
-                       cpu-idle-states = <&cpu_pw20>;
+                       cpu-idle-states = <&cpu_pw15>;
                };
 
                cpu@500 {
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster5_l2>;
-                       cpu-idle-states = <&cpu_pw20>;
+                       cpu-idle-states = <&cpu_pw15>;
                };
 
                cpu@501 {
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster5_l2>;
-                       cpu-idle-states = <&cpu_pw20>;
+                       cpu-idle-states = <&cpu_pw15>;
                };
 
                cpu@600 {
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster6_l2>;
-                       cpu-idle-states = <&cpu_pw20>;
+                       cpu-idle-states = <&cpu_pw15>;
                };
 
                cpu@601 {
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster6_l2>;
-                       cpu-idle-states = <&cpu_pw20>;
+                       cpu-idle-states = <&cpu_pw15>;
                };
 
                cpu@700 {
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster7_l2>;
-                       cpu-idle-states = <&cpu_pw20>;
+                       cpu-idle-states = <&cpu_pw15>;
                };
 
                cpu@701 {
                        i-cache-line-size = <64>;
                        i-cache-sets = <192>;
                        next-level-cache = <&cluster7_l2>;
-                       cpu-idle-states = <&cpu_pw20>;
+                       cpu-idle-states = <&cpu_pw15>;
                };
 
                cluster0_l2: l2-cache0 {
                        cache-level = <2>;
                };
 
-               cpu_pw20: cpu-pw20 {
+               cpu_pw15: cpu-pw15 {
                        compatible = "arm,idle-state";
-                       idle-state-name = "PW20";
+                       idle-state-name = "PW15";
                        arm,psci-suspend-param = <0x0>;
                        entry-latency-us = <2000>;
                        exit-latency-us = <2000>;
index 5f9d0da196e13c695ccc340a2f5ab5bc96985f67..23c8fad7932b14ffb885bd517606939ea38548f8 100644 (file)
                        };
 
                        sdma2: dma-controller@302c0000 {
-                               compatible = "fsl,imx8mm-sdma", "fsl,imx7d-sdma";
+                               compatible = "fsl,imx8mm-sdma", "fsl,imx8mq-sdma";
                                reg = <0x302c0000 0x10000>;
                                interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX8MM_CLK_SDMA2_ROOT>,
                        };
 
                        sdma3: dma-controller@302b0000 {
-                               compatible = "fsl,imx8mm-sdma", "fsl,imx7d-sdma";
+                               compatible = "fsl,imx8mm-sdma", "fsl,imx8mq-sdma";
                                reg = <0x302b0000 0x10000>;
                                interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX8MM_CLK_SDMA3_ROOT>,
                                compatible = "fsl,imx8mm-usdhc", "fsl,imx7d-usdhc";
                                reg = <0x30b40000 0x10000>;
                                interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clk IMX8MM_CLK_DUMMY>,
+                               clocks = <&clk IMX8MM_CLK_IPG_ROOT>,
                                         <&clk IMX8MM_CLK_NAND_USDHC_BUS>,
                                         <&clk IMX8MM_CLK_USDHC1_ROOT>;
                                clock-names = "ipg", "ahb", "per";
                                compatible = "fsl,imx8mm-usdhc", "fsl,imx7d-usdhc";
                                reg = <0x30b50000 0x10000>;
                                interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clk IMX8MM_CLK_DUMMY>,
+                               clocks = <&clk IMX8MM_CLK_IPG_ROOT>,
                                         <&clk IMX8MM_CLK_NAND_USDHC_BUS>,
                                         <&clk IMX8MM_CLK_USDHC2_ROOT>;
                                clock-names = "ipg", "ahb", "per";
                                compatible = "fsl,imx8mm-usdhc", "fsl,imx7d-usdhc";
                                reg = <0x30b60000 0x10000>;
                                interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clk IMX8MM_CLK_DUMMY>,
+                               clocks = <&clk IMX8MM_CLK_IPG_ROOT>,
                                         <&clk IMX8MM_CLK_NAND_USDHC_BUS>,
                                         <&clk IMX8MM_CLK_USDHC3_ROOT>;
                                clock-names = "ipg", "ahb", "per";
                        };
 
                        sdma1: dma-controller@30bd0000 {
-                               compatible = "fsl,imx8mm-sdma", "fsl,imx7d-sdma";
+                               compatible = "fsl,imx8mm-sdma", "fsl,imx8mq-sdma";
                                reg = <0x30bd0000 0x10000>;
                                interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX8MM_CLK_SDMA1_ROOT>,
index 785f4c420fa4c518dad3bc0e20ad4528279b96e7..43c4db3121468edeced10d2b6fa6752b9188ca79 100644 (file)
                        };
 
                        sdma3: dma-controller@302b0000 {
-                               compatible = "fsl,imx8mn-sdma", "fsl,imx7d-sdma";
+                               compatible = "fsl,imx8mn-sdma", "fsl,imx8mq-sdma";
                                reg = <0x302b0000 0x10000>;
                                interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX8MN_CLK_SDMA3_ROOT>,
                        };
 
                        sdma2: dma-controller@302c0000 {
-                               compatible = "fsl,imx8mn-sdma", "fsl,imx7d-sdma";
+                               compatible = "fsl,imx8mn-sdma", "fsl,imx8mq-sdma";
                                reg = <0x302c0000 0x10000>;
                                interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX8MN_CLK_SDMA2_ROOT>,
                                compatible = "fsl,imx8mn-usdhc", "fsl,imx7d-usdhc";
                                reg = <0x30b40000 0x10000>;
                                interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clk IMX8MN_CLK_DUMMY>,
+                               clocks = <&clk IMX8MN_CLK_IPG_ROOT>,
                                         <&clk IMX8MN_CLK_NAND_USDHC_BUS>,
                                         <&clk IMX8MN_CLK_USDHC1_ROOT>;
                                clock-names = "ipg", "ahb", "per";
                                compatible = "fsl,imx8mn-usdhc", "fsl,imx7d-usdhc";
                                reg = <0x30b50000 0x10000>;
                                interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clk IMX8MN_CLK_DUMMY>,
+                               clocks = <&clk IMX8MN_CLK_IPG_ROOT>,
                                         <&clk IMX8MN_CLK_NAND_USDHC_BUS>,
                                         <&clk IMX8MN_CLK_USDHC2_ROOT>;
                                clock-names = "ipg", "ahb", "per";
                                compatible = "fsl,imx8mn-usdhc", "fsl,imx7d-usdhc";
                                reg = <0x30b60000 0x10000>;
                                interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clk IMX8MN_CLK_DUMMY>,
+                               clocks = <&clk IMX8MN_CLK_IPG_ROOT>,
                                         <&clk IMX8MN_CLK_NAND_USDHC_BUS>,
                                         <&clk IMX8MN_CLK_USDHC3_ROOT>;
                                clock-names = "ipg", "ahb", "per";
                        };
 
                        sdma1: dma-controller@30bd0000 {
-                               compatible = "fsl,imx8mn-sdma", "fsl,imx7d-sdma";
+                               compatible = "fsl,imx8mn-sdma", "fsl,imx8mq-sdma";
                                reg = <0x30bd0000 0x10000>;
                                interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX8MN_CLK_SDMA1_ROOT>,
index af99473ada04377fd32af9304f5eeac8d74b1fba..32ce14936b01318a960ecd72834cf6d676268f90 100644 (file)
@@ -88,9 +88,9 @@
                regulator-name = "0V9_ARM";
                regulator-min-microvolt = <900000>;
                regulator-max-microvolt = <1000000>;
-               gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>;
-               states = <1000000 0x0
-                          900000 0x1>;
+               gpios = <&gpio3 16 GPIO_ACTIVE_HIGH>;
+               states = <1000000 0x1
+                          900000 0x0>;
                regulator-always-on;
        };
 };
index 04115ca6bfb528c40a7f7cf207c57d2377c1a1ba..55a3d1c4bdf04cfc8df24adc230d23a0702c0180 100644 (file)
                                             "fsl,imx7d-usdhc";
                                reg = <0x30b40000 0x10000>;
                                interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clk IMX8MQ_CLK_DUMMY>,
+                               clocks = <&clk IMX8MQ_CLK_IPG_ROOT>,
                                         <&clk IMX8MQ_CLK_NAND_USDHC_BUS>,
                                         <&clk IMX8MQ_CLK_USDHC1_ROOT>;
                                clock-names = "ipg", "ahb", "per";
                                             "fsl,imx7d-usdhc";
                                reg = <0x30b50000 0x10000>;
                                interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clk IMX8MQ_CLK_DUMMY>,
+                               clocks = <&clk IMX8MQ_CLK_IPG_ROOT>,
                                         <&clk IMX8MQ_CLK_NAND_USDHC_BUS>,
                                         <&clk IMX8MQ_CLK_USDHC2_ROOT>;
                                clock-names = "ipg", "ahb", "per";
index d105986c6be1a6f0a63f511b2bcd8c1d24fc1d3e..5f350cc71a2fdb08e1e7c589ef8d51267b82576f 100644 (file)
                gpio = <&gpiosb 0 GPIO_ACTIVE_HIGH>;
        };
 
-       usb3_phy: usb3-phy {
-               compatible = "usb-nop-xceiv";
-               vcc-supply = <&exp_usb3_vbus>;
-       };
-
        vsdc_reg: vsdc-reg {
                compatible = "regulator-gpio";
                regulator-name = "vsdc";
        status = "okay";
 };
 
+&comphy2 {
+       connector {
+               compatible = "usb-a-connector";
+               phy-supply = <&exp_usb3_vbus>;
+       };
+};
+
 &usb3 {
        status = "okay";
        phys = <&comphy2 0>;
-       usb-phy = <&usb3_phy>;
 };
 
 &mdio {
index e152b0ca0290c7f69e86f6b3c96a7ed16c5e3091..b8066868a3fe6ba79354040e20770e7c1c62a826 100644 (file)
@@ -44,7 +44,7 @@
                power-supply = <&pp3300_disp>;
 
                panel-timing {
-                       clock-frequency = <266604720>;
+                       clock-frequency = <266666667>;
                        hactive = <2400>;
                        hfront-porch = <48>;
                        hback-porch = <84>;
index 0d1f5f9a0de9558733446b2f9dec48ca12e58501..c133e8d64b2a3d2dfac63fedb401657ae7b7f380 100644 (file)
        status = "okay";
 
        u2phy0_host: host-port {
-               phy-supply = <&vcc5v0_host>;
+               phy-supply = <&vcc5v0_typec>;
                status = "okay";
        };
 
 
 &usbdrd_dwc3_0 {
        status = "okay";
-       dr_mode = "otg";
+       dr_mode = "host";
 };
 
 &usbdrd3_1 {
index 0401d4ec1f4527067485d864b183fb6103962624..e544deb61d288285610a2d28aea8ecf1a40adc17 100644 (file)
                regulator-always-on;
                regulator-boot-on;
                regulator-min-microvolt = <800000>;
-               regulator-max-microvolt = <1400000>;
+               regulator-max-microvolt = <1700000>;
                vin-supply = <&vcc5v0_sys>;
        };
 };
        rk808: pmic@1b {
                compatible = "rockchip,rk808";
                reg = <0x1b>;
-               interrupt-parent = <&gpio1>;
-               interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
+               interrupt-parent = <&gpio3>;
+               interrupts = <10 IRQ_TYPE_LEVEL_LOW>;
                #clock-cells = <1>;
                clock-output-names = "xin32k", "rk808-clkout2";
                pinctrl-names = "default";
 
        pmic {
                pmic_int_l: pmic-int-l {
-                       rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>;
+                       rockchip,pins = <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>;
                };
 
                vsel1_gpio: vsel1-gpio {
 
 &sdmmc {
        bus-width = <4>;
-       cap-mmc-highspeed;
        cap-sd-highspeed;
        cd-gpios = <&gpio0 7 GPIO_ACTIVE_LOW>;
        disable-wp;
 
 &sdhci {
        bus-width = <8>;
-       mmc-hs400-1_8v;
-       mmc-hs400-enhanced-strobe;
+       mmc-hs200-1_8v;
        non-removable;
        status = "okay";
 };
index b1454d117cd2c69582d519f123fcaa66f5f81c44..aca07c2f6e6e364e84efb9708f8a743cf24e6627 100644 (file)
@@ -79,6 +79,7 @@
 #define CAVIUM_CPU_PART_THUNDERX_83XX  0x0A3
 #define CAVIUM_CPU_PART_THUNDERX2      0x0AF
 
+#define BRCM_CPU_PART_BRAHMA_B53       0x100
 #define BRCM_CPU_PART_VULCAN           0x516
 
 #define QCOM_CPU_PART_FALKOR_V1                0x800
 #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
 #define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)
 #define MIDR_CAVIUM_THUNDERX2 MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX2)
+#define MIDR_BRAHMA_B53 MIDR_CPU_MODEL(ARM_CPU_IMP_BRCM, BRCM_CPU_PART_BRAHMA_B53)
 #define MIDR_BRCM_VULCAN MIDR_CPU_MODEL(ARM_CPU_IMP_BRCM, BRCM_CPU_PART_VULCAN)
 #define MIDR_QCOM_FALKOR_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_FALKOR_V1)
 #define MIDR_QCOM_FALKOR MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_FALKOR)
index 9a21b84536f2e04bdf0698e20dc52aa81d952783..8dc6c5cdabe62e2f63065abd525ff516fe685387 100644 (file)
 #define PROT_DEFAULT           (_PROT_DEFAULT | PTE_MAYBE_NG)
 #define PROT_SECT_DEFAULT      (_PROT_SECT_DEFAULT | PMD_MAYBE_NG)
 
-#define PROT_DEVICE_nGnRnE     (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRnE))
-#define PROT_DEVICE_nGnRE      (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRE))
-#define PROT_NORMAL_NC         (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_NC))
-#define PROT_NORMAL_WT         (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_WT))
-#define PROT_NORMAL            (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL))
+#define PROT_DEVICE_nGnRnE     (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRnE))
+#define PROT_DEVICE_nGnRE      (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRE))
+#define PROT_NORMAL_NC         (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_NC))
+#define PROT_NORMAL_WT         (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_WT))
+#define PROT_NORMAL            (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL))
 
 #define PROT_SECT_DEVICE_nGnRE (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_DEVICE_nGnRE))
 #define PROT_SECT_NORMAL       (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_NORMAL))
@@ -80,8 +80,9 @@
 #define PAGE_S2_DEVICE         __pgprot(_PROT_DEFAULT | PAGE_S2_MEMATTR(DEVICE_nGnRE) | PTE_S2_RDONLY | PTE_S2_XN)
 
 #define PAGE_NONE              __pgprot(((_PAGE_DEFAULT) & ~PTE_VALID) | PTE_PROT_NONE | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN)
-#define PAGE_SHARED            __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE)
-#define PAGE_SHARED_EXEC       __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_WRITE)
+/* shared+writable pages are clean by default, hence PTE_RDONLY|PTE_WRITE */
+#define PAGE_SHARED            __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE)
+#define PAGE_SHARED_EXEC       __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_WRITE)
 #define PAGE_READONLY          __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN)
 #define PAGE_READONLY_EXEC     __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN)
 #define PAGE_EXECONLY          __pgprot(_PAGE_DEFAULT | PTE_RDONLY | PTE_NG | PTE_PXN)
index 8330810f699e31bd01794f8dc5ad17dd419646f6..565aa45ef1344e481b0ad201194613305a39eb90 100644 (file)
@@ -283,23 +283,6 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
        set_pte(ptep, pte);
 }
 
-#define __HAVE_ARCH_PTE_SAME
-static inline int pte_same(pte_t pte_a, pte_t pte_b)
-{
-       pteval_t lhs, rhs;
-
-       lhs = pte_val(pte_a);
-       rhs = pte_val(pte_b);
-
-       if (pte_present(pte_a))
-               lhs &= ~PTE_RDONLY;
-
-       if (pte_present(pte_b))
-               rhs &= ~PTE_RDONLY;
-
-       return (lhs == rhs);
-}
-
 /*
  * Huge pte definitions.
  */
index 0c731bfc7c8c763a1644c98d291be3454b63f760..0c20a7c1bee506d453c7635dedf887a5b0c77e33 100644 (file)
@@ -30,13 +30,6 @@ int __arm64_get_clock_mode(struct timekeeper *tk)
 }
 #define __arch_get_clock_mode __arm64_get_clock_mode
 
-static __always_inline
-int __arm64_use_vsyscall(struct vdso_data *vdata)
-{
-       return !vdata[CS_HRES_COARSE].clock_mode;
-}
-#define __arch_use_vsyscall __arm64_use_vsyscall
-
 static __always_inline
 void __arm64_update_vsyscall(struct vdso_data *vdata, struct timekeeper *tk)
 {
index 6c3b10a41bd85f794e42e67ad908517c4a40f3a1..93f34b4eca2547413c8d49e8a4e735fcac403ba3 100644 (file)
@@ -489,6 +489,7 @@ static const struct midr_range arm64_ssb_cpus[] = {
        MIDR_ALL_VERSIONS(MIDR_CORTEX_A35),
        MIDR_ALL_VERSIONS(MIDR_CORTEX_A53),
        MIDR_ALL_VERSIONS(MIDR_CORTEX_A55),
+       MIDR_ALL_VERSIONS(MIDR_BRAHMA_B53),
        {},
 };
 
@@ -573,6 +574,7 @@ static const struct midr_range spectre_v2_safe_list[] = {
        MIDR_ALL_VERSIONS(MIDR_CORTEX_A35),
        MIDR_ALL_VERSIONS(MIDR_CORTEX_A53),
        MIDR_ALL_VERSIONS(MIDR_CORTEX_A55),
+       MIDR_ALL_VERSIONS(MIDR_BRAHMA_B53),
        { /* sentinel */ }
 };
 
@@ -659,17 +661,23 @@ static const struct midr_range arm64_harden_el2_vectors[] = {
 #endif
 
 #ifdef CONFIG_ARM64_WORKAROUND_REPEAT_TLBI
-
-static const struct midr_range arm64_repeat_tlbi_cpus[] = {
+static const struct arm64_cpu_capabilities arm64_repeat_tlbi_list[] = {
 #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1009
-       MIDR_RANGE(MIDR_QCOM_FALKOR_V1, 0, 0, 0, 0),
+       {
+               ERRATA_MIDR_REV(MIDR_QCOM_FALKOR_V1, 0, 0)
+       },
+       {
+               .midr_range.model = MIDR_QCOM_KRYO,
+               .matches = is_kryo_midr,
+       },
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_1286807
-       MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 3, 0),
+       {
+               ERRATA_MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 3, 0),
+       },
 #endif
        {},
 };
-
 #endif
 
 #ifdef CONFIG_CAVIUM_ERRATUM_27456
@@ -737,6 +745,33 @@ static const struct midr_range erratum_1418040_list[] = {
 };
 #endif
 
+#ifdef CONFIG_ARM64_ERRATUM_845719
+static const struct midr_range erratum_845719_list[] = {
+       /* Cortex-A53 r0p[01234] */
+       MIDR_REV_RANGE(MIDR_CORTEX_A53, 0, 0, 4),
+       /* Brahma-B53 r0p[0] */
+       MIDR_REV(MIDR_BRAHMA_B53, 0, 0),
+       {},
+};
+#endif
+
+#ifdef CONFIG_ARM64_ERRATUM_843419
+static const struct arm64_cpu_capabilities erratum_843419_list[] = {
+       {
+               /* Cortex-A53 r0p[01234] */
+               .matches = is_affected_midr_range,
+               ERRATA_MIDR_REV_RANGE(MIDR_CORTEX_A53, 0, 0, 4),
+               MIDR_FIXED(0x4, BIT(8)),
+       },
+       {
+               /* Brahma-B53 r0p[0] */
+               .matches = is_affected_midr_range,
+               ERRATA_MIDR_REV(MIDR_BRAHMA_B53, 0, 0),
+       },
+       {},
+};
+#endif
+
 const struct arm64_cpu_capabilities arm64_errata[] = {
 #ifdef CONFIG_ARM64_WORKAROUND_CLEAN_CACHE
        {
@@ -768,19 +803,18 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_843419
        {
-       /* Cortex-A53 r0p[01234] */
                .desc = "ARM erratum 843419",
                .capability = ARM64_WORKAROUND_843419,
-               ERRATA_MIDR_REV_RANGE(MIDR_CORTEX_A53, 0, 0, 4),
-               MIDR_FIXED(0x4, BIT(8)),
+               .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
+               .matches = cpucap_multi_entry_cap_matches,
+               .match_list = erratum_843419_list,
        },
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_845719
        {
-       /* Cortex-A53 r0p[01234] */
                .desc = "ARM erratum 845719",
                .capability = ARM64_WORKAROUND_845719,
-               ERRATA_MIDR_REV_RANGE(MIDR_CORTEX_A53, 0, 0, 4),
+               ERRATA_MIDR_RANGE_LIST(erratum_845719_list),
        },
 #endif
 #ifdef CONFIG_CAVIUM_ERRATUM_23154
@@ -816,6 +850,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
        {
                .desc = "Qualcomm Technologies Falkor/Kryo erratum 1003",
                .capability = ARM64_WORKAROUND_QCOM_FALKOR_E1003,
+               .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
                .matches = cpucap_multi_entry_cap_matches,
                .match_list = qcom_erratum_1003_list,
        },
@@ -824,7 +859,9 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
        {
                .desc = "Qualcomm erratum 1009, ARM erratum 1286807",
                .capability = ARM64_WORKAROUND_REPEAT_TLBI,
-               ERRATA_MIDR_RANGE_LIST(arm64_repeat_tlbi_cpus),
+               .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
+               .matches = cpucap_multi_entry_cap_matches,
+               .match_list = arm64_repeat_tlbi_list,
        },
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_858921
index 2071260a275bd236923da5650da86a012eaa5b4a..46822afc57e00461843b56f72cd403a939f17e69 100644 (file)
@@ -632,6 +632,8 @@ static void reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
         */
        val = ((pmcr & ~ARMV8_PMU_PMCR_MASK)
               | (ARMV8_PMU_PMCR_MASK & 0xdecafbad)) & (~ARMV8_PMU_PMCR_E);
+       if (!system_supports_32bit_el0())
+               val |= ARMV8_PMU_PMCR_LC;
        __vcpu_sys_reg(vcpu, r->reg) = val;
 }
 
@@ -682,6 +684,8 @@ static bool access_pmcr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
                val = __vcpu_sys_reg(vcpu, PMCR_EL0);
                val &= ~ARMV8_PMU_PMCR_MASK;
                val |= p->regval & ARMV8_PMU_PMCR_MASK;
+               if (!system_supports_32bit_el0())
+                       val |= ARMV8_PMU_PMCR_LC;
                __vcpu_sys_reg(vcpu, PMCR_EL0) = val;
                kvm_pmu_handle_pmcr(vcpu, val);
                kvm_vcpu_pmu_restore_guest(vcpu);
index 77a836e661c9eea91bc7582dd6ed435f5aba8f90..df69eaa453a1c299b8467c3b972ef8a225fc5706 100644 (file)
@@ -84,7 +84,7 @@ void __init prom_init(void)
                 * Here we will start up CPU1 in the background and ask it to
                 * reconfigure itself then go back to sleep.
                 */
-               memcpy((void *)0xa0000200, &bmips_smp_movevec, 0x20);
+               memcpy((void *)0xa0000200, bmips_smp_movevec, 0x20);
                __sync();
                set_c0_cause(C_SW0);
                cpumask_set_cpu(1, &bmips_booted_mask);
index bf6a8afd7ad2783dff63cb55954a2e34d8ca6e79..581a6a3c66e405c6ea23cdfefc45690a2fe43209 100644 (file)
@@ -75,11 +75,11 @@ static inline int register_bmips_smp_ops(void)
 #endif
 }
 
-extern char bmips_reset_nmi_vec;
-extern char bmips_reset_nmi_vec_end;
-extern char bmips_smp_movevec;
-extern char bmips_smp_int_vec;
-extern char bmips_smp_int_vec_end;
+extern char bmips_reset_nmi_vec[];
+extern char bmips_reset_nmi_vec_end[];
+extern char bmips_smp_movevec[];
+extern char bmips_smp_int_vec[];
+extern char bmips_smp_int_vec_end[];
 
 extern int bmips_smp_enabled;
 extern int bmips_cpu_offset;
index e78462e8ca2e74311028c78b6be52a186fc83b9a..b08825531e9f9a3ce89e926ffc3e096fbfe14fc0 100644 (file)
@@ -24,6 +24,8 @@
 
 #define VDSO_HAS_CLOCK_GETRES          1
 
+#define __VDSO_USE_SYSCALL             ULLONG_MAX
+
 #ifdef CONFIG_MIPS_CLOCK_VSYSCALL
 
 static __always_inline long gettimeofday_fallback(
@@ -205,7 +207,7 @@ static __always_inline u64 __arch_get_hw_counter(s32 clock_mode)
                break;
 #endif
        default:
-               cycle_now = 0;
+               cycle_now = __VDSO_USE_SYSCALL;
                break;
        }
 
index 195314732233fe3eaf949e53648302eea6b66d06..00d41b94ba31688242a54929c0e73470f3869b78 100644 (file)
@@ -28,13 +28,6 @@ int __mips_get_clock_mode(struct timekeeper *tk)
 }
 #define __arch_get_clock_mode __mips_get_clock_mode
 
-static __always_inline
-int __mips_use_vsyscall(struct vdso_data *vdata)
-{
-       return (vdata[CS_HRES_COARSE].clock_mode != VDSO_CLOCK_NONE);
-}
-#define __arch_use_vsyscall __mips_use_vsyscall
-
 /* The asm-generic header needs to be included after the definitions above */
 #include <asm-generic/vdso/vsyscall.h>
 
index 76fae9b79f1312c1997e399f49d940494bd8b689..712c15de6ab9faa9d856b875963432d40ef610a1 100644 (file)
@@ -464,10 +464,10 @@ static void bmips_wr_vec(unsigned long dst, char *start, char *end)
 
 static inline void bmips_nmi_handler_setup(void)
 {
-       bmips_wr_vec(BMIPS_NMI_RESET_VEC, &bmips_reset_nmi_vec,
-               &bmips_reset_nmi_vec_end);
-       bmips_wr_vec(BMIPS_WARM_RESTART_VEC, &bmips_smp_int_vec,
-               &bmips_smp_int_vec_end);
+       bmips_wr_vec(BMIPS_NMI_RESET_VEC, bmips_reset_nmi_vec,
+               bmips_reset_nmi_vec_end);
+       bmips_wr_vec(BMIPS_WARM_RESTART_VEC, bmips_smp_int_vec,
+               bmips_smp_int_vec_end);
 }
 
 struct reset_vec_info {
index e01cb33bfa1a78a67638d5b27fb8fc7e43df3e09..41bb91f056885f5589e5b2a278cdcec2d83be659 100644 (file)
@@ -653,6 +653,13 @@ static void build_restore_pagemask(u32 **p, struct uasm_reloc **r,
                                   int restore_scratch)
 {
        if (restore_scratch) {
+               /*
+                * Ensure the MFC0 below observes the value written to the
+                * KScratch register by the prior MTC0.
+                */
+               if (scratch_reg >= 0)
+                       uasm_i_ehb(p);
+
                /* Reset default page size */
                if (PM_DEFAULT_MASK >> 16) {
                        uasm_i_lui(p, tmp, PM_DEFAULT_MASK >> 16);
@@ -667,12 +674,10 @@ static void build_restore_pagemask(u32 **p, struct uasm_reloc **r,
                        uasm_i_mtc0(p, 0, C0_PAGEMASK);
                        uasm_il_b(p, r, lid);
                }
-               if (scratch_reg >= 0) {
-                       uasm_i_ehb(p);
+               if (scratch_reg >= 0)
                        UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg);
-               } else {
+               else
                        UASM_i_LW(p, 1, scratchpad_offset(0), 0);
-               }
        } else {
                /* Reset default page size */
                if (PM_DEFAULT_MASK >> 16) {
@@ -921,6 +926,10 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
        }
        if (mode != not_refill && check_for_high_segbits) {
                uasm_l_large_segbits_fault(l, *p);
+
+               if (mode == refill_scratch && scratch_reg >= 0)
+                       uasm_i_ehb(p);
+
                /*
                 * We get here if we are an xsseg address, or if we are
                 * an xuseg address above (PGDIR_SHIFT+PGDIR_BITS) boundary.
@@ -939,12 +948,10 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
                uasm_i_jr(p, ptr);
 
                if (mode == refill_scratch) {
-                       if (scratch_reg >= 0) {
-                               uasm_i_ehb(p);
+                       if (scratch_reg >= 0)
                                UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg);
-                       } else {
+                       else
                                UASM_i_LW(p, 1, scratchpad_offset(0), 0);
-                       }
                } else {
                        uasm_i_nop(p);
                }
index 1d1d748c227f075685f79dc327bfc52a029885d1..b96d7449697791260fdf2a28985ba7174f412668 100644 (file)
@@ -2125,7 +2125,7 @@ ftrace_regs_caller:
        copy    %rp, %r26
        LDREG   -FTRACE_FRAME_SIZE-PT_SZ_ALGN(%sp), %r25
        ldo     -8(%r25), %r25
-       copy    %r3, %arg2
+       ldo     -FTRACE_FRAME_SIZE(%r1), %arg2
        b,l     ftrace_function_trampoline, %rp
        copy    %r1, %arg3 /* struct pt_regs */
 
index 677e9babef801305e61951244f0b32298c1725c7..f9dc597b0b86884dca4dc9c5e1814312bb34e41e 100644 (file)
@@ -91,6 +91,7 @@
 
 static inline void kuap_update_sr(u32 sr, u32 addr, u32 end)
 {
+       addr &= 0xf0000000;     /* align addr to start of segment */
        barrier();      /* make sure thread.kuap is updated before playing with SRs */
        while (addr < end) {
                mtsrin(sr, addr);
index 409c9bfb43d9dff09e4413f1095e03eaf184f2b1..57c229a86f0811e783c9526283e617f96c485bbf 100644 (file)
@@ -175,4 +175,7 @@ do {                                                                        \
        ARCH_DLINFO_CACHE_GEOMETRY;                                     \
 } while (0)
 
+/* Relocate the kernel image to @final_address */
+void relocate(unsigned long final_address);
+
 #endif /* _ASM_POWERPC_ELF_H */
index a4e7762dd28648ac5dc8e64bc96a6854b532087c..100f1b57ec2fd18531dd16b16c0885c0550f114c 100644 (file)
@@ -3249,7 +3249,20 @@ static void setup_secure_guest(unsigned long kbase, unsigned long fdt)
        /* Switch to secure mode. */
        prom_printf("Switching to secure mode.\n");
 
+       /*
+        * The ultravisor will do an integrity check of the kernel image but we
+        * relocated it so the check will fail. Restore the original image by
+        * relocating it back to the kernel virtual base address.
+        */
+       if (IS_ENABLED(CONFIG_RELOCATABLE))
+               relocate(KERNELBASE);
+
        ret = enter_secure_mode(kbase, fdt);
+
+       /* Relocate the kernel again. */
+       if (IS_ENABLED(CONFIG_RELOCATABLE))
+               relocate(kbase);
+
        if (ret != U_SUCCESS) {
                prom_printf("Returned %d from switching to secure mode.\n", ret);
                prom_rtas_os_term("Switch to secure mode failed.\n");
index 78bab17b1396aefe35ac0a4573fbbbab39acd148..b183ab9c5107c9236930b3d3d9e1f2c7dd27b302 100644 (file)
@@ -26,7 +26,8 @@ _end enter_prom $MEM_FUNCS reloc_offset __secondary_hold
 __secondary_hold_acknowledge __secondary_hold_spinloop __start
 logo_linux_clut224 btext_prepare_BAT
 reloc_got2 kernstart_addr memstart_addr linux_banner _stext
-__prom_init_toc_start __prom_init_toc_end btext_setup_display TOC."
+__prom_init_toc_start __prom_init_toc_end btext_setup_display TOC.
+relocate"
 
 NM="$1"
 OBJ="$2"
index 591bfb4bfd0fabb74cb2c81c35ff51acef8f58ba..a3f9c665bb5ba4c68039471c9e3b257cfd7814d3 100644 (file)
@@ -1217,6 +1217,7 @@ int kvmppc_xive_connect_vcpu(struct kvm_device *dev,
        struct kvmppc_xive *xive = dev->private;
        struct kvmppc_xive_vcpu *xc;
        int i, r = -EBUSY;
+       u32 vp_id;
 
        pr_devel("connect_vcpu(cpu=%d)\n", cpu);
 
@@ -1228,25 +1229,32 @@ int kvmppc_xive_connect_vcpu(struct kvm_device *dev,
                return -EPERM;
        if (vcpu->arch.irq_type != KVMPPC_IRQ_DEFAULT)
                return -EBUSY;
-       if (kvmppc_xive_find_server(vcpu->kvm, cpu)) {
-               pr_devel("Duplicate !\n");
-               return -EEXIST;
-       }
        if (cpu >= (KVM_MAX_VCPUS * vcpu->kvm->arch.emul_smt_mode)) {
                pr_devel("Out of bounds !\n");
                return -EINVAL;
        }
-       xc = kzalloc(sizeof(*xc), GFP_KERNEL);
-       if (!xc)
-               return -ENOMEM;
 
        /* We need to synchronize with queue provisioning */
        mutex_lock(&xive->lock);
+
+       vp_id = kvmppc_xive_vp(xive, cpu);
+       if (kvmppc_xive_vp_in_use(xive->kvm, vp_id)) {
+               pr_devel("Duplicate !\n");
+               r = -EEXIST;
+               goto bail;
+       }
+
+       xc = kzalloc(sizeof(*xc), GFP_KERNEL);
+       if (!xc) {
+               r = -ENOMEM;
+               goto bail;
+       }
+
        vcpu->arch.xive_vcpu = xc;
        xc->xive = xive;
        xc->vcpu = vcpu;
        xc->server_num = cpu;
-       xc->vp_id = kvmppc_xive_vp(xive, cpu);
+       xc->vp_id = vp_id;
        xc->mfrr = 0xff;
        xc->valid = true;
 
index 955b820ffd6da64f7c4471db47b271bbc1e8fafe..fe3ed50e081867676ce8af7a4930cfe1ccebd9fe 100644 (file)
@@ -220,6 +220,18 @@ static inline u32 kvmppc_xive_vp(struct kvmppc_xive *xive, u32 server)
        return xive->vp_base + kvmppc_pack_vcpu_id(xive->kvm, server);
 }
 
+static inline bool kvmppc_xive_vp_in_use(struct kvm *kvm, u32 vp_id)
+{
+       struct kvm_vcpu *vcpu = NULL;
+       int i;
+
+       kvm_for_each_vcpu(i, vcpu, kvm) {
+               if (vcpu->arch.xive_vcpu && vp_id == vcpu->arch.xive_vcpu->vp_id)
+                       return true;
+       }
+       return false;
+}
+
 /*
  * Mapping between guest priorities and host priorities
  * is as follow.
index 248c1ea9e7881f2ebfc09f2149f5f7a4158ee413..78b906ffa0d2b8bc886fd2c004836d1bac122497 100644 (file)
@@ -106,6 +106,7 @@ int kvmppc_xive_native_connect_vcpu(struct kvm_device *dev,
        struct kvmppc_xive *xive = dev->private;
        struct kvmppc_xive_vcpu *xc = NULL;
        int rc;
+       u32 vp_id;
 
        pr_devel("native_connect_vcpu(server=%d)\n", server_num);
 
@@ -124,7 +125,8 @@ int kvmppc_xive_native_connect_vcpu(struct kvm_device *dev,
 
        mutex_lock(&xive->lock);
 
-       if (kvmppc_xive_find_server(vcpu->kvm, server_num)) {
+       vp_id = kvmppc_xive_vp(xive, server_num);
+       if (kvmppc_xive_vp_in_use(xive->kvm, vp_id)) {
                pr_devel("Duplicate !\n");
                rc = -EEXIST;
                goto bail;
@@ -141,7 +143,7 @@ int kvmppc_xive_native_connect_vcpu(struct kvm_device *dev,
        xc->vcpu = vcpu;
        xc->server_num = server_num;
 
-       xc->vp_id = kvmppc_xive_vp(xive, server_num);
+       xc->vp_id = vp_id;
        xc->valid = true;
        vcpu->arch.irq_type = KVMPPC_IRQ_XIVE;
 
index 02a59946a78af46416e9d949047ad3fefe3fc159..be3517ef0574d0911f6d63b530b33954c8ca343d 100644 (file)
@@ -1141,6 +1141,19 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
                goto out_addrs;
        }
 
+       /*
+        * If we have seen a tail call, we need a second pass.
+        * This is because bpf_jit_emit_common_epilogue() is called
+        * from bpf_jit_emit_tail_call() with a not yet stable ctx->seen.
+        */
+       if (cgctx.seen & SEEN_TAILCALL) {
+               cgctx.idx = 0;
+               if (bpf_jit_build_body(fp, 0, &cgctx, addrs, false)) {
+                       fp = org_fp;
+                       goto out_addrs;
+               }
+       }
+
        /*
         * Pretend to build prologue, given the features we've seen.  This will
         * update ctgtx.idx as it pretends to output instructions, then we can
index 6bc24a47e9ef956e654ea022b4e6a9b52c0903df..6f300ab7f0e9b368114d65232d59d0a355d1201d 100644 (file)
@@ -42,7 +42,7 @@ void pnv_pcibios_bus_add_device(struct pci_dev *pdev)
 {
        struct pci_dn *pdn = pci_get_pdn(pdev);
 
-       if (eeh_has_flag(EEH_FORCE_DISABLED))
+       if (!pdn || eeh_has_flag(EEH_FORCE_DISABLED))
                return;
 
        dev_dbg(&pdev->dev, "EEH: Setting up device\n");
index fbd6e6b7bbf28c4ac806681e4abd42e488504af8..13e25169934665e6655c780def5d3d056775d124 100644 (file)
@@ -146,20 +146,25 @@ static int pnv_smp_cpu_disable(void)
        return 0;
 }
 
+static void pnv_flush_interrupts(void)
+{
+       if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+               if (xive_enabled())
+                       xive_flush_interrupt();
+               else
+                       icp_opal_flush_interrupt();
+       } else {
+               icp_native_flush_interrupt();
+       }
+}
+
 static void pnv_smp_cpu_kill_self(void)
 {
+       unsigned long srr1, unexpected_mask, wmask;
        unsigned int cpu;
-       unsigned long srr1, wmask;
        u64 lpcr_val;
 
        /* Standard hot unplug procedure */
-       /*
-        * This hard disables local interurpts, ensuring we have no lazy
-        * irqs pending.
-        */
-       WARN_ON(irqs_disabled());
-       hard_irq_disable();
-       WARN_ON(lazy_irq_pending());
 
        idle_task_exit();
        current->active_mm = NULL; /* for sanity */
@@ -172,6 +177,27 @@ static void pnv_smp_cpu_kill_self(void)
        if (cpu_has_feature(CPU_FTR_ARCH_207S))
                wmask = SRR1_WAKEMASK_P8;
 
+       /*
+        * This turns the irq soft-disabled state we're called with, into a
+        * hard-disabled state with pending irq_happened interrupts cleared.
+        *
+        * PACA_IRQ_DEC   - Decrementer should be ignored.
+        * PACA_IRQ_HMI   - Can be ignored, processing is done in real mode.
+        * PACA_IRQ_DBELL, EE, PMI - Unexpected.
+        */
+       hard_irq_disable();
+       if (generic_check_cpu_restart(cpu))
+               goto out;
+
+       unexpected_mask = ~(PACA_IRQ_DEC | PACA_IRQ_HMI | PACA_IRQ_HARD_DIS);
+       if (local_paca->irq_happened & unexpected_mask) {
+               if (local_paca->irq_happened & PACA_IRQ_EE)
+                       pnv_flush_interrupts();
+               DBG("CPU%d Unexpected exit while offline irq_happened=%lx!\n",
+                               cpu, local_paca->irq_happened);
+       }
+       local_paca->irq_happened = PACA_IRQ_HARD_DIS;
+
        /*
         * We don't want to take decrementer interrupts while we are
         * offline, so clear LPCR:PECE1. We keep PECE2 (and
@@ -197,6 +223,7 @@ static void pnv_smp_cpu_kill_self(void)
 
                srr1 = pnv_cpu_offline(cpu);
 
+               WARN_ON_ONCE(!irqs_disabled());
                WARN_ON(lazy_irq_pending());
 
                /*
@@ -212,13 +239,7 @@ static void pnv_smp_cpu_kill_self(void)
                 */
                if (((srr1 & wmask) == SRR1_WAKEEE) ||
                    ((srr1 & wmask) == SRR1_WAKEHVI)) {
-                       if (cpu_has_feature(CPU_FTR_ARCH_300)) {
-                               if (xive_enabled())
-                                       xive_flush_interrupt();
-                               else
-                                       icp_opal_flush_interrupt();
-                       } else
-                               icp_native_flush_interrupt();
+                       pnv_flush_interrupts();
                } else if ((srr1 & wmask) == SRR1_WAKEHDBELL) {
                        unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER);
                        asm volatile(PPC_MSGCLR(%0) : : "r" (msg));
@@ -266,7 +287,7 @@ static void pnv_smp_cpu_kill_self(void)
         */
        lpcr_val = mfspr(SPRN_LPCR) | (u64)LPCR_PECE1;
        pnv_program_cpu_hotplug_lpcr(cpu, lpcr_val);
-
+out:
        DBG("CPU%d coming online...\n", cpu);
 }
 
index 07ceee8b17470a0e0aa9e6b4c03e378c0134d699..75604fec1b1b53fa954602b845f4d959494e595d 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <asm/asm.h>
 
-#ifdef CONFIG_GENERIC_BUG
 #define __INSN_LENGTH_MASK  _UL(0x3)
 #define __INSN_LENGTH_32    _UL(0x3)
 #define __COMPRESSED_INSN_MASK _UL(0xffff)
@@ -20,7 +19,6 @@
 #define __BUG_INSN_32  _UL(0x00100073) /* ebreak */
 #define __BUG_INSN_16  _UL(0x9002) /* c.ebreak */
 
-#ifndef __ASSEMBLY__
 typedef u32 bug_insn_t;
 
 #ifdef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
@@ -43,6 +41,7 @@ typedef u32 bug_insn_t;
        RISCV_SHORT " %2"
 #endif
 
+#ifdef CONFIG_GENERIC_BUG
 #define __BUG_FLAGS(flags)                                     \
 do {                                                           \
        __asm__ __volatile__ (                                  \
@@ -58,14 +57,10 @@ do {                                                                \
                  "i" (flags),                                  \
                  "i" (sizeof(struct bug_entry)));              \
 } while (0)
-
-#endif /* !__ASSEMBLY__ */
 #else /* CONFIG_GENERIC_BUG */
-#ifndef __ASSEMBLY__
 #define __BUG_FLAGS(flags) do {                                        \
        __asm__ __volatile__ ("ebreak\n");                      \
 } while (0)
-#endif /* !__ASSEMBLY__ */
 #endif /* CONFIG_GENERIC_BUG */
 
 #define BUG() do {                                             \
@@ -79,15 +74,10 @@ do {                                                                \
 
 #include <asm-generic/bug.h>
 
-#ifndef __ASSEMBLY__
-
 struct pt_regs;
 struct task_struct;
 
-extern void die(struct pt_regs *regs, const char *str);
-extern void do_trap(struct pt_regs *regs, int signo, int code,
-       unsigned long addr);
-
-#endif /* !__ASSEMBLY__ */
+void die(struct pt_regs *regs, const char *str);
+void do_trap(struct pt_regs *regs, int signo, int code, unsigned long addr);
 
 #endif /* _ASM_RISCV_BUG_H */
index fc1189ad377728f7f307796731b43f3b5310f8ee..3ba4d93721d302ec79e94d96dc4bd1dac940c56e 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/types.h>
 #include <asm/mmiowb.h>
+#include <asm/pgtable.h>
 
 extern void __iomem *ioremap(phys_addr_t offset, unsigned long size);
 
@@ -161,6 +162,12 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
 #define writeq(v,c)    ({ __io_bw(); writeq_cpu((v),(c)); __io_aw(); })
 #endif
 
+/*
+ *  I/O port access constants.
+ */
+#define IO_SPACE_LIMIT         (PCI_IO_SIZE - 1)
+#define PCI_IOBASE             ((void __iomem *)PCI_IO_START)
+
 /*
  * Emulation routines for the port-mapped IO space used by some PCI drivers.
  * These are defined as being "fully synchronous", but also "not guaranteed to
index 75576424c0f70c20d34e95419224a08837ab363b..6e1b0e0325eb92a26bba60f7c08c7c32a37a45d0 100644 (file)
@@ -7,6 +7,9 @@
 #ifndef _ASM_RISCV_IRQ_H
 #define _ASM_RISCV_IRQ_H
 
+#include <linux/interrupt.h>
+#include <linux/linkage.h>
+
 #define NR_IRQS         0
 
 void riscv_timer_interrupt(void);
index 42292d99cc740d02fb210fe92e9813bf2206cc05..d3221017194dd19bfe824683ecb700dee60d6e7b 100644 (file)
@@ -7,6 +7,7 @@
 #define _ASM_RISCV_PGTABLE_H
 
 #include <linux/mmzone.h>
+#include <linux/sizes.h>
 
 #include <asm/pgtable-bits.h>
 
@@ -86,6 +87,7 @@ extern pgd_t swapper_pg_dir[];
 #define VMALLOC_SIZE     (KERN_VIRT_SIZE >> 1)
 #define VMALLOC_END      (PAGE_OFFSET - 1)
 #define VMALLOC_START    (PAGE_OFFSET - VMALLOC_SIZE)
+#define PCI_IO_SIZE      SZ_16M
 
 /*
  * Roughly size the vmemmap space to be large enough to fit enough
@@ -100,7 +102,10 @@ extern pgd_t swapper_pg_dir[];
 
 #define vmemmap                ((struct page *)VMEMMAP_START)
 
-#define FIXADDR_TOP      (VMEMMAP_START)
+#define PCI_IO_END       VMEMMAP_START
+#define PCI_IO_START     (PCI_IO_END - PCI_IO_SIZE)
+#define FIXADDR_TOP      PCI_IO_START
+
 #ifdef CONFIG_64BIT
 #define FIXADDR_SIZE     PMD_SIZE
 #else
@@ -184,10 +189,7 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot)
        return __pte((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot));
 }
 
-static inline pte_t mk_pte(struct page *page, pgprot_t prot)
-{
-       return pfn_pte(page_to_pfn(page), prot);
-}
+#define mk_pte(page, prot)       pfn_pte(page_to_pfn(page), prot)
 
 #define pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 
@@ -428,9 +430,7 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma,
 #define __pte_to_swp_entry(pte)        ((swp_entry_t) { pte_val(pte) })
 #define __swp_entry_to_pte(x)  ((pte_t) { (x).val })
 
-#ifdef CONFIG_FLATMEM
 #define kern_addr_valid(addr)   (1) /* FIXME */
-#endif
 
 extern void *dtb_early_va;
 extern void setup_bootmem(void);
index f0227bdce0f0614925ae772dc80588b8828f2ec0..ee4f0ac62c9d7dce882489ae343965b3856c8cee 100644 (file)
@@ -6,6 +6,7 @@
 #ifndef _ASM_RISCV_SWITCH_TO_H
 #define _ASM_RISCV_SWITCH_TO_H
 
+#include <linux/sched/task_stack.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 #include <asm/csr.h>
index b1ade9a49347796cb550696f9c111af8ea9a9ead..a5ad00043104d3c16275f271649af64755c8de0e 100644 (file)
@@ -10,6 +10,7 @@
 #include <asm/processor.h>
 #include <asm/hwcap.h>
 #include <asm/smp.h>
+#include <asm/switch_to.h>
 
 unsigned long elf_hwcap __read_mostly;
 #ifdef CONFIG_FPU
diff --git a/arch/riscv/kernel/head.h b/arch/riscv/kernel/head.h
new file mode 100644 (file)
index 0000000..105fb04
--- /dev/null
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 SiFive, Inc.
+ */
+#ifndef __ASM_HEAD_H
+#define __ASM_HEAD_H
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+extern atomic_t hart_lottery;
+
+asmlinkage void do_page_fault(struct pt_regs *regs);
+asmlinkage void __init setup_vm(uintptr_t dtb_pa);
+
+extern void *__cpu_up_stack_pointer[];
+extern void *__cpu_up_task_pointer[];
+
+void __init parse_dtb(void);
+
+#endif /* __ASM_HEAD_H */
index 6d8659388c4922e1bb4bf5f67121e3407f570129..fffac6ddb0e00412fa76546cfdc0166eb5d4ed30 100644 (file)
@@ -24,7 +24,7 @@ int arch_show_interrupts(struct seq_file *p, int prec)
        return 0;
 }
 
-asmlinkage void __irq_entry do_IRQ(struct pt_regs *regs)
+asmlinkage __visible void __irq_entry do_IRQ(struct pt_regs *regs)
 {
        struct pt_regs *old_regs = set_irq_regs(regs);
 
index c9ae48333114ededcd0604e1a6bbf3291995e289..e264e59e596e80d71166107f7b5763f74fbf02c8 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/elf.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/moduleloader.h>
 
 unsigned long module_emit_got_entry(struct module *mod, unsigned long val)
 {
index fb3a082362eb87554ff297f3e026d9663c5a8044..85e3c39bb60bcfa4634212cb3c8a52d06953cf89 100644 (file)
@@ -7,6 +7,7 @@
  * Copyright (C) 2017 SiFive
  */
 
+#include <linux/cpu.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/sched/task_stack.h>
@@ -19,6 +20,7 @@
 #include <asm/csr.h>
 #include <asm/string.h>
 #include <asm/switch_to.h>
+#include <asm/thread_info.h>
 
 extern asmlinkage void ret_from_fork(void);
 extern asmlinkage void ret_from_kernel_thread(void);
index 3687514383669028d9717c35b956b21af5bb1c0e..1252113ef8b2ca9bedd507acdaf7343e5ced13eb 100644 (file)
@@ -148,7 +148,7 @@ long arch_ptrace(struct task_struct *child, long request,
  * Allows PTRACE_SYSCALL to work.  These are called from entry.S in
  * {handle,ret_from}_syscall.
  */
-void do_syscall_trace_enter(struct pt_regs *regs)
+__visible void do_syscall_trace_enter(struct pt_regs *regs)
 {
        if (test_thread_flag(TIF_SYSCALL_TRACE))
                if (tracehook_report_syscall_entry(regs))
@@ -162,7 +162,7 @@ void do_syscall_trace_enter(struct pt_regs *regs)
        audit_syscall_entry(regs->a7, regs->a0, regs->a1, regs->a2, regs->a3);
 }
 
-void do_syscall_trace_exit(struct pt_regs *regs)
+__visible void do_syscall_trace_exit(struct pt_regs *regs)
 {
        audit_syscall_exit(regs);
 
index d0fe623bfb8f31c9a56e9f90ce25ec2b192a2a89..aa56bb135ec49f25dbe989e8b425b1a67c80a740 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <linux/reboot.h>
+#include <linux/pm.h>
 #include <asm/sbi.h>
 
 static void default_power_off(void)
index a990a6cb184f2e2c66a1abeafe3958020a9b2f2a..845ae0e121159719115cc818e096aa0bc621970b 100644 (file)
@@ -24,6 +24,8 @@
 #include <asm/tlbflush.h>
 #include <asm/thread_info.h>
 
+#include "head.h"
+
 #ifdef CONFIG_DUMMY_CONSOLE
 struct screen_info screen_info = {
        .orig_video_lines       = 30,
index b14d7647d80014fd1982487b726b563def29775a..d0f6f212f5dfde4e8ef044af3b7c2bca316fabcf 100644 (file)
@@ -26,7 +26,7 @@ struct rt_sigframe {
 
 #ifdef CONFIG_FPU
 static long restore_fp_state(struct pt_regs *regs,
-                            union __riscv_fp_state *sc_fpregs)
+                            union __riscv_fp_state __user *sc_fpregs)
 {
        long err;
        struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
@@ -53,7 +53,7 @@ static long restore_fp_state(struct pt_regs *regs,
 }
 
 static long save_fp_state(struct pt_regs *regs,
-                         union __riscv_fp_state *sc_fpregs)
+                         union __riscv_fp_state __user *sc_fpregs)
 {
        long err;
        struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
@@ -292,8 +292,8 @@ static void do_signal(struct pt_regs *regs)
  * notification of userspace execution resumption
  * - triggered by the _TIF_WORK_MASK flags
  */
-asmlinkage void do_notify_resume(struct pt_regs *regs,
-       unsigned long thread_info_flags)
+asmlinkage __visible void do_notify_resume(struct pt_regs *regs,
+                                          unsigned long thread_info_flags)
 {
        /* Handle pending signal delivery */
        if (thread_info_flags & _TIF_SIGPENDING)
index b18cd6c8e8fbbf8383b0149da14be73b3c89f328..5c9ec78422c229490556295c7bbdb65def2a2fae 100644 (file)
@@ -8,7 +8,9 @@
  * Copyright (C) 2017 SiFive
  */
 
+#include <linux/cpu.h>
 #include <linux/interrupt.h>
+#include <linux/profile.h>
 #include <linux/smp.h>
 #include <linux/sched.h>
 #include <linux/seq_file.h>
index 18ae6da5115e53d4612f84dc8a0898b863e8b55e..261f4087cc39e177fbc063b003dfafc57488cc18 100644 (file)
@@ -29,6 +29,9 @@
 #include <asm/tlbflush.h>
 #include <asm/sections.h>
 #include <asm/sbi.h>
+#include <asm/smp.h>
+
+#include "head.h"
 
 void *__cpu_up_stack_pointer[NR_CPUS];
 void *__cpu_up_task_pointer[NR_CPUS];
@@ -130,7 +133,7 @@ void __init smp_cpus_done(unsigned int max_cpus)
 /*
  * C entry point for a secondary processor.
  */
-asmlinkage void __init smp_callin(void)
+asmlinkage __visible void __init smp_callin(void)
 {
        struct mm_struct *mm = &init_mm;
 
index e5dd52d8f6332b4566787243b7a90313939f97d0..f1ead9df96ca55b11fc7319cfc7b852a7d019676 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/syscalls.h>
 #include <asm-generic/syscalls.h>
 #include <asm/vdso.h>
+#include <asm/syscall.h>
 
 #undef __SYSCALL
 #define __SYSCALL(nr, call)    [nr] = (call),
index 9dd1f2e64db12089aac4cdd8d65ec9d543950a08..6a53c02e9c734c6db04e6236580ace56f0d27b19 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/clocksource.h>
 #include <linux/delay.h>
 #include <asm/sbi.h>
+#include <asm/processor.h>
 
 unsigned long riscv_timebase;
 EXPORT_SYMBOL_GPL(riscv_timebase);
index 1ac75f7d0bffd8d984df3d64128ac84660ab9157..473de3ae8bb75766ded32ec9ae35b1d4549e156b 100644 (file)
@@ -3,6 +3,7 @@
  * Copyright (C) 2012 Regents of the University of California
  */
 
+#include <linux/cpu.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/sched.h>
@@ -83,7 +84,7 @@ static void do_trap_error(struct pt_regs *regs, int signo, int code,
 }
 
 #define DO_ERROR_INFO(name, signo, code, str)                          \
-asmlinkage void name(struct pt_regs *regs)                             \
+asmlinkage __visible void name(struct pt_regs *regs)                   \
 {                                                                      \
        do_trap_error(regs, signo, code, regs->sepc, "Oops - " str);    \
 }
@@ -111,7 +112,6 @@ DO_ERROR_INFO(do_trap_ecall_s,
 DO_ERROR_INFO(do_trap_ecall_m,
        SIGILL, ILL_ILLTRP, "environment call from M-mode");
 
-#ifdef CONFIG_GENERIC_BUG
 static inline unsigned long get_break_insn_length(unsigned long pc)
 {
        bug_insn_t insn;
@@ -120,28 +120,15 @@ static inline unsigned long get_break_insn_length(unsigned long pc)
                return 0;
        return (((insn & __INSN_LENGTH_MASK) == __INSN_LENGTH_32) ? 4UL : 2UL);
 }
-#endif /* CONFIG_GENERIC_BUG */
 
-asmlinkage void do_trap_break(struct pt_regs *regs)
+asmlinkage __visible void do_trap_break(struct pt_regs *regs)
 {
-       if (user_mode(regs)) {
-               force_sig_fault(SIGTRAP, TRAP_BRKPT,
-                               (void __user *)(regs->sepc));
-               return;
-       }
-#ifdef CONFIG_GENERIC_BUG
-       {
-               enum bug_trap_type type;
-
-               type = report_bug(regs->sepc, regs);
-               if (type == BUG_TRAP_TYPE_WARN) {
-                       regs->sepc += get_break_insn_length(regs->sepc);
-                       return;
-               }
-       }
-#endif /* CONFIG_GENERIC_BUG */
-
-       die(regs, "Kernel BUG");
+       if (user_mode(regs))
+               force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->sepc);
+       else if (report_bug(regs->sepc, regs) == BUG_TRAP_TYPE_WARN)
+               regs->sepc += get_break_insn_length(regs->sepc);
+       else
+               die(regs, "Kernel BUG");
 }
 
 #ifdef CONFIG_GENERIC_BUG
index c9c21e0d56417cf3ebb3ccab116f44710da1b31f..484d95a70907afba706aec216ffc16450fb39e9d 100644 (file)
@@ -6,6 +6,7 @@
  * Copyright (C) 2015 Regents of the University of California
  */
 
+#include <linux/elf.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/binfmts.h>
@@ -25,7 +26,7 @@ static union {
        struct vdso_data        data;
        u8                      page[PAGE_SIZE];
 } vdso_data_store __page_aligned_data;
-struct vdso_data *vdso_data = &vdso_data_store.data;
+static struct vdso_data *vdso_data = &vdso_data_store.data;
 
 static int __init vdso_init(void)
 {
index beeb5d7f92ea5aaccefc10e41ea036f5554da81a..ca66d44156b628d087fe1b2fc75c35f27f14e38f 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/mm.h>
 #include <asm/tlbflush.h>
 #include <asm/cacheflush.h>
+#include <asm/mmu_context.h>
 
 /*
  * When necessary, performs a deferred icache flush for the given MM context,
index 96add1427a75a5790acd3add530f33422c0808d9..247b8c859c448ae16467b3c8e8b620adfaa94dfd 100644 (file)
@@ -18,6 +18,8 @@
 #include <asm/ptrace.h>
 #include <asm/tlbflush.h>
 
+#include "../kernel/head.h"
+
 /*
  * This routine handles page faults.  It determines the address and the
  * problem, and then passes it off to one of the appropriate routines.
index 83f7d12042fbc781ab91a3a90c70043400f66c81..573463d1c799a0425e550681507643a9e60fe1cb 100644 (file)
@@ -19,6 +19,8 @@
 #include <asm/pgtable.h>
 #include <asm/io.h>
 
+#include "../kernel/head.h"
+
 unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]
                                                        __page_aligned_bss;
 EXPORT_SYMBOL(empty_zero_page);
@@ -337,8 +339,7 @@ static uintptr_t __init best_map_size(phys_addr_t base, phys_addr_t size)
  */
 
 #ifndef __riscv_cmodel_medany
-#error "setup_vm() is called from head.S before relocate so it should "
-       "not use absolute addressing."
+#error "setup_vm() is called from head.S before relocate so it should not use absolute addressing."
 #endif
 
 asmlinkage void __init setup_vm(uintptr_t dtb_pa)
@@ -458,7 +459,7 @@ void __init paging_init(void)
        zone_sizes_init();
 }
 
-#ifdef CONFIG_SPARSEMEM
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
 int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
                               struct vmem_altmap *altmap)
 {
index 2e637ad71c05f099b5e4e45f1abb39bac5991d64..a9ffff3277c77fa7b1847e45b890689aed909d7c 100644 (file)
@@ -142,7 +142,7 @@ static irqreturn_t l2_int_handler(int irq, void *device)
        return IRQ_HANDLED;
 }
 
-int __init sifive_l2_init(void)
+static int __init sifive_l2_init(void)
 {
        struct device_node *np;
        struct resource res;
index 596ca7cc4d7b88a7c37b93cc58d87651ffe4bd9d..5367950510f695ae4c970dfa511f78456259a933 100644 (file)
@@ -101,10 +101,18 @@ static void handle_relocs(unsigned long offset)
        dynsym = (Elf64_Sym *) vmlinux.dynsym_start;
        for (rela = rela_start; rela < rela_end; rela++) {
                loc = rela->r_offset + offset;
-               val = rela->r_addend + offset;
+               val = rela->r_addend;
                r_sym = ELF64_R_SYM(rela->r_info);
-               if (r_sym)
-                       val += dynsym[r_sym].st_value;
+               if (r_sym) {
+                       if (dynsym[r_sym].st_shndx != SHN_UNDEF)
+                               val += dynsym[r_sym].st_value + offset;
+               } else {
+                       /*
+                        * 0 == undefined symbol table index (STN_UNDEF),
+                        * used for R_390_RELATIVE, only add KASLR offset
+                        */
+                       val += offset;
+               }
                r_type = ELF64_R_TYPE(rela->r_info);
                rc = arch_kexec_do_relocs(r_type, (void *) loc, val, 0);
                if (rc)
index d827b5b9a32cd6a44d7beddba18b96cdcbb18aa9..eaaefeceef6f0810c53108b390420b351257a052 100644 (file)
@@ -35,6 +35,7 @@ struct unwind_state {
        struct task_struct *task;
        struct pt_regs *regs;
        unsigned long sp, ip;
+       bool reuse_sp;
        int graph_idx;
        bool reliable;
        bool error;
index b9d8fe45737aa2e529cb9eec244349e121803858..8f8456816d83e890a3f3150ccec184f21810a509 100644 (file)
@@ -69,18 +69,26 @@ DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL);
 static ssize_t show_idle_time(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
+       unsigned long long now, idle_time, idle_enter, idle_exit, in_idle;
        struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id);
-       unsigned long long now, idle_time, idle_enter, idle_exit;
        unsigned int seq;
 
        do {
-               now = get_tod_clock();
                seq = read_seqcount_begin(&idle->seqcount);
                idle_time = READ_ONCE(idle->idle_time);
                idle_enter = READ_ONCE(idle->clock_idle_enter);
                idle_exit = READ_ONCE(idle->clock_idle_exit);
        } while (read_seqcount_retry(&idle->seqcount, seq));
-       idle_time += idle_enter ? ((idle_exit ? : now) - idle_enter) : 0;
+       in_idle = 0;
+       now = get_tod_clock();
+       if (idle_enter) {
+               if (idle_exit) {
+                       in_idle = idle_exit - idle_enter;
+               } else if (now > idle_enter) {
+                       in_idle = now - idle_enter;
+               }
+       }
+       idle_time += in_idle;
        return sprintf(buf, "%llu\n", idle_time >> 12);
 }
 DEVICE_ATTR(idle_time_us, 0444, show_idle_time, NULL);
@@ -88,17 +96,24 @@ DEVICE_ATTR(idle_time_us, 0444, show_idle_time, NULL);
 u64 arch_cpu_idle_time(int cpu)
 {
        struct s390_idle_data *idle = &per_cpu(s390_idle, cpu);
-       unsigned long long now, idle_enter, idle_exit;
+       unsigned long long now, idle_enter, idle_exit, in_idle;
        unsigned int seq;
 
        do {
-               now = get_tod_clock();
                seq = read_seqcount_begin(&idle->seqcount);
                idle_enter = READ_ONCE(idle->clock_idle_enter);
                idle_exit = READ_ONCE(idle->clock_idle_exit);
        } while (read_seqcount_retry(&idle->seqcount, seq));
-
-       return cputime_to_nsecs(idle_enter ? ((idle_exit ?: now) - idle_enter) : 0);
+       in_idle = 0;
+       now = get_tod_clock();
+       if (idle_enter) {
+               if (idle_exit) {
+                       in_idle = idle_exit - idle_enter;
+               } else if (now > idle_enter) {
+                       in_idle = now - idle_enter;
+               }
+       }
+       return cputime_to_nsecs(in_idle);
 }
 
 void arch_cpu_idle_enter(void)
index 3b664cb3ec4d3b57ba3ca53fa2c3af1d8f92f9e1..d5035de9020e738819a06b9e0ecf74b77879ac4d 100644 (file)
@@ -27,6 +27,7 @@ int arch_kexec_do_relocs(int r_type, void *loc, unsigned long val,
                *(u32 *)loc = val;
                break;
        case R_390_64:          /* Direct 64 bit.  */
+       case R_390_GLOB_DAT:
                *(u64 *)loc = val;
                break;
        case R_390_PC16:        /* PC relative 16 bit.  */
index 8fc9daae47a2ee89a25161ff9775673ee9f37dd8..a8204f952315d9edda9090a1d3762e37cc5fb99c 100644 (file)
@@ -46,10 +46,15 @@ bool unwind_next_frame(struct unwind_state *state)
 
        regs = state->regs;
        if (unlikely(regs)) {
-               sp = READ_ONCE_NOCHECK(regs->gprs[15]);
-               if (unlikely(outside_of_stack(state, sp))) {
-                       if (!update_stack_info(state, sp))
-                               goto out_err;
+               if (state->reuse_sp) {
+                       sp = state->sp;
+                       state->reuse_sp = false;
+               } else {
+                       sp = READ_ONCE_NOCHECK(regs->gprs[15]);
+                       if (unlikely(outside_of_stack(state, sp))) {
+                               if (!update_stack_info(state, sp))
+                                       goto out_err;
+                       }
                }
                sf = (struct stack_frame *) sp;
                ip = READ_ONCE_NOCHECK(sf->gprs[8]);
@@ -107,9 +112,9 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
 {
        struct stack_info *info = &state->stack_info;
        unsigned long *mask = &state->stack_mask;
+       bool reliable, reuse_sp;
        struct stack_frame *sf;
        unsigned long ip;
-       bool reliable;
 
        memset(state, 0, sizeof(*state));
        state->task = task;
@@ -134,10 +139,12 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
        if (regs) {
                ip = READ_ONCE_NOCHECK(regs->psw.addr);
                reliable = true;
+               reuse_sp = true;
        } else {
                sf = (struct stack_frame *) sp;
                ip = READ_ONCE_NOCHECK(sf->gprs[8]);
                reliable = false;
+               reuse_sp = false;
        }
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
@@ -151,5 +158,6 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
        state->sp = sp;
        state->ip = ip;
        state->reliable = reliable;
+       state->reuse_sp = reuse_sp;
 }
 EXPORT_SYMBOL_GPL(__unwind_start);
index 510a18299196f3b797be51fd22b2bbfbe5cd003f..a51c892f14f3ee5bd393ed74003c96fd80268979 100644 (file)
@@ -298,16 +298,16 @@ static int cmm_timeout_handler(struct ctl_table *ctl, int write,
        }
 
        if (write) {
-               len = *lenp;
-               if (copy_from_user(buf, buffer,
-                                  len > sizeof(buf) ? sizeof(buf) : len))
+               len = min(*lenp, sizeof(buf));
+               if (copy_from_user(buf, buffer, len))
                        return -EFAULT;
-               buf[sizeof(buf) - 1] = '\0';
+               buf[len - 1] = '\0';
                cmm_skip_blanks(buf, &p);
                nr = simple_strtoul(p, &p, 0);
                cmm_skip_blanks(p, &p);
                seconds = simple_strtoul(p, &p, 0);
                cmm_set_timeout(nr, seconds);
+               *ppos += *lenp;
        } else {
                len = sprintf(buf, "%ld %ld\n",
                              cmm_timeout_pages, cmm_timeout_seconds);
@@ -315,9 +315,9 @@ static int cmm_timeout_handler(struct ctl_table *ctl, int write,
                        len = *lenp;
                if (copy_to_user(buffer, buf, len))
                        return -EFAULT;
+               *lenp = len;
+               *ppos += len;
        }
-       *lenp = len;
-       *ppos += len;
        return 0;
 }
 
index 612535cd97065beecb42bb59c4d2d4ca8252f6c4..6627d7c30f3700954ca655527b3490dbf28dacde 100644 (file)
@@ -1403,8 +1403,12 @@ static blk_status_t ubd_queue_rq(struct blk_mq_hw_ctx *hctx,
 
        spin_unlock_irq(&ubd_dev->lock);
 
-       if (ret < 0)
-               blk_mq_requeue_request(req, true);
+       if (ret < 0) {
+               if (ret == -ENOMEM)
+                       res = BLK_STS_RESOURCE;
+               else
+                       res = BLK_STS_DEV_RESOURCE;
+       }
 
        return res;
 }
index d6662fdef3001da7465dda8df8aed58a48fe6f58..82bc60c8acb240c29f925df7dde03ac724edf3b4 100644 (file)
@@ -13,6 +13,7 @@
 #include <asm/e820/types.h>
 #include <asm/setup.h>
 #include <asm/desc.h>
+#include <asm/boot.h>
 
 #include "../string.h"
 #include "eboot.h"
@@ -813,7 +814,8 @@ efi_main(struct efi_config *c, struct boot_params *boot_params)
                status = efi_relocate_kernel(sys_table, &bzimage_addr,
                                             hdr->init_size, hdr->init_size,
                                             hdr->pref_address,
-                                            hdr->kernel_alignment);
+                                            hdr->kernel_alignment,
+                                            LOAD_PHYSICAL_ADDR);
                if (status != EFI_SUCCESS) {
                        efi_printk(sys_table, "efi_relocate_kernel() failed!\n");
                        goto fail;
index 5b35b7ea5d7282d870b7d0d2a519620793deba76..26c36357c4c9c6b809abb04d07e43aba80675bf3 100644 (file)
@@ -377,7 +377,8 @@ static inline void perf_ibs_disable_event(struct perf_ibs *perf_ibs,
                                          struct hw_perf_event *hwc, u64 config)
 {
        config &= ~perf_ibs->cnt_mask;
-       wrmsrl(hwc->config_base, config);
+       if (boot_cpu_data.x86 == 0x10)
+               wrmsrl(hwc->config_base, config);
        config &= ~perf_ibs->enable_mask;
        wrmsrl(hwc->config_base, config);
 }
@@ -553,7 +554,8 @@ static struct perf_ibs perf_ibs_op = {
        },
        .msr                    = MSR_AMD64_IBSOPCTL,
        .config_mask            = IBS_OP_CONFIG_MASK,
-       .cnt_mask               = IBS_OP_MAX_CNT,
+       .cnt_mask               = IBS_OP_MAX_CNT | IBS_OP_CUR_CNT |
+                                 IBS_OP_CUR_CNT_RAND,
        .enable_mask            = IBS_OP_ENABLE,
        .valid_mask             = IBS_OP_VAL,
        .max_period             = IBS_OP_MAX_CNT << 4,
@@ -614,7 +616,7 @@ fail:
        if (event->attr.sample_type & PERF_SAMPLE_RAW)
                offset_max = perf_ibs->offset_max;
        else if (check_rip)
-               offset_max = 2;
+               offset_max = 3;
        else
                offset_max = 1;
        do {
index 74e80ed9c6c474551b57c6d8b4d548aeb3ea8e4d..05e43d0f430bcdfd89999dc3e31369b49ad0ca4c 100644 (file)
@@ -627,7 +627,7 @@ static struct topa *topa_alloc(int cpu, gfp_t gfp)
         * link as the 2nd entry in the table
         */
        if (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries)) {
-               TOPA_ENTRY(&tp->topa, 1)->base = page_to_phys(p);
+               TOPA_ENTRY(&tp->topa, 1)->base = page_to_phys(p) >> TOPA_SHIFT;
                TOPA_ENTRY(&tp->topa, 1)->end = 1;
        }
 
index 6fc2e06ab4c6f9dfa45feb6f8762c97546203b2d..86467f85c383100789d0430a80ffc4989d12af03 100644 (file)
@@ -502,10 +502,8 @@ void uncore_pmu_event_start(struct perf_event *event, int flags)
        local64_set(&event->hw.prev_count, uncore_read_counter(box, event));
        uncore_enable_event(box, event);
 
-       if (box->n_active == 1) {
-               uncore_enable_box(box);
+       if (box->n_active == 1)
                uncore_pmu_start_hrtimer(box);
-       }
 }
 
 void uncore_pmu_event_stop(struct perf_event *event, int flags)
@@ -529,10 +527,8 @@ void uncore_pmu_event_stop(struct perf_event *event, int flags)
                WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
                hwc->state |= PERF_HES_STOPPED;
 
-               if (box->n_active == 0) {
-                       uncore_disable_box(box);
+               if (box->n_active == 0)
                        uncore_pmu_cancel_hrtimer(box);
-               }
        }
 
        if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
@@ -778,6 +774,40 @@ static int uncore_pmu_event_init(struct perf_event *event)
        return ret;
 }
 
+static void uncore_pmu_enable(struct pmu *pmu)
+{
+       struct intel_uncore_pmu *uncore_pmu;
+       struct intel_uncore_box *box;
+
+       uncore_pmu = container_of(pmu, struct intel_uncore_pmu, pmu);
+       if (!uncore_pmu)
+               return;
+
+       box = uncore_pmu_to_box(uncore_pmu, smp_processor_id());
+       if (!box)
+               return;
+
+       if (uncore_pmu->type->ops->enable_box)
+               uncore_pmu->type->ops->enable_box(box);
+}
+
+static void uncore_pmu_disable(struct pmu *pmu)
+{
+       struct intel_uncore_pmu *uncore_pmu;
+       struct intel_uncore_box *box;
+
+       uncore_pmu = container_of(pmu, struct intel_uncore_pmu, pmu);
+       if (!uncore_pmu)
+               return;
+
+       box = uncore_pmu_to_box(uncore_pmu, smp_processor_id());
+       if (!box)
+               return;
+
+       if (uncore_pmu->type->ops->disable_box)
+               uncore_pmu->type->ops->disable_box(box);
+}
+
 static ssize_t uncore_get_attr_cpumask(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
@@ -803,6 +833,8 @@ static int uncore_pmu_register(struct intel_uncore_pmu *pmu)
                pmu->pmu = (struct pmu) {
                        .attr_groups    = pmu->type->attr_groups,
                        .task_ctx_nr    = perf_invalid_context,
+                       .pmu_enable     = uncore_pmu_enable,
+                       .pmu_disable    = uncore_pmu_disable,
                        .event_init     = uncore_pmu_event_init,
                        .add            = uncore_pmu_event_add,
                        .del            = uncore_pmu_event_del,
index f36f7bebbc1bbaca769c9f978efda52fa9e39897..bbfdaa720b4568ded56b575d366febf6e296e319 100644 (file)
@@ -441,18 +441,6 @@ static inline int uncore_freerunning_hw_config(struct intel_uncore_box *box,
        return -EINVAL;
 }
 
-static inline void uncore_disable_box(struct intel_uncore_box *box)
-{
-       if (box->pmu->type->ops->disable_box)
-               box->pmu->type->ops->disable_box(box);
-}
-
-static inline void uncore_enable_box(struct intel_uncore_box *box)
-{
-       if (box->pmu->type->ops->enable_box)
-               box->pmu->type->ops->enable_box(box);
-}
-
 static inline void uncore_disable_event(struct intel_uncore_box *box,
                                struct perf_event *event)
 {
index 50eb430b0ad8f0733906b31691c489fb8adb53f4..24d6598dea29b2d048d41ae5c545c1366312c615 100644 (file)
@@ -1189,7 +1189,7 @@ struct kvm_x86_ops {
        int (*set_nested_state)(struct kvm_vcpu *vcpu,
                                struct kvm_nested_state __user *user_kvm_nested_state,
                                struct kvm_nested_state *kvm_state);
-       void (*get_vmcs12_pages)(struct kvm_vcpu *vcpu);
+       bool (*get_vmcs12_pages)(struct kvm_vcpu *vcpu);
 
        int (*smi_allowed)(struct kvm_vcpu *vcpu);
        int (*pre_enter_smm)(struct kvm_vcpu *vcpu, char *smstate);
index e00c9e87593327e781d72ff9c3b5a2545fc986c0..ac9fc51e2b1862f5dff7264a1978f3d399b5c847 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <asm/cpufeatures.h>
 #include <asm/alternative.h>
+#include <linux/stringify.h>
 
 /*
  * The hypercall definitions differ in the low word of the %edx argument
@@ -20,8 +21,8 @@
  */
 
 /* Old port-based version */
-#define VMWARE_HYPERVISOR_PORT    "0x5658"
-#define VMWARE_HYPERVISOR_PORT_HB "0x5659"
+#define VMWARE_HYPERVISOR_PORT    0x5658
+#define VMWARE_HYPERVISOR_PORT_HB 0x5659
 
 /* Current vmcall / vmmcall version */
 #define VMWARE_HYPERVISOR_HB   BIT(0)
@@ -29,7 +30,8 @@
 
 /* The low bandwidth call. The low word of edx is presumed clear. */
 #define VMWARE_HYPERCALL                                               \
-       ALTERNATIVE_2("movw $" VMWARE_HYPERVISOR_PORT ", %%dx; inl (%%dx)", \
+       ALTERNATIVE_2("movw $" __stringify(VMWARE_HYPERVISOR_PORT) ", %%dx; " \
+                     "inl (%%dx), %%eax",                              \
                      "vmcall", X86_FEATURE_VMCALL,                     \
                      "vmmcall", X86_FEATURE_VMW_VMMCALL)
 
@@ -38,7 +40,8 @@
  * HB and OUT bits set.
  */
 #define VMWARE_HYPERCALL_HB_OUT                                                \
-       ALTERNATIVE_2("movw $" VMWARE_HYPERVISOR_PORT_HB ", %%dx; rep outsb", \
+       ALTERNATIVE_2("movw $" __stringify(VMWARE_HYPERVISOR_PORT_HB) ", %%dx; " \
+                     "rep outsb",                                      \
                      "vmcall", X86_FEATURE_VMCALL,                     \
                      "vmmcall", X86_FEATURE_VMW_VMMCALL)
 
@@ -47,7 +50,8 @@
  * HB bit set.
  */
 #define VMWARE_HYPERCALL_HB_IN                                         \
-       ALTERNATIVE_2("movw $" VMWARE_HYPERVISOR_PORT_HB ", %%dx; rep insb", \
+       ALTERNATIVE_2("movw $" __stringify(VMWARE_HYPERVISOR_PORT_HB) ", %%dx; " \
+                     "rep insb",                                       \
                      "vmcall", X86_FEATURE_VMCALL,                     \
                      "vmmcall", X86_FEATURE_VMW_VMMCALL)
 #endif
index 9e2dd2b296cd570046fafc200d3662f4b368da12..2b0faf86da1b7327ad4b2bdb4548ef823c0efd30 100644 (file)
@@ -1586,9 +1586,6 @@ static void setup_local_APIC(void)
 {
        int cpu = smp_processor_id();
        unsigned int value;
-#ifdef CONFIG_X86_32
-       int logical_apicid, ldr_apicid;
-#endif
 
        if (disable_apic) {
                disable_ioapic_support();
@@ -1626,16 +1623,21 @@ static void setup_local_APIC(void)
        apic->init_apic_ldr();
 
 #ifdef CONFIG_X86_32
-       /*
-        * APIC LDR is initialized.  If logical_apicid mapping was
-        * initialized during get_smp_config(), make sure it matches the
-        * actual value.
-        */
-       logical_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu);
-       ldr_apicid = GET_APIC_LOGICAL_ID(apic_read(APIC_LDR));
-       WARN_ON(logical_apicid != BAD_APICID && logical_apicid != ldr_apicid);
-       /* always use the value from LDR */
-       early_per_cpu(x86_cpu_to_logical_apicid, cpu) = ldr_apicid;
+       if (apic->dest_logical) {
+               int logical_apicid, ldr_apicid;
+
+               /*
+                * APIC LDR is initialized.  If logical_apicid mapping was
+                * initialized during get_smp_config(), make sure it matches
+                * the actual value.
+                */
+               logical_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu);
+               ldr_apicid = GET_APIC_LOGICAL_ID(apic_read(APIC_LDR));
+               if (logical_apicid != BAD_APICID)
+                       WARN_ON(logical_apicid != ldr_apicid);
+               /* Always use the value from LDR. */
+               early_per_cpu(x86_cpu_to_logical_apicid, cpu) = ldr_apicid;
+       }
 #endif
 
        /*
index efbd54cc4e696b5c78f56f7db46d5bb605df40e9..055c8613b5317afd6c550cab54ca94507b4e196a 100644 (file)
@@ -522,6 +522,10 @@ int rdtgroup_mondata_show(struct seq_file *m, void *arg)
        int ret = 0;
 
        rdtgrp = rdtgroup_kn_lock_live(of->kn);
+       if (!rdtgrp) {
+               ret = -ENOENT;
+               goto out;
+       }
 
        md.priv = of->kn->priv;
        resid = md.u.rid;
index 753b8cfe8b8a212d7423ec1622e3699431a3b6f2..87b97897a881035966bbef4693df91e8d46b547e 100644 (file)
@@ -94,6 +94,13 @@ static bool in_exception_stack(unsigned long *stack, struct stack_info *info)
        BUILD_BUG_ON(N_EXCEPTION_STACKS != 6);
 
        begin = (unsigned long)__this_cpu_read(cea_exception_stacks);
+       /*
+        * Handle the case where stack trace is collected _before_
+        * cea_exception_stacks had been initialized.
+        */
+       if (!begin)
+               return false;
+
        end = begin + sizeof(struct cea_exception_stacks);
        /* Bail if @stack is outside the exception stack area. */
        if (stk < begin || stk >= end)
index c59454c382fdcd78c45be54cdfe43e064f58f766..7e322e2daaf59e06841422dcbc926718a688a42d 100644 (file)
@@ -1505,6 +1505,9 @@ void __init tsc_init(void)
                return;
        }
 
+       if (tsc_clocksource_reliable || no_tsc_watchdog)
+               clocksource_tsc_early.flags &= ~CLOCK_SOURCE_MUST_VERIFY;
+
        clocksource_register_khz(&clocksource_tsc_early, tsc_khz);
        detect_art();
 }
index 9c5029cf6f3f245d9048599e3ff53c228f8092ec..f68c0c753c38f6fd29703f98b0646f1372969407 100644 (file)
@@ -363,7 +363,7 @@ static inline void do_cpuid_7_mask(struct kvm_cpuid_entry2 *entry, int index)
 
        /* cpuid 7.0.ecx*/
        const u32 kvm_cpuid_7_0_ecx_x86_features =
-               F(AVX512VBMI) | F(LA57) | F(PKU) | 0 /*OSPKE*/ |
+               F(AVX512VBMI) | F(LA57) | F(PKU) | 0 /*OSPKE*/ | F(RDPID) |
                F(AVX512_VPOPCNTDQ) | F(UMIP) | F(AVX512_VBMI2) | F(GFNI) |
                F(VAES) | F(VPCLMULQDQ) | F(AVX512_VNNI) | F(AVX512_BITALG) |
                F(CLDEMOTE) | F(MOVDIRI) | F(MOVDIR64B) | 0 /*WAITPKG*/;
index 87b0fcc23ef8946f7fe2f7ab46db9c0178a706b9..b29d00b661ff2155a3530bd6eeb094287a981f37 100644 (file)
@@ -111,11 +111,6 @@ static inline int apic_enabled(struct kvm_lapic *apic)
        (LVT_MASK | APIC_MODE_MASK | APIC_INPUT_POLARITY | \
         APIC_LVT_REMOTE_IRR | APIC_LVT_LEVEL_TRIGGER)
 
-static inline u8 kvm_xapic_id(struct kvm_lapic *apic)
-{
-       return kvm_lapic_get_reg(apic, APIC_ID) >> 24;
-}
-
 static inline u32 kvm_x2apic_id(struct kvm_lapic *apic)
 {
        return apic->vcpu->vcpu_id;
index 2aad7e226fc016e130f29746f4fa2798fb811126..1f5014852e208e1c38c9d0c7c57fa0ae8fc6d110 100644 (file)
@@ -242,4 +242,9 @@ static inline enum lapic_mode kvm_apic_mode(u64 apic_base)
        return apic_base & (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE);
 }
 
+static inline u8 kvm_xapic_id(struct kvm_lapic *apic)
+{
+       return kvm_lapic_get_reg(apic, APIC_ID) >> 24;
+}
+
 #endif
index f8ecb6df5106641517a75380e4755dfa65967f08..c5673bda4b66df5e7672abc78e5bf520b3c3361c 100644 (file)
@@ -734,8 +734,14 @@ static int get_npt_level(struct kvm_vcpu *vcpu)
 static void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer)
 {
        vcpu->arch.efer = efer;
-       if (!npt_enabled && !(efer & EFER_LMA))
-               efer &= ~EFER_LME;
+
+       if (!npt_enabled) {
+               /* Shadow paging assumes NX to be available.  */
+               efer |= EFER_NX;
+
+               if (!(efer & EFER_LMA))
+                       efer &= ~EFER_LME;
+       }
 
        to_svm(vcpu)->vmcb->save.efer = efer | EFER_SVME;
        mark_dirty(to_svm(vcpu)->vmcb, VMCB_CR);
@@ -4591,6 +4597,7 @@ static int avic_handle_ldr_update(struct kvm_vcpu *vcpu)
        int ret = 0;
        struct vcpu_svm *svm = to_svm(vcpu);
        u32 ldr = kvm_lapic_get_reg(vcpu->arch.apic, APIC_LDR);
+       u32 id = kvm_xapic_id(vcpu->arch.apic);
 
        if (ldr == svm->ldr_reg)
                return 0;
@@ -4598,7 +4605,7 @@ static int avic_handle_ldr_update(struct kvm_vcpu *vcpu)
        avic_invalidate_logical_id_entry(vcpu);
 
        if (ldr)
-               ret = avic_ldr_write(vcpu, vcpu->vcpu_id, ldr);
+               ret = avic_ldr_write(vcpu, id, ldr);
 
        if (!ret)
                svm->ldr_reg = ldr;
@@ -4610,8 +4617,7 @@ static int avic_handle_apic_id_update(struct kvm_vcpu *vcpu)
 {
        u64 *old, *new;
        struct vcpu_svm *svm = to_svm(vcpu);
-       u32 apic_id_reg = kvm_lapic_get_reg(vcpu->arch.apic, APIC_ID);
-       u32 id = (apic_id_reg >> 24) & 0xff;
+       u32 id = kvm_xapic_id(vcpu->arch.apic);
 
        if (vcpu->vcpu_id == id)
                return 0;
index e76eb4f07f6c93a2b8bad15afefbc1087d9f487c..0e7c9301fe86549e42bb2959e4408299230fb82b 100644 (file)
@@ -2917,7 +2917,7 @@ static int nested_vmx_check_vmentry_hw(struct kvm_vcpu *vcpu)
 static inline bool nested_vmx_prepare_msr_bitmap(struct kvm_vcpu *vcpu,
                                                 struct vmcs12 *vmcs12);
 
-static void nested_get_vmcs12_pages(struct kvm_vcpu *vcpu)
+static bool nested_get_vmcs12_pages(struct kvm_vcpu *vcpu)
 {
        struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
        struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -2937,19 +2937,18 @@ static void nested_get_vmcs12_pages(struct kvm_vcpu *vcpu)
                        vmx->nested.apic_access_page = NULL;
                }
                page = kvm_vcpu_gpa_to_page(vcpu, vmcs12->apic_access_addr);
-               /*
-                * If translation failed, no matter: This feature asks
-                * to exit when accessing the given address, and if it
-                * can never be accessed, this feature won't do
-                * anything anyway.
-                */
                if (!is_error_page(page)) {
                        vmx->nested.apic_access_page = page;
                        hpa = page_to_phys(vmx->nested.apic_access_page);
                        vmcs_write64(APIC_ACCESS_ADDR, hpa);
                } else {
-                       secondary_exec_controls_clearbit(vmx,
-                               SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES);
+                       pr_debug_ratelimited("%s: no backing 'struct page' for APIC-access address in vmcs12\n",
+                                            __func__);
+                       vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+                       vcpu->run->internal.suberror =
+                               KVM_INTERNAL_ERROR_EMULATION;
+                       vcpu->run->internal.ndata = 0;
+                       return false;
                }
        }
 
@@ -2994,6 +2993,7 @@ static void nested_get_vmcs12_pages(struct kvm_vcpu *vcpu)
                exec_controls_setbit(vmx, CPU_BASED_USE_MSR_BITMAPS);
        else
                exec_controls_clearbit(vmx, CPU_BASED_USE_MSR_BITMAPS);
+       return true;
 }
 
 /*
@@ -3032,13 +3032,15 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
 /*
  * If from_vmentry is false, this is being called from state restore (either RSM
  * or KVM_SET_NESTED_STATE).  Otherwise it's called from vmlaunch/vmresume.
-+ *
-+ * Returns:
-+ *   0 - success, i.e. proceed with actual VMEnter
-+ *   1 - consistency check VMExit
-+ *  -1 - consistency check VMFail
+ *
+ * Returns:
+ *     NVMX_ENTRY_SUCCESS: Entered VMX non-root mode
+ *     NVMX_ENTRY_VMFAIL:  Consistency check VMFail
+ *     NVMX_ENTRY_VMEXIT:  Consistency check VMExit
+ *     NVMX_ENTRY_KVM_INTERNAL_ERROR: KVM internal error
  */
-int nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu, bool from_vmentry)
+enum nvmx_vmentry_status nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu,
+                                                       bool from_vmentry)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
@@ -3081,11 +3083,12 @@ int nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu, bool from_vmentry)
        prepare_vmcs02_early(vmx, vmcs12);
 
        if (from_vmentry) {
-               nested_get_vmcs12_pages(vcpu);
+               if (unlikely(!nested_get_vmcs12_pages(vcpu)))
+                       return NVMX_VMENTRY_KVM_INTERNAL_ERROR;
 
                if (nested_vmx_check_vmentry_hw(vcpu)) {
                        vmx_switch_vmcs(vcpu, &vmx->vmcs01);
-                       return -1;
+                       return NVMX_VMENTRY_VMFAIL;
                }
 
                if (nested_vmx_check_guest_state(vcpu, vmcs12, &exit_qual))
@@ -3149,7 +3152,7 @@ int nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu, bool from_vmentry)
         * returned as far as L1 is concerned. It will only return (and set
         * the success flag) when L2 exits (see nested_vmx_vmexit()).
         */
-       return 0;
+       return NVMX_VMENTRY_SUCCESS;
 
        /*
         * A failed consistency check that leads to a VMExit during L1's
@@ -3165,14 +3168,14 @@ vmentry_fail_vmexit:
        vmx_switch_vmcs(vcpu, &vmx->vmcs01);
 
        if (!from_vmentry)
-               return 1;
+               return NVMX_VMENTRY_VMEXIT;
 
        load_vmcs12_host_state(vcpu, vmcs12);
        vmcs12->vm_exit_reason = exit_reason | VMX_EXIT_REASONS_FAILED_VMENTRY;
        vmcs12->exit_qualification = exit_qual;
        if (enable_shadow_vmcs || vmx->nested.hv_evmcs)
                vmx->nested.need_vmcs12_to_shadow_sync = true;
-       return 1;
+       return NVMX_VMENTRY_VMEXIT;
 }
 
 /*
@@ -3182,9 +3185,9 @@ vmentry_fail_vmexit:
 static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
 {
        struct vmcs12 *vmcs12;
+       enum nvmx_vmentry_status status;
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        u32 interrupt_shadow = vmx_get_interrupt_shadow(vcpu);
-       int ret;
 
        if (!nested_vmx_check_permission(vcpu))
                return 1;
@@ -3244,13 +3247,9 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
         * the nested entry.
         */
        vmx->nested.nested_run_pending = 1;
-       ret = nested_vmx_enter_non_root_mode(vcpu, true);
-       vmx->nested.nested_run_pending = !ret;
-       if (ret > 0)
-               return 1;
-       else if (ret)
-               return nested_vmx_failValid(vcpu,
-                       VMXERR_ENTRY_INVALID_CONTROL_FIELD);
+       status = nested_vmx_enter_non_root_mode(vcpu, true);
+       if (unlikely(status != NVMX_VMENTRY_SUCCESS))
+               goto vmentry_failed;
 
        /* Hide L1D cache contents from the nested guest.  */
        vmx->vcpu.arch.l1tf_flush_l1d = true;
@@ -3281,6 +3280,15 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
                return kvm_vcpu_halt(vcpu);
        }
        return 1;
+
+vmentry_failed:
+       vmx->nested.nested_run_pending = 0;
+       if (status == NVMX_VMENTRY_KVM_INTERNAL_ERROR)
+               return 0;
+       if (status == NVMX_VMENTRY_VMEXIT)
+               return 1;
+       WARN_ON_ONCE(status != NVMX_VMENTRY_VMFAIL);
+       return nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
 }
 
 /*
index 187d39bf0bf10ca178cc3f1a7b45e18b7000ccbe..6280f33e5fa604c745ac19f3e62fda681709c90d 100644 (file)
@@ -6,6 +6,16 @@
 #include "vmcs12.h"
 #include "vmx.h"
 
+/*
+ * Status returned by nested_vmx_enter_non_root_mode():
+ */
+enum nvmx_vmentry_status {
+       NVMX_VMENTRY_SUCCESS,           /* Entered VMX non-root mode */
+       NVMX_VMENTRY_VMFAIL,            /* Consistency check VMFail */
+       NVMX_VMENTRY_VMEXIT,            /* Consistency check VMExit */
+       NVMX_VMENTRY_KVM_INTERNAL_ERROR,/* KVM internal error */
+};
+
 void vmx_leave_nested(struct kvm_vcpu *vcpu);
 void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps,
                                bool apicv);
@@ -13,7 +23,8 @@ void nested_vmx_hardware_unsetup(void);
 __init int nested_vmx_hardware_setup(int (*exit_handlers[])(struct kvm_vcpu *));
 void nested_vmx_vcpu_setup(void);
 void nested_vmx_free_vcpu(struct kvm_vcpu *vcpu);
-int nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu, bool from_vmentry);
+enum nvmx_vmentry_status nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu,
+                                                    bool from_vmentry);
 bool nested_vmx_exit_reflected(struct kvm_vcpu *vcpu, u32 exit_reason);
 void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason,
                       u32 exit_intr_info, unsigned long exit_qualification);
index e7970a2e8eae918f76ce8ef3646aba0f39a27275..5d21a4ab28cfc80b3f800adfd042cb23c155a737 100644 (file)
@@ -969,17 +969,9 @@ static bool update_transition_efer(struct vcpu_vmx *vmx, int efer_offset)
        u64 guest_efer = vmx->vcpu.arch.efer;
        u64 ignore_bits = 0;
 
-       if (!enable_ept) {
-               /*
-                * NX is needed to handle CR0.WP=1, CR4.SMEP=1.  Testing
-                * host CPUID is more efficient than testing guest CPUID
-                * or CR4.  Host SMEP is anyway a requirement for guest SMEP.
-                */
-               if (boot_cpu_has(X86_FEATURE_SMEP))
-                       guest_efer |= EFER_NX;
-               else if (!(guest_efer & EFER_NX))
-                       ignore_bits |= EFER_NX;
-       }
+       /* Shadow paging assumes NX to be available.  */
+       if (!enable_ept)
+               guest_efer |= EFER_NX;
 
        /*
         * LMA and LME handled by hardware; SCE meaningless outside long mode.
@@ -5543,14 +5535,6 @@ static int handle_encls(struct kvm_vcpu *vcpu)
        return 1;
 }
 
-static int handle_unexpected_vmexit(struct kvm_vcpu *vcpu)
-{
-       kvm_skip_emulated_instruction(vcpu);
-       WARN_ONCE(1, "Unexpected VM-Exit Reason = 0x%x",
-               vmcs_read32(VM_EXIT_REASON));
-       return 1;
-}
-
 /*
  * The exit handlers return 1 if the exit was handled fully and guest execution
  * may resume.  Otherwise they set the kvm_run parameter to indicate what needs
@@ -5602,15 +5586,11 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
        [EXIT_REASON_INVVPID]                 = handle_vmx_instruction,
        [EXIT_REASON_RDRAND]                  = handle_invalid_op,
        [EXIT_REASON_RDSEED]                  = handle_invalid_op,
-       [EXIT_REASON_XSAVES]                  = handle_unexpected_vmexit,
-       [EXIT_REASON_XRSTORS]                 = handle_unexpected_vmexit,
        [EXIT_REASON_PML_FULL]                = handle_pml_full,
        [EXIT_REASON_INVPCID]                 = handle_invpcid,
        [EXIT_REASON_VMFUNC]                  = handle_vmx_instruction,
        [EXIT_REASON_PREEMPTION_TIMER]        = handle_preemption_timer,
        [EXIT_REASON_ENCLS]                   = handle_encls,
-       [EXIT_REASON_UMWAIT]                  = handle_unexpected_vmexit,
-       [EXIT_REASON_TPAUSE]                  = handle_unexpected_vmexit,
 };
 
 static const int kvm_vmx_max_exit_handlers =
index 661e2bf3852664c63c95b34360712a7bf8674521..ff395f8127190b10986ec116eac85b30f379ab8c 100644 (file)
@@ -360,8 +360,7 @@ EXPORT_SYMBOL_GPL(kvm_set_apic_base);
 asmlinkage __visible void kvm_spurious_fault(void)
 {
        /* Fault while not rebooting.  We want the trace. */
-       if (!kvm_rebooting)
-               BUG();
+       BUG_ON(!kvm_rebooting);
 }
 EXPORT_SYMBOL_GPL(kvm_spurious_fault);
 
@@ -2537,6 +2536,7 @@ static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data)
 static void kvmclock_reset(struct kvm_vcpu *vcpu)
 {
        vcpu->arch.pv_time_enabled = false;
+       vcpu->arch.time = 0;
 }
 
 static void kvm_vcpu_flush_tlb(struct kvm_vcpu *vcpu, bool invalidate_gpa)
@@ -2702,8 +2702,6 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
        case MSR_KVM_SYSTEM_TIME: {
                struct kvm_arch *ka = &vcpu->kvm->arch;
 
-               kvmclock_reset(vcpu);
-
                if (vcpu->vcpu_id == 0 && !msr_info->host_initiated) {
                        bool tmp = (msr == MSR_KVM_SYSTEM_TIME);
 
@@ -2717,14 +2715,13 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                kvm_make_request(KVM_REQ_GLOBAL_CLOCK_UPDATE, vcpu);
 
                /* we verify if the enable bit is set... */
+               vcpu->arch.pv_time_enabled = false;
                if (!(data & 1))
                        break;
 
-               if (kvm_gfn_to_hva_cache_init(vcpu->kvm,
+               if (!kvm_gfn_to_hva_cache_init(vcpu->kvm,
                     &vcpu->arch.pv_time, data & ~1ULL,
                     sizeof(struct pvclock_vcpu_time_info)))
-                       vcpu->arch.pv_time_enabled = false;
-               else
                        vcpu->arch.pv_time_enabled = true;
 
                break;
@@ -7941,8 +7938,12 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
        bool req_immediate_exit = false;
 
        if (kvm_request_pending(vcpu)) {
-               if (kvm_check_request(KVM_REQ_GET_VMCS12_PAGES, vcpu))
-                       kvm_x86_ops->get_vmcs12_pages(vcpu);
+               if (kvm_check_request(KVM_REQ_GET_VMCS12_PAGES, vcpu)) {
+                       if (unlikely(!kvm_x86_ops->get_vmcs12_pages(vcpu))) {
+                               r = 0;
+                               goto out;
+                       }
+               }
                if (kvm_check_request(KVM_REQ_MMU_RELOAD, vcpu))
                        kvm_mmu_unload(vcpu);
                if (kvm_check_request(KVM_REQ_MIGRATE_TIMER, vcpu))
index 58f79ab32358429ea4f948ccccbdfe86e9e294e3..5bfea374a1609a590d9cae7b343b07f85e02bf6d 100644 (file)
@@ -117,6 +117,14 @@ static void __init xen_banner(void)
        printk(KERN_INFO "Xen version: %d.%d%s%s\n",
               version >> 16, version & 0xffff, extra.extraversion,
               xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : "");
+
+#ifdef CONFIG_X86_32
+       pr_warn("WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!\n"
+               "Support for running as 32-bit PV-guest under Xen will soon be removed\n"
+               "from the Linux kernel!\n"
+               "Please use either a 64-bit kernel or switch to HVM or PVH mode!\n"
+               "WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!\n");
+#endif
 }
 
 static void __init xen_pv_init_platform(void)
index 5d21027b1faf03b1a16bcd38b8670657c9f02380..1eb8895be4c6b8bb17d49022583d2ee411336e94 100644 (file)
@@ -934,9 +934,14 @@ static int blkcg_print_stat(struct seq_file *sf, void *v)
                int i;
                bool has_stats = false;
 
+               spin_lock_irq(&blkg->q->queue_lock);
+
+               if (!blkg->online)
+                       goto skip;
+
                dname = blkg_dev_name(blkg);
                if (!dname)
-                       continue;
+                       goto skip;
 
                /*
                 * Hooray string manipulation, count is the size written NOT
@@ -946,8 +951,6 @@ static int blkcg_print_stat(struct seq_file *sf, void *v)
                 */
                off += scnprintf(buf+off, size-off, "%s ", dname);
 
-               spin_lock_irq(&blkg->q->queue_lock);
-
                blkg_rwstat_recursive_sum(blkg, NULL,
                                offsetof(struct blkcg_gq, stat_bytes), &rwstat);
                rbytes = rwstat.cnt[BLKG_RWSTAT_READ];
@@ -960,8 +963,6 @@ static int blkcg_print_stat(struct seq_file *sf, void *v)
                wios = rwstat.cnt[BLKG_RWSTAT_WRITE];
                dios = rwstat.cnt[BLKG_RWSTAT_DISCARD];
 
-               spin_unlock_irq(&blkg->q->queue_lock);
-
                if (rbytes || wbytes || rios || wios) {
                        has_stats = true;
                        off += scnprintf(buf+off, size-off,
@@ -999,6 +1000,8 @@ static int blkcg_print_stat(struct seq_file *sf, void *v)
                                seq_commit(sf, -1);
                        }
                }
+       skip:
+               spin_unlock_irq(&blkg->q->queue_lock);
        }
 
        rcu_read_unlock();
index 2a3db80c1dce7f97c65229510d078e3553615fc4..a7ed434eae0387b92d41009b0cc52f3522ed556c 100644 (file)
@@ -2110,10 +2110,10 @@ static ssize_t ioc_weight_write(struct kernfs_open_file *of, char *buf,
                        goto einval;
        }
 
-       spin_lock_irq(&iocg->ioc->lock);
+       spin_lock(&iocg->ioc->lock);
        iocg->cfg_weight = v;
        weight_updated(iocg);
-       spin_unlock_irq(&iocg->ioc->lock);
+       spin_unlock(&iocg->ioc->lock);
 
        blkg_conf_finish(&ctx);
        return nbytes;
index 1413324982f0d7628068711e61e598093b88d320..14e68f202f8109dfce44d19eee7274d68d1552bc 100644 (file)
@@ -1322,7 +1322,7 @@ static ssize_t scrub_show(struct device *dev,
        nfit_device_lock(dev);
        nd_desc = dev_get_drvdata(dev);
        if (!nd_desc) {
-               device_unlock(dev);
+               nfit_device_unlock(dev);
                return rc;
        }
        acpi_desc = to_acpi_desc(nd_desc);
index 08da9c29f1e9a8fe722e5bfc7895357b5ec3277e..62114a03a51aa134dbf5254f105392c60c27a550 100644 (file)
@@ -290,14 +290,13 @@ static int acpi_processor_notifier(struct notifier_block *nb,
                                   unsigned long event, void *data)
 {
        struct cpufreq_policy *policy = data;
-       int cpu = policy->cpu;
 
        if (event == CPUFREQ_CREATE_POLICY) {
-               acpi_thermal_cpufreq_init(cpu);
-               acpi_processor_ppc_init(cpu);
+               acpi_thermal_cpufreq_init(policy);
+               acpi_processor_ppc_init(policy);
        } else if (event == CPUFREQ_REMOVE_POLICY) {
-               acpi_processor_ppc_exit(cpu);
-               acpi_thermal_cpufreq_exit(cpu);
+               acpi_processor_ppc_exit(policy);
+               acpi_thermal_cpufreq_exit(policy);
        }
 
        return 0;
index 930a49fa4dfc5aec8d2847f3d5802ab2eb0956a1..5909e8fa4013f2c6c831b1a28d9d69ca4cec98fb 100644 (file)
@@ -81,10 +81,10 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
        pr->performance_platform_limit = (int)ppc;
 
        if (ppc >= pr->performance->state_count ||
-           unlikely(!dev_pm_qos_request_active(&pr->perflib_req)))
+           unlikely(!freq_qos_request_active(&pr->perflib_req)))
                return 0;
 
-       ret = dev_pm_qos_update_request(&pr->perflib_req,
+       ret = freq_qos_update_request(&pr->perflib_req,
                        pr->performance->states[ppc].core_frequency * 1000);
        if (ret < 0) {
                pr_warn("Failed to update perflib freq constraint: CPU%d (%d)\n",
@@ -157,28 +157,36 @@ void acpi_processor_ignore_ppc_init(void)
                ignore_ppc = 0;
 }
 
-void acpi_processor_ppc_init(int cpu)
+void acpi_processor_ppc_init(struct cpufreq_policy *policy)
 {
-       struct acpi_processor *pr = per_cpu(processors, cpu);
-       int ret;
+       unsigned int cpu;
 
-       if (!pr)
-               return;
+       for_each_cpu(cpu, policy->related_cpus) {
+               struct acpi_processor *pr = per_cpu(processors, cpu);
+               int ret;
+
+               if (!pr)
+                       continue;
 
-       ret = dev_pm_qos_add_request(get_cpu_device(cpu),
-                                    &pr->perflib_req, DEV_PM_QOS_MAX_FREQUENCY,
-                                    INT_MAX);
-       if (ret < 0)
-               pr_err("Failed to add freq constraint for CPU%d (%d)\n", cpu,
-                      ret);
+               ret = freq_qos_add_request(&policy->constraints,
+                                          &pr->perflib_req,
+                                          FREQ_QOS_MAX, INT_MAX);
+               if (ret < 0)
+                       pr_err("Failed to add freq constraint for CPU%d (%d)\n",
+                              cpu, ret);
+       }
 }
 
-void acpi_processor_ppc_exit(int cpu)
+void acpi_processor_ppc_exit(struct cpufreq_policy *policy)
 {
-       struct acpi_processor *pr = per_cpu(processors, cpu);
+       unsigned int cpu;
 
-       if (pr)
-               dev_pm_qos_remove_request(&pr->perflib_req);
+       for_each_cpu(cpu, policy->related_cpus) {
+               struct acpi_processor *pr = per_cpu(processors, cpu);
+
+               if (pr)
+                       freq_qos_remove_request(&pr->perflib_req);
+       }
 }
 
 static int acpi_processor_get_performance_control(struct acpi_processor *pr)
index 8227c7dd75b17dac5f5e21daf0d98370c1c86bea..41feb88ee92d69380af6e4d30c92199e3e4dd4d1 100644 (file)
@@ -105,7 +105,7 @@ static int cpufreq_set_cur_state(unsigned int cpu, int state)
 
                pr = per_cpu(processors, i);
 
-               if (unlikely(!dev_pm_qos_request_active(&pr->thermal_req)))
+               if (unlikely(!freq_qos_request_active(&pr->thermal_req)))
                        continue;
 
                policy = cpufreq_cpu_get(i);
@@ -116,7 +116,7 @@ static int cpufreq_set_cur_state(unsigned int cpu, int state)
 
                cpufreq_cpu_put(policy);
 
-               ret = dev_pm_qos_update_request(&pr->thermal_req, max_freq);
+               ret = freq_qos_update_request(&pr->thermal_req, max_freq);
                if (ret < 0) {
                        pr_warn("Failed to update thermal freq constraint: CPU%d (%d)\n",
                                pr->id, ret);
@@ -125,28 +125,36 @@ static int cpufreq_set_cur_state(unsigned int cpu, int state)
        return 0;
 }
 
-void acpi_thermal_cpufreq_init(int cpu)
+void acpi_thermal_cpufreq_init(struct cpufreq_policy *policy)
 {
-       struct acpi_processor *pr = per_cpu(processors, cpu);
-       int ret;
+       unsigned int cpu;
 
-       if (!pr)
-               return;
-
-       ret = dev_pm_qos_add_request(get_cpu_device(cpu),
-                                    &pr->thermal_req, DEV_PM_QOS_MAX_FREQUENCY,
-                                    INT_MAX);
-       if (ret < 0)
-               pr_err("Failed to add freq constraint for CPU%d (%d)\n", cpu,
-                      ret);
+       for_each_cpu(cpu, policy->related_cpus) {
+               struct acpi_processor *pr = per_cpu(processors, cpu);
+               int ret;
+
+               if (!pr)
+                       continue;
+
+               ret = freq_qos_add_request(&policy->constraints,
+                                          &pr->thermal_req,
+                                          FREQ_QOS_MAX, INT_MAX);
+               if (ret < 0)
+                       pr_err("Failed to add freq constraint for CPU%d (%d)\n",
+                              cpu, ret);
+       }
 }
 
-void acpi_thermal_cpufreq_exit(int cpu)
+void acpi_thermal_cpufreq_exit(struct cpufreq_policy *policy)
 {
-       struct acpi_processor *pr = per_cpu(processors, cpu);
+       unsigned int cpu;
+
+       for_each_cpu(cpu, policy->related_cpus) {
+               struct acpi_processor *pr = per_cpu(processors, policy->cpu);
 
-       if (pr)
-               dev_pm_qos_remove_request(&pr->thermal_req);
+               if (pr)
+                       freq_qos_remove_request(&pr->thermal_req);
+       }
 }
 #else                          /* ! CONFIG_CPU_FREQ */
 static int cpufreq_get_max_state(unsigned int cpu)
index f39f075abff9f71bac1f688db5483017957ad88c..fe1523664816a49712c88b4afcdc9ee65011b955 100644 (file)
@@ -409,9 +409,11 @@ static int amba_device_try_add(struct amba_device *dev, struct resource *parent)
                 */
                rstc = of_reset_control_array_get_optional_shared(dev->dev.of_node);
                if (IS_ERR(rstc)) {
-                       if (PTR_ERR(rstc) != -EPROBE_DEFER)
-                               dev_err(&dev->dev, "Can't get amba reset!\n");
-                       return PTR_ERR(rstc);
+                       ret = PTR_ERR(rstc);
+                       if (ret != -EPROBE_DEFER)
+                               dev_err(&dev->dev, "can't get reset: %d\n",
+                                       ret);
+                       goto err_reset;
                }
                reset_control_deassert(rstc);
                reset_control_put(rstc);
@@ -472,6 +474,12 @@ static int amba_device_try_add(struct amba_device *dev, struct resource *parent)
        release_resource(&dev->res);
  err_out:
        return ret;
+
+ err_reset:
+       amba_put_disable_pclk(dev);
+       iounmap(tmp);
+       dev_pm_domain_detach(&dev->dev, true);
+       goto err_release;
 }
 
 /*
index 5b9ac2122e894558eea8e67353f981438283a2be..265d9dd46a5ebb6610bf826ed0fa620b55c289a6 100644 (file)
@@ -97,10 +97,6 @@ DEFINE_SHOW_ATTRIBUTE(proc);
 #define SZ_1K                               0x400
 #endif
 
-#ifndef SZ_4M
-#define SZ_4M                               0x400000
-#endif
-
 #define FORBIDDEN_MMAP_FLAGS                (VM_WRITE)
 
 enum {
@@ -5177,9 +5173,6 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
        if (proc->tsk != current->group_leader)
                return -EINVAL;
 
-       if ((vma->vm_end - vma->vm_start) > SZ_4M)
-               vma->vm_end = vma->vm_start + SZ_4M;
-
        binder_debug(BINDER_DEBUG_OPEN_CLOSE,
                     "%s: %d %lx-%lx (%ld K) vma %lx pagep %lx\n",
                     __func__, proc->pid, vma->vm_start, vma->vm_end,
index d42a8b2f636a5bbdcd43bcfee43b24d820e1e745..eb76a823fbb200f008b0e4c6ad02bc5818929857 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/cacheflush.h>
 #include <linux/uaccess.h>
 #include <linux/highmem.h>
+#include <linux/sizes.h>
 #include "binder_alloc.h"
 #include "binder_trace.h"
 
@@ -689,7 +690,9 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
        alloc->buffer = (void __user *)vma->vm_start;
        mutex_unlock(&binder_alloc_mmap_lock);
 
-       alloc->pages = kcalloc((vma->vm_end - vma->vm_start) / PAGE_SIZE,
+       alloc->buffer_size = min_t(unsigned long, vma->vm_end - vma->vm_start,
+                                  SZ_4M);
+       alloc->pages = kcalloc(alloc->buffer_size / PAGE_SIZE,
                               sizeof(alloc->pages[0]),
                               GFP_KERNEL);
        if (alloc->pages == NULL) {
@@ -697,7 +700,6 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
                failure_string = "alloc page array";
                goto err_alloc_pages_failed;
        }
-       alloc->buffer_size = vma->vm_end - vma->vm_start;
 
        buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
        if (!buffer) {
index e742780950de84c330c2c83b1daf1a0905f03ed0..8befce036af84810b0a3c815829b87f6fd904d8c 100644 (file)
@@ -153,17 +153,13 @@ int ahci_platform_enable_regulators(struct ahci_host_priv *hpriv)
 {
        int rc, i;
 
-       if (hpriv->ahci_regulator) {
-               rc = regulator_enable(hpriv->ahci_regulator);
-               if (rc)
-                       return rc;
-       }
+       rc = regulator_enable(hpriv->ahci_regulator);
+       if (rc)
+               return rc;
 
-       if (hpriv->phy_regulator) {
-               rc = regulator_enable(hpriv->phy_regulator);
-               if (rc)
-                       goto disable_ahci_pwrs;
-       }
+       rc = regulator_enable(hpriv->phy_regulator);
+       if (rc)
+               goto disable_ahci_pwrs;
 
        for (i = 0; i < hpriv->nports; i++) {
                if (!hpriv->target_pwrs[i])
@@ -181,11 +177,9 @@ disable_target_pwrs:
                if (hpriv->target_pwrs[i])
                        regulator_disable(hpriv->target_pwrs[i]);
 
-       if (hpriv->phy_regulator)
-               regulator_disable(hpriv->phy_regulator);
+       regulator_disable(hpriv->phy_regulator);
 disable_ahci_pwrs:
-       if (hpriv->ahci_regulator)
-               regulator_disable(hpriv->ahci_regulator);
+       regulator_disable(hpriv->ahci_regulator);
        return rc;
 }
 EXPORT_SYMBOL_GPL(ahci_platform_enable_regulators);
@@ -207,10 +201,8 @@ void ahci_platform_disable_regulators(struct ahci_host_priv *hpriv)
                regulator_disable(hpriv->target_pwrs[i]);
        }
 
-       if (hpriv->ahci_regulator)
-               regulator_disable(hpriv->ahci_regulator);
-       if (hpriv->phy_regulator)
-               regulator_disable(hpriv->phy_regulator);
+       regulator_disable(hpriv->ahci_regulator);
+       regulator_disable(hpriv->phy_regulator);
 }
 EXPORT_SYMBOL_GPL(ahci_platform_disable_regulators);
 /**
@@ -359,7 +351,7 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port,
        struct regulator *target_pwr;
        int rc = 0;
 
-       target_pwr = regulator_get_optional(dev, "target");
+       target_pwr = regulator_get(dev, "target");
 
        if (!IS_ERR(target_pwr))
                hpriv->target_pwrs[port] = target_pwr;
@@ -436,16 +428,14 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
                hpriv->clks[i] = clk;
        }
 
-       hpriv->ahci_regulator = devm_regulator_get_optional(dev, "ahci");
+       hpriv->ahci_regulator = devm_regulator_get(dev, "ahci");
        if (IS_ERR(hpriv->ahci_regulator)) {
                rc = PTR_ERR(hpriv->ahci_regulator);
-               if (rc == -EPROBE_DEFER)
+               if (rc != 0)
                        goto err_out;
-               rc = 0;
-               hpriv->ahci_regulator = NULL;
        }
 
-       hpriv->phy_regulator = devm_regulator_get_optional(dev, "phy");
+       hpriv->phy_regulator = devm_regulator_get(dev, "phy");
        if (IS_ERR(hpriv->phy_regulator)) {
                rc = PTR_ERR(hpriv->phy_regulator);
                if (rc == -EPROBE_DEFER)
index 6c90fd7e2ff8f385a7c00fa6a36bf4d3a344b02d..350dcafd751f8e6c352f5e68945103da7cd84227 100644 (file)
@@ -115,20 +115,10 @@ s32 dev_pm_qos_read_value(struct device *dev, enum dev_pm_qos_req_type type)
 
        spin_lock_irqsave(&dev->power.lock, flags);
 
-       switch (type) {
-       case DEV_PM_QOS_RESUME_LATENCY:
+       if (type == DEV_PM_QOS_RESUME_LATENCY) {
                ret = IS_ERR_OR_NULL(qos) ? PM_QOS_RESUME_LATENCY_NO_CONSTRAINT
                        : pm_qos_read_value(&qos->resume_latency);
-               break;
-       case DEV_PM_QOS_MIN_FREQUENCY:
-               ret = IS_ERR_OR_NULL(qos) ? PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE
-                       : pm_qos_read_value(&qos->min_frequency);
-               break;
-       case DEV_PM_QOS_MAX_FREQUENCY:
-               ret = IS_ERR_OR_NULL(qos) ? PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE
-                       : pm_qos_read_value(&qos->max_frequency);
-               break;
-       default:
+       } else {
                WARN_ON(1);
                ret = 0;
        }
@@ -169,14 +159,6 @@ static int apply_constraint(struct dev_pm_qos_request *req,
                        req->dev->power.set_latency_tolerance(req->dev, value);
                }
                break;
-       case DEV_PM_QOS_MIN_FREQUENCY:
-               ret = pm_qos_update_target(&qos->min_frequency,
-                                          &req->data.pnode, action, value);
-               break;
-       case DEV_PM_QOS_MAX_FREQUENCY:
-               ret = pm_qos_update_target(&qos->max_frequency,
-                                          &req->data.pnode, action, value);
-               break;
        case DEV_PM_QOS_FLAGS:
                ret = pm_qos_update_flags(&qos->flags, &req->data.flr,
                                          action, value);
@@ -227,24 +209,6 @@ static int dev_pm_qos_constraints_allocate(struct device *dev)
        c->no_constraint_value = PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT;
        c->type = PM_QOS_MIN;
 
-       c = &qos->min_frequency;
-       plist_head_init(&c->list);
-       c->target_value = PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE;
-       c->default_value = PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE;
-       c->no_constraint_value = PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE;
-       c->type = PM_QOS_MAX;
-       c->notifiers = ++n;
-       BLOCKING_INIT_NOTIFIER_HEAD(n);
-
-       c = &qos->max_frequency;
-       plist_head_init(&c->list);
-       c->target_value = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE;
-       c->default_value = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE;
-       c->no_constraint_value = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE;
-       c->type = PM_QOS_MIN;
-       c->notifiers = ++n;
-       BLOCKING_INIT_NOTIFIER_HEAD(n);
-
        INIT_LIST_HEAD(&qos->flags.list);
 
        spin_lock_irq(&dev->power.lock);
@@ -305,18 +269,6 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
                memset(req, 0, sizeof(*req));
        }
 
-       c = &qos->min_frequency;
-       plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) {
-               apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE);
-               memset(req, 0, sizeof(*req));
-       }
-
-       c = &qos->max_frequency;
-       plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) {
-               apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE);
-               memset(req, 0, sizeof(*req));
-       }
-
        f = &qos->flags;
        list_for_each_entry_safe(req, tmp, &f->list, data.flr.node) {
                apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
@@ -428,8 +380,6 @@ static int __dev_pm_qos_update_request(struct dev_pm_qos_request *req,
        switch(req->type) {
        case DEV_PM_QOS_RESUME_LATENCY:
        case DEV_PM_QOS_LATENCY_TOLERANCE:
-       case DEV_PM_QOS_MIN_FREQUENCY:
-       case DEV_PM_QOS_MAX_FREQUENCY:
                curr_value = req->data.pnode.prio;
                break;
        case DEV_PM_QOS_FLAGS:
@@ -557,14 +507,6 @@ int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier,
                ret = blocking_notifier_chain_register(dev->power.qos->resume_latency.notifiers,
                                                       notifier);
                break;
-       case DEV_PM_QOS_MIN_FREQUENCY:
-               ret = blocking_notifier_chain_register(dev->power.qos->min_frequency.notifiers,
-                                                      notifier);
-               break;
-       case DEV_PM_QOS_MAX_FREQUENCY:
-               ret = blocking_notifier_chain_register(dev->power.qos->max_frequency.notifiers,
-                                                      notifier);
-               break;
        default:
                WARN_ON(1);
                ret = -EINVAL;
@@ -604,14 +546,6 @@ int dev_pm_qos_remove_notifier(struct device *dev,
                ret = blocking_notifier_chain_unregister(dev->power.qos->resume_latency.notifiers,
                                                         notifier);
                break;
-       case DEV_PM_QOS_MIN_FREQUENCY:
-               ret = blocking_notifier_chain_unregister(dev->power.qos->min_frequency.notifiers,
-                                                        notifier);
-               break;
-       case DEV_PM_QOS_MAX_FREQUENCY:
-               ret = blocking_notifier_chain_unregister(dev->power.qos->max_frequency.notifiers,
-                                                        notifier);
-               break;
        default:
                WARN_ON(1);
                ret = -EINVAL;
index 5b248763a672414e925f217216fc21c9a2a257fb..a18155cdce4167dd8dfa6a614c3f084c798c7009 100644 (file)
@@ -786,7 +786,6 @@ int __drbd_send_protocol(struct drbd_connection *connection, enum drbd_packet cm
 
        if (nc->tentative && connection->agreed_pro_version < 92) {
                rcu_read_unlock();
-               mutex_unlock(&sock->mutex);
                drbd_err(connection, "--dry-run is not supported by peer");
                return -EOPNOTSUPP;
        }
index 478aa86fc1f28d9fd39bd3b0b6c7b5ba15de897b..a94ee45440b3b6443ab9921d6a7e2e250e9146bf 100644 (file)
@@ -385,17 +385,16 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req,
        struct nbd_device *nbd = cmd->nbd;
        struct nbd_config *config;
 
+       if (!mutex_trylock(&cmd->lock))
+               return BLK_EH_RESET_TIMER;
+
        if (!refcount_inc_not_zero(&nbd->config_refs)) {
                cmd->status = BLK_STS_TIMEOUT;
+               mutex_unlock(&cmd->lock);
                goto done;
        }
        config = nbd->config;
 
-       if (!mutex_trylock(&cmd->lock)) {
-               nbd_config_put(nbd);
-               return BLK_EH_RESET_TIMER;
-       }
-
        if (config->num_connections > 1) {
                dev_err_ratelimited(nbd_to_dev(nbd),
                                    "Connection timed out, retrying (%d/%d alive)\n",
@@ -711,6 +710,12 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index)
                ret = -ENOENT;
                goto out;
        }
+       if (cmd->status != BLK_STS_OK) {
+               dev_err(disk_to_dev(nbd->disk), "Command already handled %p\n",
+                       req);
+               ret = -ENOENT;
+               goto out;
+       }
        if (test_bit(NBD_CMD_REQUEUED, &cmd->flags)) {
                dev_err(disk_to_dev(nbd->disk), "Raced with timeout on req %p\n",
                        req);
@@ -792,7 +797,10 @@ static bool nbd_clear_req(struct request *req, void *data, bool reserved)
 {
        struct nbd_cmd *cmd = blk_mq_rq_to_pdu(req);
 
+       mutex_lock(&cmd->lock);
        cmd->status = BLK_STS_IOERR;
+       mutex_unlock(&cmd->lock);
+
        blk_mq_complete_request(req);
        return true;
 }
@@ -972,6 +980,25 @@ static blk_status_t nbd_queue_rq(struct blk_mq_hw_ctx *hctx,
        return ret;
 }
 
+static struct socket *nbd_get_socket(struct nbd_device *nbd, unsigned long fd,
+                                    int *err)
+{
+       struct socket *sock;
+
+       *err = 0;
+       sock = sockfd_lookup(fd, err);
+       if (!sock)
+               return NULL;
+
+       if (sock->ops->shutdown == sock_no_shutdown) {
+               dev_err(disk_to_dev(nbd->disk), "Unsupported socket: shutdown callout must be supported.\n");
+               *err = -EINVAL;
+               return NULL;
+       }
+
+       return sock;
+}
+
 static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg,
                          bool netlink)
 {
@@ -981,7 +1008,7 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg,
        struct nbd_sock *nsock;
        int err;
 
-       sock = sockfd_lookup(arg, &err);
+       sock = nbd_get_socket(nbd, arg, &err);
        if (!sock)
                return err;
 
@@ -1033,7 +1060,7 @@ static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg)
        int i;
        int err;
 
-       sock = sockfd_lookup(arg, &err);
+       sock = nbd_get_socket(nbd, arg, &err);
        if (!sock)
                return err;
 
index ad50efb470aaa296bdc9cae1ba7a3ea321ddcf1c..2b6670daf7fc70cd58ac287785d06990bf1cb61e 100644 (file)
@@ -74,6 +74,7 @@ static const char * const clock_names[SYSC_MAX_CLOCKS] = {
  * @clk_disable_quirk: module specific clock disable quirk
  * @reset_done_quirk: module specific reset done quirk
  * @module_enable_quirk: module specific enable quirk
+ * @module_disable_quirk: module specific disable quirk
  */
 struct sysc {
        struct device *dev;
@@ -100,6 +101,7 @@ struct sysc {
        void (*clk_disable_quirk)(struct sysc *sysc);
        void (*reset_done_quirk)(struct sysc *sysc);
        void (*module_enable_quirk)(struct sysc *sysc);
+       void (*module_disable_quirk)(struct sysc *sysc);
 };
 
 static void sysc_parse_dts_quirks(struct sysc *ddata, struct device_node *np,
@@ -959,6 +961,9 @@ static int sysc_disable_module(struct device *dev)
        if (ddata->offsets[SYSC_SYSCONFIG] == -ENODEV)
                return 0;
 
+       if (ddata->module_disable_quirk)
+               ddata->module_disable_quirk(ddata);
+
        regbits = ddata->cap->regbits;
        reg = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]);
 
@@ -1248,6 +1253,9 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
                   SYSC_MODULE_QUIRK_SGX),
        SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0,
                   SYSC_MODULE_QUIRK_WDT),
+       /* Watchdog on am3 and am4 */
+       SYSC_QUIRK("wdt", 0x44e35000, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0,
+                  SYSC_MODULE_QUIRK_WDT | SYSC_QUIRK_SWSUP_SIDLE),
 
 #ifdef DEBUG
        SYSC_QUIRK("adc", 0, 0, 0x10, -1, 0x47300001, 0xffffffff, 0),
@@ -1440,14 +1448,14 @@ static void sysc_reset_done_quirk_wdt(struct sysc *ddata)
                                   !(val & 0x10), 100,
                                   MAX_MODULE_SOFTRESET_WAIT);
        if (error)
-               dev_warn(ddata->dev, "wdt disable spr failed\n");
+               dev_warn(ddata->dev, "wdt disable step1 failed\n");
 
-       sysc_write(ddata, wps, 0x5555);
+       sysc_write(ddata, spr, 0x5555);
        error = readl_poll_timeout(ddata->module_va + wps, val,
                                   !(val & 0x10), 100,
                                   MAX_MODULE_SOFTRESET_WAIT);
        if (error)
-               dev_warn(ddata->dev, "wdt disable wps failed\n");
+               dev_warn(ddata->dev, "wdt disable step2 failed\n");
 }
 
 static void sysc_init_module_quirks(struct sysc *ddata)
@@ -1471,8 +1479,10 @@ static void sysc_init_module_quirks(struct sysc *ddata)
        if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_SGX)
                ddata->module_enable_quirk = sysc_module_enable_quirk_sgx;
 
-       if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_WDT)
+       if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_WDT) {
                ddata->reset_done_quirk = sysc_reset_done_quirk_wdt;
+               ddata->module_disable_quirk = sysc_reset_done_quirk_wdt;
+       }
 }
 
 static int sysc_clockdomain_init(struct sysc *ddata)
index 87083b3a2769d2f383f381a1f82cc219a6ac953e..37c22667e8319011aa5528613c26a9e0544e3e6e 100644 (file)
@@ -297,7 +297,10 @@ static int clk_main_probe_frequency(struct regmap *regmap)
                regmap_read(regmap, AT91_CKGR_MCFR, &mcfr);
                if (mcfr & AT91_PMC_MAINRDY)
                        return 0;
-               usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT);
+               if (system_state < SYSTEM_RUNNING)
+                       udelay(MAINF_LOOP_MIN_WAIT);
+               else
+                       usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT);
        } while (time_before(prep_time, timeout));
 
        return -ETIMEDOUT;
index 9790ddfa5b3cba525c368bc4860a7a64067aac96..86238d5ecb4da948add6b2b3b203cda5cdd7bc21 100644 (file)
@@ -43,6 +43,7 @@ static const struct clk_pll_characteristics upll_characteristics = {
 };
 
 static const struct clk_programmable_layout sam9x60_programmable_layout = {
+       .pres_mask = 0xff,
        .pres_shift = 8,
        .css_mask = 0x1f,
        .have_slck_mck = 0,
index 9bfe9a28294a7ec7f5acbb38f7e21f477355839e..fac0ca56d42d92a3df623f2d3e69cb5ca380e639 100644 (file)
@@ -76,7 +76,10 @@ static int clk_slow_osc_prepare(struct clk_hw *hw)
 
        writel(tmp | osc->bits->cr_osc32en, sckcr);
 
-       usleep_range(osc->startup_usec, osc->startup_usec + 1);
+       if (system_state < SYSTEM_RUNNING)
+               udelay(osc->startup_usec);
+       else
+               usleep_range(osc->startup_usec, osc->startup_usec + 1);
 
        return 0;
 }
@@ -187,7 +190,10 @@ static int clk_slow_rc_osc_prepare(struct clk_hw *hw)
 
        writel(readl(sckcr) | osc->bits->cr_rcen, sckcr);
 
-       usleep_range(osc->startup_usec, osc->startup_usec + 1);
+       if (system_state < SYSTEM_RUNNING)
+               udelay(osc->startup_usec);
+       else
+               usleep_range(osc->startup_usec, osc->startup_usec + 1);
 
        return 0;
 }
@@ -288,7 +294,10 @@ static int clk_sam9x5_slow_set_parent(struct clk_hw *hw, u8 index)
 
        writel(tmp, sckcr);
 
-       usleep_range(SLOWCK_SW_TIME_USEC, SLOWCK_SW_TIME_USEC + 1);
+       if (system_state < SYSTEM_RUNNING)
+               udelay(SLOWCK_SW_TIME_USEC);
+       else
+               usleep_range(SLOWCK_SW_TIME_USEC, SLOWCK_SW_TIME_USEC + 1);
 
        return 0;
 }
@@ -533,7 +542,10 @@ static int clk_sama5d4_slow_osc_prepare(struct clk_hw *hw)
                return 0;
        }
 
-       usleep_range(osc->startup_usec, osc->startup_usec + 1);
+       if (system_state < SYSTEM_RUNNING)
+               udelay(osc->startup_usec);
+       else
+               usleep_range(osc->startup_usec, osc->startup_usec + 1);
        osc->prepared = true;
 
        return 0;
index 1c1bb39bb04e672ccb73bd66f78ba61f6fbac787..b1318e6b655bcc615cef2354d96278ea71f836ea 100644 (file)
@@ -266,10 +266,11 @@ static int aspeed_g6_clk_enable(struct clk_hw *hw)
 
        /* Enable clock */
        if (gate->flags & CLK_GATE_SET_TO_DISABLE) {
-               regmap_write(gate->map, get_clock_reg(gate), clk);
-       } else {
-               /* Use set to clear register */
+               /* Clock is clear to enable, so use set to clear register */
                regmap_write(gate->map, get_clock_reg(gate) + 0x04, clk);
+       } else {
+               /* Clock is set to enable, so use write to set register */
+               regmap_write(gate->map, get_clock_reg(gate), clk);
        }
 
        if (gate->reset_idx >= 0) {
index 067ab876911dd4979dae95746b0389f5bcd3caa8..172589e94f60e17658c4896b5127f0c94a170f95 100644 (file)
@@ -638,7 +638,7 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
                                           clks[IMX8MM_CLK_A53_DIV],
                                           clks[IMX8MM_CLK_A53_SRC],
                                           clks[IMX8MM_ARM_PLL_OUT],
-                                          clks[IMX8MM_CLK_24M]);
+                                          clks[IMX8MM_SYS_PLL1_800M]);
 
        imx_check_clocks(clks, ARRAY_SIZE(clks));
 
index 47a4b44ba3cb00319297e5afa2ec1490c50481be..58b5acee38306909e76e08587f6f310bceeab3ff 100644 (file)
@@ -610,7 +610,7 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
                                           clks[IMX8MN_CLK_A53_DIV],
                                           clks[IMX8MN_CLK_A53_SRC],
                                           clks[IMX8MN_ARM_PLL_OUT],
-                                          clks[IMX8MN_CLK_24M]);
+                                          clks[IMX8MN_SYS_PLL1_800M]);
 
        imx_check_clocks(clks, ARRAY_SIZE(clks));
 
index ea4c791f106ddb9604779c7805168c059cbfbf8e..b3af61cc6fb9497059aefa08e015e95c470ea294 100644 (file)
@@ -343,6 +343,7 @@ static struct clk_regmap g12a_cpu_clk_premux0 = {
                .offset = HHI_SYS_CPU_CLK_CNTL0,
                .mask = 0x3,
                .shift = 0,
+               .flags = CLK_MUX_ROUND_CLOSEST,
        },
        .hw.init = &(struct clk_init_data){
                .name = "cpu_clk_dyn0_sel",
@@ -353,8 +354,7 @@ static struct clk_regmap g12a_cpu_clk_premux0 = {
                        { .hw = &g12a_fclk_div3.hw },
                },
                .num_parents = 3,
-               /* This sub-tree is used a parking clock */
-               .flags = CLK_SET_RATE_NO_REPARENT,
+               .flags = CLK_SET_RATE_PARENT,
        },
 };
 
@@ -410,6 +410,7 @@ static struct clk_regmap g12a_cpu_clk_postmux0 = {
                .offset = HHI_SYS_CPU_CLK_CNTL0,
                .mask = 0x1,
                .shift = 2,
+               .flags = CLK_MUX_ROUND_CLOSEST,
        },
        .hw.init = &(struct clk_init_data){
                .name = "cpu_clk_dyn0",
@@ -466,6 +467,7 @@ static struct clk_regmap g12a_cpu_clk_dyn = {
                .offset = HHI_SYS_CPU_CLK_CNTL0,
                .mask = 0x1,
                .shift = 10,
+               .flags = CLK_MUX_ROUND_CLOSEST,
        },
        .hw.init = &(struct clk_init_data){
                .name = "cpu_clk_dyn",
@@ -485,6 +487,7 @@ static struct clk_regmap g12a_cpu_clk = {
                .offset = HHI_SYS_CPU_CLK_CNTL0,
                .mask = 0x1,
                .shift = 11,
+               .flags = CLK_MUX_ROUND_CLOSEST,
        },
        .hw.init = &(struct clk_init_data){
                .name = "cpu_clk",
@@ -504,6 +507,7 @@ static struct clk_regmap g12b_cpu_clk = {
                .offset = HHI_SYS_CPU_CLK_CNTL0,
                .mask = 0x1,
                .shift = 11,
+               .flags = CLK_MUX_ROUND_CLOSEST,
        },
        .hw.init = &(struct clk_init_data){
                .name = "cpu_clk",
@@ -523,6 +527,7 @@ static struct clk_regmap g12b_cpub_clk_premux0 = {
                .offset = HHI_SYS_CPUB_CLK_CNTL,
                .mask = 0x3,
                .shift = 0,
+               .flags = CLK_MUX_ROUND_CLOSEST,
        },
        .hw.init = &(struct clk_init_data){
                .name = "cpub_clk_dyn0_sel",
@@ -533,6 +538,7 @@ static struct clk_regmap g12b_cpub_clk_premux0 = {
                        { .hw = &g12a_fclk_div3.hw },
                },
                .num_parents = 3,
+               .flags = CLK_SET_RATE_PARENT,
        },
 };
 
@@ -567,6 +573,7 @@ static struct clk_regmap g12b_cpub_clk_postmux0 = {
                .offset = HHI_SYS_CPUB_CLK_CNTL,
                .mask = 0x1,
                .shift = 2,
+               .flags = CLK_MUX_ROUND_CLOSEST,
        },
        .hw.init = &(struct clk_init_data){
                .name = "cpub_clk_dyn0",
@@ -644,6 +651,7 @@ static struct clk_regmap g12b_cpub_clk_dyn = {
                .offset = HHI_SYS_CPUB_CLK_CNTL,
                .mask = 0x1,
                .shift = 10,
+               .flags = CLK_MUX_ROUND_CLOSEST,
        },
        .hw.init = &(struct clk_init_data){
                .name = "cpub_clk_dyn",
@@ -663,6 +671,7 @@ static struct clk_regmap g12b_cpub_clk = {
                .offset = HHI_SYS_CPUB_CLK_CNTL,
                .mask = 0x1,
                .shift = 11,
+               .flags = CLK_MUX_ROUND_CLOSEST,
        },
        .hw.init = &(struct clk_init_data){
                .name = "cpub_clk",
index 7cfb998eeb3e0e05234f041ce0bb6938dc7db1f9..1f9c056e684ce0bf93cff9f4868da37d7f4282f2 100644 (file)
@@ -935,6 +935,7 @@ static struct clk_regmap gxbb_sar_adc_clk_div = {
                        &gxbb_sar_adc_clk_sel.hw
                },
                .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
        },
 };
 
index 7670cc596c74245205babf39e339c8e0b5e087f6..31466cd1842f860727869e651a748839e67ec2e5 100644 (file)
@@ -165,12 +165,18 @@ static const unsigned long exynos5x_clk_regs[] __initconst = {
        GATE_BUS_CPU,
        GATE_SCLK_CPU,
        CLKOUT_CMU_CPU,
+       CPLL_CON0,
+       DPLL_CON0,
        EPLL_CON0,
        EPLL_CON1,
        EPLL_CON2,
        RPLL_CON0,
        RPLL_CON1,
        RPLL_CON2,
+       IPLL_CON0,
+       SPLL_CON0,
+       VPLL_CON0,
+       MPLL_CON0,
        SRC_TOP0,
        SRC_TOP1,
        SRC_TOP2,
@@ -1172,8 +1178,6 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = {
        GATE(CLK_SCLK_ISP_SENSOR2, "sclk_isp_sensor2", "dout_isp_sensor2",
                        GATE_TOP_SCLK_ISP, 12, CLK_SET_RATE_PARENT, 0),
 
-       GATE(CLK_G3D, "g3d", "mout_user_aclk_g3d", GATE_IP_G3D, 9, 0, 0),
-
        /* CDREX */
        GATE(CLK_CLKM_PHY0, "clkm_phy0", "dout_sclk_cdrex",
                        GATE_BUS_CDREX0, 0, 0, 0),
@@ -1248,6 +1252,15 @@ static struct exynos5_subcmu_reg_dump exynos5x_gsc_suspend_regs[] = {
        { DIV2_RATIO0, 0, 0x30 },       /* DIV dout_gscl_blk_300 */
 };
 
+static const struct samsung_gate_clock exynos5x_g3d_gate_clks[] __initconst = {
+       GATE(CLK_G3D, "g3d", "mout_user_aclk_g3d", GATE_IP_G3D, 9, 0, 0),
+};
+
+static struct exynos5_subcmu_reg_dump exynos5x_g3d_suspend_regs[] = {
+       { GATE_IP_G3D, 0x3ff, 0x3ff },  /* G3D gates */
+       { SRC_TOP5, 0, BIT(16) },       /* MUX mout_user_aclk_g3d */
+};
+
 static const struct samsung_div_clock exynos5x_mfc_div_clks[] __initconst = {
        DIV(0, "dout_mfc_blk", "mout_user_aclk333", DIV4_RATIO, 0, 2),
 };
@@ -1320,6 +1333,14 @@ static const struct exynos5_subcmu_info exynos5x_gsc_subcmu = {
        .pd_name        = "GSC",
 };
 
+static const struct exynos5_subcmu_info exynos5x_g3d_subcmu = {
+       .gate_clks      = exynos5x_g3d_gate_clks,
+       .nr_gate_clks   = ARRAY_SIZE(exynos5x_g3d_gate_clks),
+       .suspend_regs   = exynos5x_g3d_suspend_regs,
+       .nr_suspend_regs = ARRAY_SIZE(exynos5x_g3d_suspend_regs),
+       .pd_name        = "G3D",
+};
+
 static const struct exynos5_subcmu_info exynos5x_mfc_subcmu = {
        .div_clks       = exynos5x_mfc_div_clks,
        .nr_div_clks    = ARRAY_SIZE(exynos5x_mfc_div_clks),
@@ -1351,6 +1372,7 @@ static const struct exynos5_subcmu_info exynos5800_mau_subcmu = {
 static const struct exynos5_subcmu_info *exynos5x_subcmus[] = {
        &exynos5x_disp_subcmu,
        &exynos5x_gsc_subcmu,
+       &exynos5x_g3d_subcmu,
        &exynos5x_mfc_subcmu,
        &exynos5x_mscl_subcmu,
 };
@@ -1358,6 +1380,7 @@ static const struct exynos5_subcmu_info *exynos5x_subcmus[] = {
 static const struct exynos5_subcmu_info *exynos5800_subcmus[] = {
        &exynos5x_disp_subcmu,
        &exynos5x_gsc_subcmu,
+       &exynos5x_g3d_subcmu,
        &exynos5x_mfc_subcmu,
        &exynos5x_mscl_subcmu,
        &exynos5800_mau_subcmu,
index 7824c2ba3d8e6c29c850f67655da8b9fd0d6201d..4b1aa9382ad28e01e755e6207d78c0720ec5c665 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/slab.h>
 
 #include <dt-bindings/clock/exynos5433.h>
 
@@ -5584,6 +5585,8 @@ static int __init exynos5433_cmu_probe(struct platform_device *pdev)
 
        data->clk_save = samsung_clk_alloc_reg_dump(info->clk_regs,
                                                    info->nr_clk_regs);
+       if (!data->clk_save)
+               return -ENOMEM;
        data->nr_clk_save = info->nr_clk_regs;
        data->clk_suspend = info->suspend_regs;
        data->nr_clk_suspend = info->nr_suspend_regs;
@@ -5592,12 +5595,19 @@ static int __init exynos5433_cmu_probe(struct platform_device *pdev)
        if (data->nr_pclks > 0) {
                data->pclks = devm_kcalloc(dev, sizeof(struct clk *),
                                           data->nr_pclks, GFP_KERNEL);
-
+               if (!data->pclks) {
+                       kfree(data->clk_save);
+                       return -ENOMEM;
+               }
                for (i = 0; i < data->nr_pclks; i++) {
                        struct clk *clk = of_clk_get(dev->of_node, i);
 
-                       if (IS_ERR(clk))
+                       if (IS_ERR(clk)) {
+                               kfree(data->clk_save);
+                               while (--i >= 0)
+                                       clk_put(data->pclks[i]);
                                return PTR_ERR(clk);
+                       }
                        data->pclks[i] = clk;
                }
        }
index dcac1391767f6887913d91f8c5938d26822b5bc5..ef29582676f6eee6a5aeed679730ebd5c942ecae 100644 (file)
@@ -1224,7 +1224,7 @@ static int sun9i_a80_ccu_probe(struct platform_device *pdev)
 
        /* Enforce d1 = 0, d2 = 0 for Audio PLL */
        val = readl(reg + SUN9I_A80_PLL_AUDIO_REG);
-       val &= (BIT(16) & BIT(18));
+       val &= ~(BIT(16) | BIT(18));
        writel(val, reg + SUN9I_A80_PLL_AUDIO_REG);
 
        /* Enforce P = 1 for both CPU cluster PLLs */
index d3a43381a792700a96f618e4e86924612d529aa3..27201fd26e4422b7bd5eba152be7e0693029c95a 100644 (file)
@@ -1080,8 +1080,8 @@ static struct clk ** __init sunxi_divs_clk_setup(struct device_node *node,
                                                 rate_hw, rate_ops,
                                                 gate_hw, &clk_gate_ops,
                                                 clkflags |
-                                                data->div[i].critical ?
-                                                       CLK_IS_CRITICAL : 0);
+                                                (data->div[i].critical ?
+                                                       CLK_IS_CRITICAL : 0));
 
                WARN_ON(IS_ERR(clk_data->clks[i]));
        }
index a01ca9395179a77c9f0c620e5389fe98b1d0fba3..f65e16c4f3c4b8585ea56cc97633730a6882a01f 100644 (file)
@@ -174,7 +174,6 @@ static void __init of_dra7_atl_clock_setup(struct device_node *node)
        struct clk_init_data init = { NULL };
        const char **parent_names = NULL;
        struct clk *clk;
-       int ret;
 
        clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
        if (!clk_hw) {
@@ -207,11 +206,6 @@ static void __init of_dra7_atl_clock_setup(struct device_node *node)
        clk = ti_clk_register(NULL, &clk_hw->hw, node->name);
 
        if (!IS_ERR(clk)) {
-               ret = ti_clk_add_alias(NULL, clk, node->name);
-               if (ret) {
-                       clk_unregister(clk);
-                       goto cleanup;
-               }
                of_clk_add_provider(node, of_clk_src_simple_get, clk);
                kfree(parent_names);
                return;
index 975995eea15cb51d64100e625f6b433c34998998..b0c0690a5a121ab35b173bc26a40c4720a2d18a1 100644 (file)
@@ -100,11 +100,12 @@ static bool _omap4_is_timeout(union omap4_timeout *time, u32 timeout)
         * can be from a timer that requires pm_runtime access, which
         * will eventually bring us here with timekeeping_suspended,
         * during both suspend entry and resume paths. This happens
-        * at least on am43xx platform.
+        * at least on am43xx platform. Account for flakeyness
+        * with udelay() by multiplying the timeout value by 2.
         */
        if (unlikely(_early_timeout || timekeeping_suspended)) {
                if (time->cycles++ < timeout) {
-                       udelay(1);
+                       udelay(1 * 2);
                        return false;
                }
        } else {
index 354b27d14a19bfcef43656f3555e69a32b28da2d..62812f80b5cc0916d3a38146ac6b3b75c4b9915f 100644 (file)
@@ -328,12 +328,13 @@ static int sh_mtu2_register(struct sh_mtu2_channel *ch, const char *name)
        return 0;
 }
 
+static const unsigned int sh_mtu2_channel_offsets[] = {
+       0x300, 0x380, 0x000,
+};
+
 static int sh_mtu2_setup_channel(struct sh_mtu2_channel *ch, unsigned int index,
                                 struct sh_mtu2_device *mtu)
 {
-       static const unsigned int channel_offsets[] = {
-               0x300, 0x380, 0x000,
-       };
        char name[6];
        int irq;
        int ret;
@@ -356,7 +357,7 @@ static int sh_mtu2_setup_channel(struct sh_mtu2_channel *ch, unsigned int index,
                return ret;
        }
 
-       ch->base = mtu->mapbase + channel_offsets[index];
+       ch->base = mtu->mapbase + sh_mtu2_channel_offsets[index];
        ch->index = index;
 
        return sh_mtu2_register(ch, dev_name(&mtu->pdev->dev));
@@ -408,7 +409,12 @@ static int sh_mtu2_setup(struct sh_mtu2_device *mtu,
        }
 
        /* Allocate and setup the channels. */
-       mtu->num_channels = 3;
+       ret = platform_irq_count(pdev);
+       if (ret < 0)
+               goto err_unmap;
+
+       mtu->num_channels = min_t(unsigned int, ret,
+                                 ARRAY_SIZE(sh_mtu2_channel_offsets));
 
        mtu->channels = kcalloc(mtu->num_channels, sizeof(*mtu->channels),
                                GFP_KERNEL);
index a562f491b0f8ddd3b856b38935d7a0fdad6102b6..9318edcd89635ea195e1389ef8acc1853358c216 100644 (file)
@@ -268,15 +268,12 @@ static int __init mtk_syst_init(struct device_node *node)
 
        ret = timer_of_init(node, &to);
        if (ret)
-               goto err;
+               return ret;
 
        clockevents_config_and_register(&to.clkevt, timer_of_rate(&to),
                                        TIMER_SYNC_TICKS, 0xffffffff);
 
        return 0;
-err:
-       timer_of_cleanup(&to);
-       return ret;
 }
 
 static int __init mtk_gpt_init(struct device_node *node)
@@ -293,7 +290,7 @@ static int __init mtk_gpt_init(struct device_node *node)
 
        ret = timer_of_init(node, &to);
        if (ret)
-               goto err;
+               return ret;
 
        /* Configure clock source */
        mtk_gpt_setup(&to, TIMER_CLK_SRC, GPT_CTRL_OP_FREERUN);
@@ -311,9 +308,6 @@ static int __init mtk_gpt_init(struct device_node *node)
        mtk_gpt_enable_irq(&to, TIMER_CLK_EVT);
 
        return 0;
-err:
-       timer_of_cleanup(&to);
-       return ret;
 }
 TIMER_OF_DECLARE(mtk_mt6577, "mediatek,mt6577-timer", mtk_gpt_init);
 TIMER_OF_DECLARE(mtk_mt6765, "mediatek,mt6765-timer", mtk_syst_init);
index bffc11b872474e1f251d9e67580d6a36cd979aa4..48a224a6b17815ae789ee8bede83508cc8f077d9 100644 (file)
@@ -720,7 +720,7 @@ static ssize_t store_##file_name                                    \
        if (ret != 1)                                                   \
                return -EINVAL;                                         \
                                                                        \
-       ret = dev_pm_qos_update_request(policy->object##_freq_req, val);\
+       ret = freq_qos_update_request(policy->object##_freq_req, val);\
        return ret >= 0 ? count : ret;                                  \
 }
 
@@ -1202,19 +1202,21 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
                goto err_free_real_cpus;
        }
 
+       freq_constraints_init(&policy->constraints);
+
        policy->nb_min.notifier_call = cpufreq_notifier_min;
        policy->nb_max.notifier_call = cpufreq_notifier_max;
 
-       ret = dev_pm_qos_add_notifier(dev, &policy->nb_min,
-                                     DEV_PM_QOS_MIN_FREQUENCY);
+       ret = freq_qos_add_notifier(&policy->constraints, FREQ_QOS_MIN,
+                                   &policy->nb_min);
        if (ret) {
                dev_err(dev, "Failed to register MIN QoS notifier: %d (%*pbl)\n",
                        ret, cpumask_pr_args(policy->cpus));
                goto err_kobj_remove;
        }
 
-       ret = dev_pm_qos_add_notifier(dev, &policy->nb_max,
-                                     DEV_PM_QOS_MAX_FREQUENCY);
+       ret = freq_qos_add_notifier(&policy->constraints, FREQ_QOS_MAX,
+                                   &policy->nb_max);
        if (ret) {
                dev_err(dev, "Failed to register MAX QoS notifier: %d (%*pbl)\n",
                        ret, cpumask_pr_args(policy->cpus));
@@ -1232,8 +1234,8 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
        return policy;
 
 err_min_qos_notifier:
-       dev_pm_qos_remove_notifier(dev, &policy->nb_min,
-                                  DEV_PM_QOS_MIN_FREQUENCY);
+       freq_qos_remove_notifier(&policy->constraints, FREQ_QOS_MIN,
+                                &policy->nb_min);
 err_kobj_remove:
        cpufreq_policy_put_kobj(policy);
 err_free_real_cpus:
@@ -1250,7 +1252,6 @@ err_free_policy:
 
 static void cpufreq_policy_free(struct cpufreq_policy *policy)
 {
-       struct device *dev = get_cpu_device(policy->cpu);
        unsigned long flags;
        int cpu;
 
@@ -1262,10 +1263,13 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy)
                per_cpu(cpufreq_cpu_data, cpu) = NULL;
        write_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
-       dev_pm_qos_remove_notifier(dev, &policy->nb_max,
-                                  DEV_PM_QOS_MAX_FREQUENCY);
-       dev_pm_qos_remove_notifier(dev, &policy->nb_min,
-                                  DEV_PM_QOS_MIN_FREQUENCY);
+       freq_qos_remove_notifier(&policy->constraints, FREQ_QOS_MAX,
+                                &policy->nb_max);
+       freq_qos_remove_notifier(&policy->constraints, FREQ_QOS_MIN,
+                                &policy->nb_min);
+
+       /* Cancel any pending policy->update work before freeing the policy. */
+       cancel_work_sync(&policy->update);
 
        if (policy->max_freq_req) {
                /*
@@ -1274,10 +1278,10 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy)
                 */
                blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
                                             CPUFREQ_REMOVE_POLICY, policy);
-               dev_pm_qos_remove_request(policy->max_freq_req);
+               freq_qos_remove_request(policy->max_freq_req);
        }
 
-       dev_pm_qos_remove_request(policy->min_freq_req);
+       freq_qos_remove_request(policy->min_freq_req);
        kfree(policy->min_freq_req);
 
        cpufreq_policy_put_kobj(policy);
@@ -1357,8 +1361,6 @@ static int cpufreq_online(unsigned int cpu)
        cpumask_and(policy->cpus, policy->cpus, cpu_online_mask);
 
        if (new_policy) {
-               struct device *dev = get_cpu_device(cpu);
-
                for_each_cpu(j, policy->related_cpus) {
                        per_cpu(cpufreq_cpu_data, j) = policy;
                        add_cpu_dev_symlink(policy, j);
@@ -1369,36 +1371,31 @@ static int cpufreq_online(unsigned int cpu)
                if (!policy->min_freq_req)
                        goto out_destroy_policy;
 
-               ret = dev_pm_qos_add_request(dev, policy->min_freq_req,
-                                            DEV_PM_QOS_MIN_FREQUENCY,
-                                            policy->min);
+               ret = freq_qos_add_request(&policy->constraints,
+                                          policy->min_freq_req, FREQ_QOS_MIN,
+                                          policy->min);
                if (ret < 0) {
                        /*
-                        * So we don't call dev_pm_qos_remove_request() for an
+                        * So we don't call freq_qos_remove_request() for an
                         * uninitialized request.
                         */
                        kfree(policy->min_freq_req);
                        policy->min_freq_req = NULL;
-
-                       dev_err(dev, "Failed to add min-freq constraint (%d)\n",
-                               ret);
                        goto out_destroy_policy;
                }
 
                /*
                 * This must be initialized right here to avoid calling
-                * dev_pm_qos_remove_request() on uninitialized request in case
+                * freq_qos_remove_request() on uninitialized request in case
                 * of errors.
                 */
                policy->max_freq_req = policy->min_freq_req + 1;
 
-               ret = dev_pm_qos_add_request(dev, policy->max_freq_req,
-                                            DEV_PM_QOS_MAX_FREQUENCY,
-                                            policy->max);
+               ret = freq_qos_add_request(&policy->constraints,
+                                          policy->max_freq_req, FREQ_QOS_MAX,
+                                          policy->max);
                if (ret < 0) {
                        policy->max_freq_req = NULL;
-                       dev_err(dev, "Failed to add max-freq constraint (%d)\n",
-                               ret);
                        goto out_destroy_policy;
                }
 
@@ -2374,7 +2371,6 @@ int cpufreq_set_policy(struct cpufreq_policy *policy,
                       struct cpufreq_policy *new_policy)
 {
        struct cpufreq_governor *old_gov;
-       struct device *cpu_dev = get_cpu_device(policy->cpu);
        int ret;
 
        pr_debug("setting new policy for CPU %u: %u - %u kHz\n",
@@ -2386,8 +2382,8 @@ int cpufreq_set_policy(struct cpufreq_policy *policy,
         * PM QoS framework collects all the requests from users and provide us
         * the final aggregated value here.
         */
-       new_policy->min = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MIN_FREQUENCY);
-       new_policy->max = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MAX_FREQUENCY);
+       new_policy->min = freq_qos_read_value(&policy->constraints, FREQ_QOS_MIN);
+       new_policy->max = freq_qos_read_value(&policy->constraints, FREQ_QOS_MAX);
 
        /* verify the cpu speed can be set within this limit */
        ret = cpufreq_driver->verify(new_policy);
@@ -2518,7 +2514,7 @@ static int cpufreq_boost_set_sw(int state)
                        break;
                }
 
-               ret = dev_pm_qos_update_request(policy->max_freq_req, policy->max);
+               ret = freq_qos_update_request(policy->max_freq_req, policy->max);
                if (ret < 0)
                        break;
        }
index 9f02de9a1b4743ea7d01c2a3ff9f85e0cb81a997..8ab31702cf6a26daa5e9e9ab6e641f309f0d228a 100644 (file)
@@ -847,11 +847,9 @@ static void intel_pstate_hwp_force_min_perf(int cpu)
        value |= HWP_MAX_PERF(min_perf);
        value |= HWP_MIN_PERF(min_perf);
 
-       /* Set EPP/EPB to min */
+       /* Set EPP to min */
        if (boot_cpu_has(X86_FEATURE_HWP_EPP))
                value |= HWP_ENERGY_PERF_PREFERENCE(HWP_EPP_POWERSAVE);
-       else
-               intel_pstate_set_epb(cpu, HWP_EPP_BALANCE_POWERSAVE);
 
        wrmsrl_on_cpu(cpu, MSR_HWP_REQUEST, value);
 }
@@ -1088,10 +1086,10 @@ static ssize_t store_no_turbo(struct kobject *a, struct kobj_attribute *b,
 
 static struct cpufreq_driver intel_pstate;
 
-static void update_qos_request(enum dev_pm_qos_req_type type)
+static void update_qos_request(enum freq_qos_req_type type)
 {
        int max_state, turbo_max, freq, i, perf_pct;
-       struct dev_pm_qos_request *req;
+       struct freq_qos_request *req;
        struct cpufreq_policy *policy;
 
        for_each_possible_cpu(i) {
@@ -1112,7 +1110,7 @@ static void update_qos_request(enum dev_pm_qos_req_type type)
                else
                        turbo_max = cpu->pstate.turbo_pstate;
 
-               if (type == DEV_PM_QOS_MIN_FREQUENCY) {
+               if (type == FREQ_QOS_MIN) {
                        perf_pct = global.min_perf_pct;
                } else {
                        req++;
@@ -1122,7 +1120,7 @@ static void update_qos_request(enum dev_pm_qos_req_type type)
                freq = DIV_ROUND_UP(turbo_max * perf_pct, 100);
                freq *= cpu->pstate.scaling;
 
-               if (dev_pm_qos_update_request(req, freq) < 0)
+               if (freq_qos_update_request(req, freq) < 0)
                        pr_warn("Failed to update freq constraint: CPU%d\n", i);
        }
 }
@@ -1153,7 +1151,7 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct kobj_attribute *b,
        if (intel_pstate_driver == &intel_pstate)
                intel_pstate_update_policies();
        else
-               update_qos_request(DEV_PM_QOS_MAX_FREQUENCY);
+               update_qos_request(FREQ_QOS_MAX);
 
        mutex_unlock(&intel_pstate_driver_lock);
 
@@ -1187,7 +1185,7 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct kobj_attribute *b,
        if (intel_pstate_driver == &intel_pstate)
                intel_pstate_update_policies();
        else
-               update_qos_request(DEV_PM_QOS_MIN_FREQUENCY);
+               update_qos_request(FREQ_QOS_MIN);
 
        mutex_unlock(&intel_pstate_driver_lock);
 
@@ -2381,7 +2379,7 @@ static unsigned int intel_cpufreq_fast_switch(struct cpufreq_policy *policy,
 static int intel_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
        int max_state, turbo_max, min_freq, max_freq, ret;
-       struct dev_pm_qos_request *req;
+       struct freq_qos_request *req;
        struct cpudata *cpu;
        struct device *dev;
 
@@ -2416,15 +2414,15 @@ static int intel_cpufreq_cpu_init(struct cpufreq_policy *policy)
        max_freq = DIV_ROUND_UP(turbo_max * global.max_perf_pct, 100);
        max_freq *= cpu->pstate.scaling;
 
-       ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_MIN_FREQUENCY,
-                                    min_freq);
+       ret = freq_qos_add_request(&policy->constraints, req, FREQ_QOS_MIN,
+                                  min_freq);
        if (ret < 0) {
                dev_err(dev, "Failed to add min-freq constraint (%d)\n", ret);
                goto free_req;
        }
 
-       ret = dev_pm_qos_add_request(dev, req + 1, DEV_PM_QOS_MAX_FREQUENCY,
-                                    max_freq);
+       ret = freq_qos_add_request(&policy->constraints, req + 1, FREQ_QOS_MAX,
+                                  max_freq);
        if (ret < 0) {
                dev_err(dev, "Failed to add max-freq constraint (%d)\n", ret);
                goto remove_min_req;
@@ -2435,7 +2433,7 @@ static int intel_cpufreq_cpu_init(struct cpufreq_policy *policy)
        return 0;
 
 remove_min_req:
-       dev_pm_qos_remove_request(req);
+       freq_qos_remove_request(req);
 free_req:
        kfree(req);
 pstate_exit:
@@ -2446,12 +2444,12 @@ pstate_exit:
 
 static int intel_cpufreq_cpu_exit(struct cpufreq_policy *policy)
 {
-       struct dev_pm_qos_request *req;
+       struct freq_qos_request *req;
 
        req = policy->driver_data;
 
-       dev_pm_qos_remove_request(req + 1);
-       dev_pm_qos_remove_request(req);
+       freq_qos_remove_request(req + 1);
+       freq_qos_remove_request(req);
        kfree(req);
 
        return intel_pstate_cpu_exit(policy);
index bc9dd30395c402893d2ca71a5b78a96888c3526e..037fe23bc6ed0feeb76384126706a24cab82b863 100644 (file)
@@ -65,7 +65,7 @@ EXPORT_SYMBOL_GPL(cbe_cpufreq_set_pmode_pmi);
 static void cbe_cpufreq_handle_pmi(pmi_message_t pmi_msg)
 {
        struct cpufreq_policy *policy;
-       struct dev_pm_qos_request *req;
+       struct freq_qos_request *req;
        u8 node, slow_mode;
        int cpu, ret;
 
@@ -86,7 +86,7 @@ static void cbe_cpufreq_handle_pmi(pmi_message_t pmi_msg)
 
        req = policy->driver_data;
 
-       ret = dev_pm_qos_update_request(req,
+       ret = freq_qos_update_request(req,
                        policy->freq_table[slow_mode].frequency);
        if (ret < 0)
                pr_warn("Failed to update freq constraint: %d\n", ret);
@@ -103,7 +103,7 @@ static struct pmi_handler cbe_pmi_handler = {
 
 void cbe_cpufreq_pmi_policy_init(struct cpufreq_policy *policy)
 {
-       struct dev_pm_qos_request *req;
+       struct freq_qos_request *req;
        int ret;
 
        if (!cbe_cpufreq_has_pmi)
@@ -113,9 +113,8 @@ void cbe_cpufreq_pmi_policy_init(struct cpufreq_policy *policy)
        if (!req)
                return;
 
-       ret = dev_pm_qos_add_request(get_cpu_device(policy->cpu), req,
-                                    DEV_PM_QOS_MAX_FREQUENCY,
-                                    policy->freq_table[0].frequency);
+       ret = freq_qos_add_request(&policy->constraints, req, FREQ_QOS_MAX,
+                                  policy->freq_table[0].frequency);
        if (ret < 0) {
                pr_err("Failed to add freq constraint (%d)\n", ret);
                kfree(req);
@@ -128,10 +127,10 @@ EXPORT_SYMBOL_GPL(cbe_cpufreq_pmi_policy_init);
 
 void cbe_cpufreq_pmi_policy_exit(struct cpufreq_policy *policy)
 {
-       struct dev_pm_qos_request *req = policy->driver_data;
+       struct freq_qos_request *req = policy->driver_data;
 
        if (cbe_cpufreq_has_pmi) {
-               dev_pm_qos_remove_request(req);
+               freq_qos_remove_request(req);
                kfree(req);
        }
 }
index 932390b028f1df148d8f96bd6a5b1b6b36fcec72..b0ce9bc78113e6bde532101ffe0beba9c9baf860 100644 (file)
@@ -95,6 +95,10 @@ static int __init haltpoll_init(void)
        int ret;
        struct cpuidle_driver *drv = &haltpoll_driver;
 
+       /* Do not load haltpoll if idle= is passed */
+       if (boot_option_idle_override != IDLE_NO_OVERRIDE)
+               return -ENODEV;
+
        cpuidle_poll_state_init(drv);
 
        if (!kvm_para_available() ||
index 774d991d7cca49011016d41c00914ad84059ccb8..aca75237bbcf83eb1d440bcdf1e4d3b702cff0a1 100644 (file)
@@ -1297,7 +1297,7 @@ static void make_established(struct sock *sk, u32 snd_isn, unsigned int opt)
        tp->write_seq = snd_isn;
        tp->snd_nxt = snd_isn;
        tp->snd_una = snd_isn;
-       inet_sk(sk)->inet_id = tp->write_seq ^ jiffies;
+       inet_sk(sk)->inet_id = prandom_u32();
        assign_rxopt(sk, opt);
 
        if (tp->rcv_wnd > (RCV_BUFSIZ_M << 10))
index 0891ab829b1b6b1318353e945e6394fab29f7c1e..98bc5a4cd5e7014990f064a92777308ae98b13e4 100644 (file)
@@ -1702,7 +1702,7 @@ int chtls_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
                return peekmsg(sk, msg, len, nonblock, flags);
 
        if (sk_can_busy_loop(sk) &&
-           skb_queue_empty(&sk->sk_receive_queue) &&
+           skb_queue_empty_lockless(&sk->sk_receive_queue) &&
            sk->sk_state == TCP_ESTABLISHED)
                sk_busy_loop(sk, nonblock);
 
index 9ba74ab7e912e90fe78ab9f02b4120d79ab14fb4..c27e206a764c3599ef8e548c4d9491399ce70c13 100644 (file)
@@ -1707,6 +1707,14 @@ static void sdma_add_scripts(struct sdma_engine *sdma,
        if (!sdma->script_number)
                sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1;
 
+       if (sdma->script_number > sizeof(struct sdma_script_start_addrs)
+                                 / sizeof(s32)) {
+               dev_err(sdma->dev,
+                       "SDMA script number %d not match with firmware.\n",
+                       sdma->script_number);
+               return;
+       }
+
        for (i = 0; i < sdma->script_number; i++)
                if (addr_arr[i] > 0)
                        saddr_arr[i] = addr_arr[i];
index 8e90a405939df4989d69d001efc803515ca1515a..ef73f65224b1b7b3d419b7543478cfbb63da6c07 100644 (file)
@@ -694,6 +694,25 @@ static int bam_dma_terminate_all(struct dma_chan *chan)
 
        /* remove all transactions, including active transaction */
        spin_lock_irqsave(&bchan->vc.lock, flag);
+       /*
+        * If we have transactions queued, then some might be committed to the
+        * hardware in the desc fifo.  The only way to reset the desc fifo is
+        * to do a hardware reset (either by pipe or the entire block).
+        * bam_chan_init_hw() will trigger a pipe reset, and also reinit the
+        * pipe.  If the pipe is left disabled (default state after pipe reset)
+        * and is accessed by a connected hardware engine, a fatal error in
+        * the BAM will occur.  There is a small window where this could happen
+        * with bam_chan_init_hw(), but it is assumed that the caller has
+        * stopped activity on any attached hardware engine.  Make sure to do
+        * this first so that the BAM hardware doesn't cause memory corruption
+        * by accessing freed resources.
+        */
+       if (!list_empty(&bchan->desc_list)) {
+               async_desc = list_first_entry(&bchan->desc_list,
+                                             struct bam_async_desc, desc_node);
+               bam_chan_init_hw(bchan, async_desc->dir);
+       }
+
        list_for_each_entry_safe(async_desc, tmp,
                                 &bchan->desc_list, desc_node) {
                list_add(&async_desc->vd.node, &bchan->vc.desc_issued);
index 525dc7338fe3b86842f4d2aa3ffd9857d34ec5f6..8546ad03472083d76156995158e860e106be028b 100644 (file)
 #define SPRD_DMA_SRC_TRSF_STEP_OFFSET  0
 #define SPRD_DMA_TRSF_STEP_MASK                GENMASK(15, 0)
 
+/* SPRD DMA_SRC_BLK_STEP register definition */
+#define SPRD_DMA_LLIST_HIGH_MASK       GENMASK(31, 28)
+#define SPRD_DMA_LLIST_HIGH_SHIFT      28
+
 /* define DMA channel mode & trigger mode mask */
 #define SPRD_DMA_CHN_MODE_MASK         GENMASK(7, 0)
 #define SPRD_DMA_TRG_MODE_MASK         GENMASK(7, 0)
@@ -208,6 +212,7 @@ struct sprd_dma_dev {
        struct sprd_dma_chn     channels[0];
 };
 
+static void sprd_dma_free_desc(struct virt_dma_desc *vd);
 static bool sprd_dma_filter_fn(struct dma_chan *chan, void *param);
 static struct of_dma_filter_info sprd_dma_info = {
        .filter_fn = sprd_dma_filter_fn,
@@ -609,12 +614,19 @@ static int sprd_dma_alloc_chan_resources(struct dma_chan *chan)
 static void sprd_dma_free_chan_resources(struct dma_chan *chan)
 {
        struct sprd_dma_chn *schan = to_sprd_dma_chan(chan);
+       struct virt_dma_desc *cur_vd = NULL;
        unsigned long flags;
 
        spin_lock_irqsave(&schan->vc.lock, flags);
+       if (schan->cur_desc)
+               cur_vd = &schan->cur_desc->vd;
+
        sprd_dma_stop(schan);
        spin_unlock_irqrestore(&schan->vc.lock, flags);
 
+       if (cur_vd)
+               sprd_dma_free_desc(cur_vd);
+
        vchan_free_chan_resources(&schan->vc);
        pm_runtime_put(chan->device->dev);
 }
@@ -717,6 +729,7 @@ static int sprd_dma_fill_desc(struct dma_chan *chan,
        u32 int_mode = flags & SPRD_DMA_INT_MASK;
        int src_datawidth, dst_datawidth, src_step, dst_step;
        u32 temp, fix_mode = 0, fix_en = 0;
+       phys_addr_t llist_ptr;
 
        if (dir == DMA_MEM_TO_DEV) {
                src_step = sprd_dma_get_step(slave_cfg->src_addr_width);
@@ -814,13 +827,16 @@ static int sprd_dma_fill_desc(struct dma_chan *chan,
                 * Set the link-list pointer point to next link-list
                 * configuration's physical address.
                 */
-               hw->llist_ptr = schan->linklist.phy_addr + temp;
+               llist_ptr = schan->linklist.phy_addr + temp;
+               hw->llist_ptr = lower_32_bits(llist_ptr);
+               hw->src_blk_step = (upper_32_bits(llist_ptr) << SPRD_DMA_LLIST_HIGH_SHIFT) &
+                       SPRD_DMA_LLIST_HIGH_MASK;
        } else {
                hw->llist_ptr = 0;
+               hw->src_blk_step = 0;
        }
 
        hw->frg_step = 0;
-       hw->src_blk_step = 0;
        hw->des_blk_step = 0;
        return 0;
 }
@@ -1023,15 +1039,22 @@ static int sprd_dma_resume(struct dma_chan *chan)
 static int sprd_dma_terminate_all(struct dma_chan *chan)
 {
        struct sprd_dma_chn *schan = to_sprd_dma_chan(chan);
+       struct virt_dma_desc *cur_vd = NULL;
        unsigned long flags;
        LIST_HEAD(head);
 
        spin_lock_irqsave(&schan->vc.lock, flags);
+       if (schan->cur_desc)
+               cur_vd = &schan->cur_desc->vd;
+
        sprd_dma_stop(schan);
 
        vchan_get_all_descriptors(&schan->vc, &head);
        spin_unlock_irqrestore(&schan->vc.lock, flags);
 
+       if (cur_vd)
+               sprd_dma_free_desc(cur_vd);
+
        vchan_dma_desc_free_list(&schan->vc, &head);
        return 0;
 }
index 5f8adf5c1f203f4c1905f728c752ed2dbbfe64b5..6e1268552f74070277e28ed1036df1b4349bca7b 100644 (file)
@@ -40,6 +40,7 @@
 #define ADMA_CH_CONFIG_MAX_BURST_SIZE                   16
 #define ADMA_CH_CONFIG_WEIGHT_FOR_WRR(val)             ((val) & 0xf)
 #define ADMA_CH_CONFIG_MAX_BUFS                                8
+#define TEGRA186_ADMA_CH_CONFIG_OUTSTANDING_REQS(reqs) (reqs << 4)
 
 #define ADMA_CH_FIFO_CTRL                              0x2c
 #define TEGRA210_ADMA_CH_FIFO_CTRL_TXSIZE(val)         (((val) & 0xf) << 8)
@@ -77,6 +78,7 @@ struct tegra_adma;
  * @ch_req_tx_shift: Register offset for AHUB transmit channel select.
  * @ch_req_rx_shift: Register offset for AHUB receive channel select.
  * @ch_base_offset: Register offset of DMA channel registers.
+ * @has_outstanding_reqs: If DMA channel can have outstanding requests.
  * @ch_fifo_ctrl: Default value for channel FIFO CTRL register.
  * @ch_req_mask: Mask for Tx or Rx channel select.
  * @ch_req_max: Maximum number of Tx or Rx channels available.
@@ -95,6 +97,7 @@ struct tegra_adma_chip_data {
        unsigned int ch_req_max;
        unsigned int ch_reg_size;
        unsigned int nr_channels;
+       bool has_outstanding_reqs;
 };
 
 /*
@@ -594,6 +597,8 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
                         ADMA_CH_CTRL_FLOWCTRL_EN;
        ch_regs->config |= cdata->adma_get_burst_config(burst_size);
        ch_regs->config |= ADMA_CH_CONFIG_WEIGHT_FOR_WRR(1);
+       if (cdata->has_outstanding_reqs)
+               ch_regs->config |= TEGRA186_ADMA_CH_CONFIG_OUTSTANDING_REQS(8);
        ch_regs->fifo_ctrl = cdata->ch_fifo_ctrl;
        ch_regs->tc = desc->period_len & ADMA_CH_TC_COUNT_MASK;
 
@@ -778,6 +783,7 @@ static const struct tegra_adma_chip_data tegra210_chip_data = {
        .ch_req_tx_shift        = 28,
        .ch_req_rx_shift        = 24,
        .ch_base_offset         = 0,
+       .has_outstanding_reqs   = false,
        .ch_fifo_ctrl           = TEGRA210_FIFO_CTRL_DEFAULT,
        .ch_req_mask            = 0xf,
        .ch_req_max             = 10,
@@ -792,6 +798,7 @@ static const struct tegra_adma_chip_data tegra186_chip_data = {
        .ch_req_tx_shift        = 27,
        .ch_req_rx_shift        = 22,
        .ch_base_offset         = 0x10000,
+       .has_outstanding_reqs   = true,
        .ch_fifo_ctrl           = TEGRA186_FIFO_CTRL_DEFAULT,
        .ch_req_mask            = 0x1f,
        .ch_req_max             = 20,
index 2f946f55076c549847fbd0fb1044af3e6f8ed277..8c2f7ebe998c0ba1ec290fa6b6ac4083424daf88 100644 (file)
@@ -586,9 +586,22 @@ static struct dma_async_tx_descriptor *cppi41_dma_prep_slave_sg(
        enum dma_transfer_direction dir, unsigned long tx_flags, void *context)
 {
        struct cppi41_channel *c = to_cpp41_chan(chan);
+       struct dma_async_tx_descriptor *txd = NULL;
+       struct cppi41_dd *cdd = c->cdd;
        struct cppi41_desc *d;
        struct scatterlist *sg;
        unsigned int i;
+       int error;
+
+       error = pm_runtime_get(cdd->ddev.dev);
+       if (error < 0) {
+               pm_runtime_put_noidle(cdd->ddev.dev);
+
+               return NULL;
+       }
+
+       if (cdd->is_suspended)
+               goto err_out_not_ready;
 
        d = c->desc;
        for_each_sg(sgl, sg, sg_len, i) {
@@ -611,7 +624,13 @@ static struct dma_async_tx_descriptor *cppi41_dma_prep_slave_sg(
                d++;
        }
 
-       return &c->txd;
+       txd = &c->txd;
+
+err_out_not_ready:
+       pm_runtime_mark_last_busy(cdd->ddev.dev);
+       pm_runtime_put_autosuspend(cdd->ddev.dev);
+
+       return txd;
 }
 
 static void cppi41_compute_td_desc(struct cppi41_desc *d)
index e7dc3c4dc8e077d855410055539a2b88a16d9bfb..5d56f1e4d332ce5386b97efb0ec8063b1c659316 100644 (file)
@@ -68,6 +68,9 @@
 #define XILINX_DMA_DMACR_CIRC_EN               BIT(1)
 #define XILINX_DMA_DMACR_RUNSTOP               BIT(0)
 #define XILINX_DMA_DMACR_FSYNCSRC_MASK         GENMASK(6, 5)
+#define XILINX_DMA_DMACR_DELAY_MASK            GENMASK(31, 24)
+#define XILINX_DMA_DMACR_FRAME_COUNT_MASK      GENMASK(23, 16)
+#define XILINX_DMA_DMACR_MASTER_MASK           GENMASK(11, 8)
 
 #define XILINX_DMA_REG_DMASR                   0x0004
 #define XILINX_DMA_DMASR_EOL_LATE_ERR          BIT(15)
@@ -1354,7 +1357,8 @@ static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan)
                                           node);
                hw = &segment->hw;
 
-               xilinx_write(chan, XILINX_DMA_REG_SRCDSTADDR, hw->buf_addr);
+               xilinx_write(chan, XILINX_DMA_REG_SRCDSTADDR,
+                            xilinx_prep_dma_addr_t(hw->buf_addr));
 
                /* Start the transfer */
                dma_ctrl_write(chan, XILINX_DMA_REG_BTT,
@@ -2117,8 +2121,10 @@ int xilinx_vdma_channel_set_config(struct dma_chan *dchan,
        chan->config.gen_lock = cfg->gen_lock;
        chan->config.master = cfg->master;
 
+       dmacr &= ~XILINX_DMA_DMACR_GENLOCK_EN;
        if (cfg->gen_lock && chan->genlock) {
                dmacr |= XILINX_DMA_DMACR_GENLOCK_EN;
+               dmacr &= ~XILINX_DMA_DMACR_MASTER_MASK;
                dmacr |= cfg->master << XILINX_DMA_DMACR_MASTER_SHIFT;
        }
 
@@ -2134,11 +2140,13 @@ int xilinx_vdma_channel_set_config(struct dma_chan *dchan,
        chan->config.delay = cfg->delay;
 
        if (cfg->coalesc <= XILINX_DMA_DMACR_FRAME_COUNT_MAX) {
+               dmacr &= ~XILINX_DMA_DMACR_FRAME_COUNT_MASK;
                dmacr |= cfg->coalesc << XILINX_DMA_DMACR_FRAME_COUNT_SHIFT;
                chan->config.coalesc = cfg->coalesc;
        }
 
        if (cfg->delay <= XILINX_DMA_DMACR_DELAY_MAX) {
+               dmacr &= ~XILINX_DMA_DMACR_DELAY_MASK;
                dmacr |= cfg->delay << XILINX_DMA_DMACR_DELAY_SHIFT;
                chan->config.delay = cfg->delay;
        }
index d413a0bdc9ad9da8637b811e79a81023c39c1906..0bb62857ffb2414cb0b2da26c3591b5c7fb10cbe 100644 (file)
@@ -553,7 +553,11 @@ void ghes_edac_unregister(struct ghes *ghes)
        if (!ghes_pvt)
                return;
 
+       if (atomic_dec_return(&ghes_init))
+               return;
+
        mci = ghes_pvt->mci;
+       ghes_pvt = NULL;
        edac_mc_del_mc(mci->pdev);
        edac_mc_free(mci);
 }
index 178ee8106828775f90a317bbb86a3b75d8dfb9ac..b248870a980611034e616ce403f19e5cca995c86 100644 (file)
@@ -182,6 +182,7 @@ config RESET_ATTACK_MITIGATION
 
 config EFI_RCI2_TABLE
        bool "EFI Runtime Configuration Interface Table Version 2 Support"
+       depends on X86 || COMPILE_TEST
        help
          Displays the content of the Runtime Configuration Interface
          Table version 2 on Dell EMC PowerEdge systems as a binary
index 69f00f7453a34c386237f4b2344f66a05f3c67fc..e98bbf8e56d9b07e7c609fb614e2105decd99175 100644 (file)
@@ -554,7 +554,7 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
                                              sizeof(*seed) + size);
                        if (seed != NULL) {
                                pr_notice("seeding entropy pool\n");
-                               add_device_randomness(seed->bits, seed->size);
+                               add_bootloader_randomness(seed->bits, seed->size);
                                early_memunmap(seed, sizeof(*seed) + size);
                        } else {
                                pr_err("Could not map UEFI random seed!\n");
index 0460c7581220e13cc8418488042d9a7bb17c0b3e..ee0661ddb25bb6a9e74f52e5c2cced5e85f632c7 100644 (file)
@@ -52,6 +52,7 @@ lib-$(CONFIG_EFI_ARMSTUB)     += arm-stub.o fdt.o string.o random.o \
 
 lib-$(CONFIG_ARM)              += arm32-stub.o
 lib-$(CONFIG_ARM64)            += arm64-stub.o
+CFLAGS_arm32-stub.o            := -DTEXT_OFFSET=$(TEXT_OFFSET)
 CFLAGS_arm64-stub.o            := -DTEXT_OFFSET=$(TEXT_OFFSET)
 
 #
index e8f7aefb6813d9c25b85ae367c01aa935a0fe8d1..41213bf5fcf5e8a84619923757fd033cce66761b 100644 (file)
@@ -195,6 +195,7 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
                                 unsigned long dram_base,
                                 efi_loaded_image_t *image)
 {
+       unsigned long kernel_base;
        efi_status_t status;
 
        /*
@@ -204,9 +205,18 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
         * loaded. These assumptions are made by the decompressor,
         * before any memory map is available.
         */
-       dram_base = round_up(dram_base, SZ_128M);
+       kernel_base = round_up(dram_base, SZ_128M);
 
-       status = reserve_kernel_base(sys_table, dram_base, reserve_addr,
+       /*
+        * Note that some platforms (notably, the Raspberry Pi 2) put
+        * spin-tables and other pieces of firmware at the base of RAM,
+        * abusing the fact that the window of TEXT_OFFSET bytes at the
+        * base of the kernel image is only partially used at the moment.
+        * (Up to 5 pages are used for the swapper page tables)
+        */
+       kernel_base += TEXT_OFFSET - 5 * PAGE_SIZE;
+
+       status = reserve_kernel_base(sys_table, kernel_base, reserve_addr,
                                     reserve_size);
        if (status != EFI_SUCCESS) {
                pr_efi_err(sys_table, "Unable to allocate memory for uncompressed kernel.\n");
@@ -220,7 +230,7 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
        *image_size = image->image_size;
        status = efi_relocate_kernel(sys_table, image_addr, *image_size,
                                     *image_size,
-                                    dram_base + MAX_UNCOMP_KERNEL_SIZE, 0);
+                                    kernel_base + MAX_UNCOMP_KERNEL_SIZE, 0, 0);
        if (status != EFI_SUCCESS) {
                pr_efi_err(sys_table, "Failed to relocate kernel.\n");
                efi_free(sys_table, *reserve_size, *reserve_addr);
index 3caae7f2cf56772936b6f77484ef1f7e1a2b42c2..35dbc2791c973f6281470bce96016f1ce37e95a9 100644 (file)
@@ -260,11 +260,11 @@ fail:
 }
 
 /*
- * Allocate at the lowest possible address.
+ * Allocate at the lowest possible address that is not below 'min'.
  */
-efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg,
-                          unsigned long size, unsigned long align,
-                          unsigned long *addr)
+efi_status_t efi_low_alloc_above(efi_system_table_t *sys_table_arg,
+                                unsigned long size, unsigned long align,
+                                unsigned long *addr, unsigned long min)
 {
        unsigned long map_size, desc_size, buff_size;
        efi_memory_desc_t *map;
@@ -311,13 +311,8 @@ efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg,
                start = desc->phys_addr;
                end = start + desc->num_pages * EFI_PAGE_SIZE;
 
-               /*
-                * Don't allocate at 0x0. It will confuse code that
-                * checks pointers against NULL. Skip the first 8
-                * bytes so we start at a nice even number.
-                */
-               if (start == 0x0)
-                       start += 8;
+               if (start < min)
+                       start = min;
 
                start = round_up(start, align);
                if ((start + size) > end)
@@ -698,7 +693,8 @@ efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg,
                                 unsigned long image_size,
                                 unsigned long alloc_size,
                                 unsigned long preferred_addr,
-                                unsigned long alignment)
+                                unsigned long alignment,
+                                unsigned long min_addr)
 {
        unsigned long cur_image_addr;
        unsigned long new_addr = 0;
@@ -731,8 +727,8 @@ efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg,
         * possible.
         */
        if (status != EFI_SUCCESS) {
-               status = efi_low_alloc(sys_table_arg, alloc_size, alignment,
-                                      &new_addr);
+               status = efi_low_alloc_above(sys_table_arg, alloc_size,
+                                            alignment, &new_addr, min_addr);
        }
        if (status != EFI_SUCCESS) {
                pr_efi_err(sys_table_arg, "Failed to allocate usable memory for kernel.\n");
index 877745c3aaf2833fed62659aa38c52c0f3b2eb1c..7baf48c01e72f2f63e65e802609059da9cdb12ee 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 #include <linux/efi.h>
+#include <linux/security.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
 
@@ -717,6 +718,13 @@ static long efi_test_ioctl(struct file *file, unsigned int cmd,
 
 static int efi_test_open(struct inode *inode, struct file *file)
 {
+       int ret = security_locked_down(LOCKDOWN_EFI_TEST);
+
+       if (ret)
+               return ret;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EACCES;
        /*
         * nothing special to do here
         * We do accept multiple open files at the same time as we
index ebd7977653a8e28b4a7086573c0e3c80d2e271e3..31f9f0e369b977345dee40523d2f615aec402e84 100644 (file)
@@ -88,6 +88,7 @@ int __init efi_tpm_eventlog_init(void)
 
        if (tbl_size < 0) {
                pr_err(FW_BUG "Failed to parse event in TPM Final Events Log\n");
+               ret = -EINVAL;
                goto out_calc;
        }
 
index 2f1e9da81c1e422644e1611fd5c43b6a14cc0b85..3302125e5265110722d131c7979a8a5d4da0e081 100644 (file)
@@ -362,9 +362,8 @@ static void mrfld_irq_handler(struct irq_desc *desc)
        chained_irq_exit(irqchip, desc);
 }
 
-static int mrfld_irq_init_hw(struct gpio_chip *chip)
+static void mrfld_irq_init_hw(struct mrfld_gpio *priv)
 {
-       struct mrfld_gpio *priv = gpiochip_get_data(chip);
        void __iomem *reg;
        unsigned int base;
 
@@ -376,8 +375,6 @@ static int mrfld_irq_init_hw(struct gpio_chip *chip)
                reg = gpio_reg(&priv->chip, base, GFER);
                writel(0, reg);
        }
-
-       return 0;
 }
 
 static const char *mrfld_gpio_get_pinctrl_dev_name(struct mrfld_gpio *priv)
@@ -400,7 +397,6 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
 {
        const struct mrfld_gpio_pinrange *range;
        const char *pinctrl_dev_name;
-       struct gpio_irq_chip *girq;
        struct mrfld_gpio *priv;
        u32 gpio_base, irq_base;
        void __iomem *base;
@@ -448,21 +444,6 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
 
        raw_spin_lock_init(&priv->lock);
 
-       girq = &priv->chip.irq;
-       girq->chip = &mrfld_irqchip;
-       girq->init_hw = mrfld_irq_init_hw;
-       girq->parent_handler = mrfld_irq_handler;
-       girq->num_parents = 1;
-       girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents,
-                                    sizeof(*girq->parents),
-                                    GFP_KERNEL);
-       if (!girq->parents)
-               return -ENOMEM;
-       girq->parents[0] = pdev->irq;
-       girq->first = irq_base;
-       girq->default_type = IRQ_TYPE_NONE;
-       girq->handler = handle_bad_irq;
-
        pci_set_drvdata(pdev, priv);
        retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv);
        if (retval) {
@@ -484,6 +465,18 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
                }
        }
 
+       retval = gpiochip_irqchip_add(&priv->chip, &mrfld_irqchip, irq_base,
+                                     handle_bad_irq, IRQ_TYPE_NONE);
+       if (retval) {
+               dev_err(&pdev->dev, "could not connect irqchip to gpiochip\n");
+               return retval;
+       }
+
+       mrfld_irq_init_hw(priv);
+
+       gpiochip_set_chained_irqchip(&priv->chip, &mrfld_irqchip, pdev->irq,
+                                    mrfld_irq_handler);
+
        return 0;
 }
 
index 0bb08e0e1611445008c0fcad9542e97d46f7655a..bcc5d40a8d5f629d2345d32ef56c547993782f81 100644 (file)
@@ -977,6 +977,9 @@ struct amdgpu_device {
 
        uint64_t                        unique_id;
        uint64_t        df_perfmon_config_assign_mask[AMDGPU_MAX_DF_PERFMONS];
+
+       /* device pstate */
+       int                             pstate;
 };
 
 static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev)
index 649e68c4479bb62fc6531fef27f279866457869a..d1495e1c92894168bc84e3f89decd27f31516cf2 100644 (file)
@@ -33,7 +33,7 @@ static int amdgpu_benchmark_do_move(struct amdgpu_device *adev, unsigned size,
 {
        unsigned long start_jiffies;
        unsigned long end_jiffies;
-       struct dma_fence *fence = NULL;
+       struct dma_fence *fence;
        int i, r;
 
        start_jiffies = jiffies;
@@ -44,16 +44,14 @@ static int amdgpu_benchmark_do_move(struct amdgpu_device *adev, unsigned size,
                if (r)
                        goto exit_do_move;
                r = dma_fence_wait(fence, false);
+               dma_fence_put(fence);
                if (r)
                        goto exit_do_move;
-               dma_fence_put(fence);
        }
        end_jiffies = jiffies;
        r = jiffies_to_msecs(end_jiffies - start_jiffies);
 
 exit_do_move:
-       if (fence)
-               dma_fence_put(fence);
        return r;
 }
 
index 6614d8a6f4c8d367dcb8bb281f70514f6a054f22..2cdaf3b2a72170c5a638530dce89007e850735a8 100644 (file)
@@ -604,8 +604,11 @@ void amdgpu_ctx_mgr_entity_fini(struct amdgpu_ctx_mgr *mgr)
                        continue;
                }
 
-               for (i = 0; i < num_entities; i++)
+               for (i = 0; i < num_entities; i++) {
+                       mutex_lock(&ctx->adev->lock_reset);
                        drm_sched_entity_fini(&ctx->entities[0][i].entity);
+                       mutex_unlock(&ctx->adev->lock_reset);
+               }
        }
 }
 
index 693f17e787914b493f028b43621457e4ec7189f4..8e6726e0d035fa261c2bc8e8cf9de6fe61f8c061 100644 (file)
@@ -859,6 +859,9 @@ static int amdgpu_debugfs_test_ib(struct seq_file *m, void *data)
        struct amdgpu_device *adev = dev->dev_private;
        int r = 0, i;
 
+       /* Avoid accidently unparking the sched thread during GPU reset */
+       mutex_lock(&adev->lock_reset);
+
        /* hold on the scheduler */
        for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
                struct amdgpu_ring *ring = adev->rings[i];
@@ -884,6 +887,8 @@ static int amdgpu_debugfs_test_ib(struct seq_file *m, void *data)
                kthread_unpark(ring->sched.thread);
        }
 
+       mutex_unlock(&adev->lock_reset);
+
        return 0;
 }
 
@@ -1036,6 +1041,9 @@ static int amdgpu_debugfs_ib_preempt(void *data, u64 val)
        if (!fences)
                return -ENOMEM;
 
+       /* Avoid accidently unparking the sched thread during GPU reset */
+       mutex_lock(&adev->lock_reset);
+
        /* stop the scheduler */
        kthread_park(ring->sched.thread);
 
@@ -1075,6 +1083,8 @@ failure:
        /* restart the scheduler */
        kthread_unpark(ring->sched.thread);
 
+       mutex_unlock(&adev->lock_reset);
+
        ttm_bo_unlock_delayed_workqueue(&adev->mman.bdev, resched);
 
        kfree(fences);
index d36d2b09353944fe8fb22ebd9eff352cd1805d93..58f6b3b92831b4065b6a3c6568556e9cea50aa30 100644 (file)
@@ -2057,6 +2057,7 @@ out:
  */
 static int amdgpu_device_ip_late_init(struct amdgpu_device *adev)
 {
+       struct amdgpu_gpu_instance *gpu_instance;
        int i = 0, r;
 
        for (i = 0; i < adev->num_ip_blocks; i++) {
@@ -2082,8 +2083,39 @@ static int amdgpu_device_ip_late_init(struct amdgpu_device *adev)
        if (r)
                DRM_ERROR("enable mgpu fan boost failed (%d).\n", r);
 
-       /* set to low pstate by default */
-       amdgpu_xgmi_set_pstate(adev, 0);
+
+       if (adev->gmc.xgmi.num_physical_nodes > 1) {
+               mutex_lock(&mgpu_info.mutex);
+
+               /*
+                * Reset device p-state to low as this was booted with high.
+                *
+                * This should be performed only after all devices from the same
+                * hive get initialized.
+                *
+                * However, it's unknown how many device in the hive in advance.
+                * As this is counted one by one during devices initializations.
+                *
+                * So, we wait for all XGMI interlinked devices initialized.
+                * This may bring some delays as those devices may come from
+                * different hives. But that should be OK.
+                */
+               if (mgpu_info.num_dgpu == adev->gmc.xgmi.num_physical_nodes) {
+                       for (i = 0; i < mgpu_info.num_gpu; i++) {
+                               gpu_instance = &(mgpu_info.gpu_ins[i]);
+                               if (gpu_instance->adev->flags & AMD_IS_APU)
+                                       continue;
+
+                               r = amdgpu_xgmi_set_pstate(gpu_instance->adev, 0);
+                               if (r) {
+                                       DRM_ERROR("pstate setting failed (%d).\n", r);
+                                       break;
+                               }
+                       }
+               }
+
+               mutex_unlock(&mgpu_info.mutex);
+       }
 
        return 0;
 }
@@ -3020,6 +3052,13 @@ fence_driver_init:
                        DRM_INFO("amdgpu: acceleration disabled, skipping benchmarks\n");
        }
 
+       /*
+        * Register gpu instance before amdgpu_device_enable_mgpu_fan_boost.
+        * Otherwise the mgpu fan boost feature will be skipped due to the
+        * gpu instance is counted less.
+        */
+       amdgpu_register_gpu_instance(adev);
+
        /* enable clockgating, etc. after ib tests, etc. since some blocks require
         * explicit gating rather than handling it automatically.
         */
index 1d6ce018c8f205c5f16b7ef1133fcae46d67c1b9..557be89421a881cfb98d39e40b06f5469a781adf 100644 (file)
@@ -1001,6 +1001,7 @@ static const struct pci_device_id pciidlist[] = {
        {0x1002, 0x7340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI14|AMD_EXP_HW_SUPPORT},
        {0x1002, 0x7341, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI14|AMD_EXP_HW_SUPPORT},
        {0x1002, 0x7347, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI14|AMD_EXP_HW_SUPPORT},
+       {0x1002, 0x734F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI14|AMD_EXP_HW_SUPPORT},
 
        /* Renoir */
        {0x1002, 0x1636, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RENOIR|AMD_IS_APU|AMD_EXP_HW_SUPPORT},
index 459aa90595428bdc0b478b74f1b906dc11b64eb6..a74ecd449775af685da0ce2fc99d9ad91f775b40 100644 (file)
@@ -267,6 +267,7 @@ struct amdgpu_gfx {
        uint32_t                        mec2_feature_version;
        bool                            mec_fw_write_wait;
        bool                            me_fw_write_wait;
+       bool                            cp_fw_write_wait;
        struct amdgpu_ring              gfx_ring[AMDGPU_MAX_GFX_RINGS];
        unsigned                        num_gfx_rings;
        struct amdgpu_ring              compute_ring[AMDGPU_MAX_COMPUTE_RINGS];
index 555d8e57fae98add5345271cc2bb81529e363e17..406736a1bd3d41e92d054185e58a725571ec0c2f 100644 (file)
@@ -127,18 +127,48 @@ struct amdgpu_xgmi {
 };
 
 struct amdgpu_gmc {
+       /* FB's physical address in MMIO space (for CPU to
+        * map FB). This is different compared to the agp/
+        * gart/vram_start/end field as the later is from
+        * GPU's view and aper_base is from CPU's view.
+        */
        resource_size_t         aper_size;
        resource_size_t         aper_base;
        /* for some chips with <= 32MB we need to lie
         * about vram size near mc fb location */
        u64                     mc_vram_size;
        u64                     visible_vram_size;
+       /* AGP aperture start and end in MC address space
+        * Driver find a hole in the MC address space
+        * to place AGP by setting MC_VM_AGP_BOT/TOP registers
+        * Under VMID0, logical address == MC address. AGP
+        * aperture maps to physical bus or IOVA addressed.
+        * AGP aperture is used to simulate FB in ZFB case.
+        * AGP aperture is also used for page table in system
+        * memory (mainly for APU).
+        *
+        */
        u64                     agp_size;
        u64                     agp_start;
        u64                     agp_end;
+       /* GART aperture start and end in MC address space
+        * Driver find a hole in the MC address space
+        * to place GART by setting VM_CONTEXT0_PAGE_TABLE_START/END_ADDR
+        * registers
+        * Under VMID0, logical address inside GART aperture will
+        * be translated through gpuvm gart page table to access
+        * paged system memory
+        */
        u64                     gart_size;
        u64                     gart_start;
        u64                     gart_end;
+       /* Frame buffer aperture of this GPU device. Different from
+        * fb_start (see below), this only covers the local GPU device.
+        * Driver get fb_start from MC_VM_FB_LOCATION_BASE (set by vbios)
+        * and calculate vram_start of this local device by adding an
+        * offset inside the XGMI hive.
+        * Under VMID0, logical address == MC address
+        */
        u64                     vram_start;
        u64                     vram_end;
        /* FB region , it's same as local vram region in single GPU, in XGMI
index 6f3b03f6224f1a7640d9d3df0649dfc977af4b5e..30d540d23b778a0ac01a2224988730cd7b38f042 100644 (file)
@@ -311,7 +311,7 @@ void amdgpu_irq_fini(struct amdgpu_device *adev)
                drm_irq_uninstall(adev->ddev);
                adev->irq.installed = false;
                if (adev->irq.msi_enabled)
-                       pci_disable_msi(adev->pdev);
+                       pci_free_irq_vectors(adev->pdev);
                if (!amdgpu_device_has_dc_support(adev))
                        flush_work(&adev->hotplug_work);
        }
index 137a8573d5569ca58ab9445438d37ece65c5111f..82c46c4faaad5761b3f03ea3fbf41771800b16be 100644 (file)
@@ -190,7 +190,6 @@ int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags)
                pm_runtime_put_autosuspend(dev->dev);
        }
 
-       amdgpu_register_gpu_instance(adev);
 out:
        if (r) {
                /* balance pm_runtime_get_sync in amdgpu_driver_unload_kms */
index dab90c28047643e1cff7c56861563a39cc67d1bb..404483437bd3aa1a4b8d353196d4f27a6256b096 100644 (file)
@@ -220,7 +220,7 @@ static struct ras_manager *amdgpu_ras_find_obj(struct amdgpu_device *adev,
  * As their names indicate, inject operation will write the
  * value to the address.
  *
- * Second member: struct ras_debug_if::op.
+ * The second member: struct ras_debug_if::op.
  * It has three kinds of operations.
  *
  * - 0: disable RAS on the block. Take ::head as its data.
@@ -228,14 +228,20 @@ static struct ras_manager *amdgpu_ras_find_obj(struct amdgpu_device *adev,
  * - 2: inject errors on the block. Take ::inject as its data.
  *
  * How to use the interface?
- * programs:
- * copy the struct ras_debug_if in your codes and initialize it.
- * write the struct to the control node.
+ *
+ * Programs
+ *
+ * Copy the struct ras_debug_if in your codes and initialize it.
+ * Write the struct to the control node.
+ *
+ * Shells
  *
  * .. code-block:: bash
  *
  *     echo op block [error [sub_block address value]] > .../ras/ras_ctrl
  *
+ * Parameters:
+ *
  * op: disable, enable, inject
  *     disable: only block is needed
  *     enable: block and error are needed
@@ -265,8 +271,10 @@ static struct ras_manager *amdgpu_ras_find_obj(struct amdgpu_device *adev,
  * /sys/class/drm/card[0/1/2...]/device/ras/[gfx/sdma/...]_err_count
  *
  * .. note::
- *     Operation is only allowed on blocks which are supported.
+ *     Operations are only allowed on blocks which are supported.
  *     Please check ras mask at /sys/module/amdgpu/parameters/ras_mask
+ *     to see which blocks support RAS on a particular asic.
+ *
  */
 static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, const char __user *buf,
                size_t size, loff_t *pos)
@@ -322,7 +330,7 @@ static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, const char __user *
  * DOC: AMDGPU RAS debugfs EEPROM table reset interface
  *
  * Some boards contain an EEPROM which is used to persistently store a list of
- * bad pages containing ECC errors detected in vram.  This interface provides
+ * bad pages which experiences ECC errors in vram.  This interface provides
  * a way to reset the EEPROM, e.g., after testing error injection.
  *
  * Usage:
@@ -362,7 +370,7 @@ static const struct file_operations amdgpu_ras_debugfs_eeprom_ops = {
 /**
  * DOC: AMDGPU RAS sysfs Error Count Interface
  *
- * It allows user to read the error count for each IP block on the gpu through
+ * It allows the user to read the error count for each IP block on the gpu through
  * /sys/class/drm/card[0/1/2...]/device/ras/[gfx/sdma/...]_err_count
  *
  * It outputs the multiple lines which report the uncorrected (ue) and corrected
@@ -1027,6 +1035,24 @@ static int amdgpu_ras_sysfs_remove_all(struct amdgpu_device *adev)
 }
 /* sysfs end */
 
+/**
+ * DOC: AMDGPU RAS Reboot Behavior for Unrecoverable Errors
+ *
+ * Normally when there is an uncorrectable error, the driver will reset
+ * the GPU to recover.  However, in the event of an unrecoverable error,
+ * the driver provides an interface to reboot the system automatically
+ * in that event.
+ *
+ * The following file in debugfs provides that interface:
+ * /sys/kernel/debug/dri/[0/1/2...]/ras/auto_reboot
+ *
+ * Usage:
+ *
+ * .. code-block:: bash
+ *
+ *     echo true > .../ras/auto_reboot
+ *
+ */
 /* debugfs begin */
 static void amdgpu_ras_debugfs_create_ctrl_node(struct amdgpu_device *adev)
 {
index b66d29d5ffa2c3bfad8d72ca66d4b9739b010bd7..b158230af8db705cfee5d012fb60738bc0cb69e5 100644 (file)
@@ -138,6 +138,7 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev)
                }
 
                dma_fence_put(fence);
+               fence = NULL;
 
                r = amdgpu_bo_kmap(vram_obj, &vram_map);
                if (r) {
@@ -183,6 +184,7 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev)
                }
 
                dma_fence_put(fence);
+               fence = NULL;
 
                r = amdgpu_bo_kmap(gtt_obj[i], &gtt_map);
                if (r) {
index d5d9161692264aabf02359397623d0d79520e7ba..61d9b7774d42ef87ab26ee2a8d6916d19cea355e 100644 (file)
@@ -1906,9 +1906,6 @@ void amdgpu_ttm_late_init(struct amdgpu_device *adev)
        void *stolen_vga_buf;
        /* return the VGA stolen memory (if any) back to VRAM */
        amdgpu_bo_free_kernel(&adev->stolen_vga_memory, NULL, &stolen_vga_buf);
-
-       /* return the IP Discovery TMR memory back to VRAM */
-       amdgpu_bo_free_kernel(&adev->discovery_memory, NULL, NULL);
 }
 
 /**
@@ -1921,7 +1918,10 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev)
 
        amdgpu_ttm_debugfs_fini(adev);
        amdgpu_ttm_training_reserve_vram_fini(adev);
+       /* return the IP Discovery TMR memory back to VRAM */
+       amdgpu_bo_free_kernel(&adev->discovery_memory, NULL, NULL);
        amdgpu_ttm_fw_reserve_vram_fini(adev);
+
        if (adev->mman.aper_base_kaddr)
                iounmap(adev->mman.aper_base_kaddr);
        adev->mman.aper_base_kaddr = NULL;
index e775f271f1edfbb60fff3f52cae9be81bdb9b6bd..598c24505c73b0161abf83928d8d4bc77c17ef55 100644 (file)
@@ -1418,6 +1418,9 @@ static int amdgpu_vm_update_ptes(struct amdgpu_vm_update_params *params,
                uint64_t incr, entry_end, pe_start;
                struct amdgpu_bo *pt;
 
+               /* make sure that the page tables covering the address range are
+                * actually allocated
+                */
                r = amdgpu_vm_alloc_pts(params->adev, params->vm, &cursor,
                                        params->direct);
                if (r)
@@ -1491,7 +1494,12 @@ static int amdgpu_vm_update_ptes(struct amdgpu_vm_update_params *params,
                } while (frag_start < entry_end);
 
                if (amdgpu_vm_pt_descendant(adev, &cursor)) {
-                       /* Free all child entries */
+                       /* Free all child entries.
+                        * Update the tables with the flags and addresses and free up subsequent
+                        * tables in the case of huge pages or freed up areas.
+                        * This is the maximum you can free, because all other page tables are not
+                        * completely covered by the range and so potentially still in use.
+                        */
                        while (cursor.pfn < frag_start) {
                                amdgpu_vm_free_pts(adev, params->vm, &cursor);
                                amdgpu_vm_pt_next(adev, &cursor);
index 00371713c671a531410512afaa5976ddb488e03c..61d13d8b7b20dfc9e0f4c8a558f577d557f110b5 100644 (file)
@@ -274,22 +274,55 @@ int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate)
 {
        int ret = 0;
        struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev, 0);
+       struct amdgpu_device *tmp_adev;
+       bool update_hive_pstate = true;
+       bool is_high_pstate = pstate && adev->asic_type == CHIP_VEGA20;
 
        if (!hive)
                return 0;
 
-       if (hive->pstate == pstate)
-               return 0;
+       mutex_lock(&hive->hive_lock);
+
+       if (hive->pstate == pstate) {
+               adev->pstate = is_high_pstate ? pstate : adev->pstate;
+               goto out;
+       }
 
        dev_dbg(adev->dev, "Set xgmi pstate %d.\n", pstate);
 
        if (is_support_sw_smu_xgmi(adev))
                ret = smu_set_xgmi_pstate(&adev->smu, pstate);
-       if (ret)
+       else if (adev->powerplay.pp_funcs &&
+                adev->powerplay.pp_funcs->set_xgmi_pstate)
+               ret = adev->powerplay.pp_funcs->set_xgmi_pstate(adev->powerplay.pp_handle,
+                                                               pstate);
+
+       if (ret) {
                dev_err(adev->dev,
                        "XGMI: Set pstate failure on device %llx, hive %llx, ret %d",
                        adev->gmc.xgmi.node_id,
                        adev->gmc.xgmi.hive_id, ret);
+               goto out;
+       }
+
+       /* Update device pstate */
+       adev->pstate = pstate;
+
+       /*
+        * Update the hive pstate only all devices of the hive
+        * are in the same pstate
+        */
+       list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) {
+               if (tmp_adev->pstate != adev->pstate) {
+                       update_hive_pstate = false;
+                       break;
+               }
+       }
+       if (update_hive_pstate || is_high_pstate)
+               hive->pstate = pstate;
+
+out:
+       mutex_unlock(&hive->hive_lock);
 
        return ret;
 }
@@ -364,6 +397,9 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev)
                goto exit;
        }
 
+       /* Set default device pstate */
+       adev->pstate = -1;
+
        top_info = &adev->psp.xgmi_context.top_info;
 
        list_add_tail(&adev->gmc.xgmi.head, &hive->device_list);
index e7bab4f094b3a831eb13f56c82bd346b6cec9543..a93dd3dc09029e8af651d23c75809b9306a42cea 100644 (file)
@@ -564,6 +564,32 @@ static void gfx_v10_0_free_microcode(struct amdgpu_device *adev)
        kfree(adev->gfx.rlc.register_list_format);
 }
 
+static void gfx_v10_0_check_fw_write_wait(struct amdgpu_device *adev)
+{
+       adev->gfx.cp_fw_write_wait = false;
+
+       switch (adev->asic_type) {
+       case CHIP_NAVI10:
+       case CHIP_NAVI12:
+       case CHIP_NAVI14:
+               if ((adev->gfx.me_fw_version >= 0x00000046) &&
+                   (adev->gfx.me_feature_version >= 27) &&
+                   (adev->gfx.pfp_fw_version >= 0x00000068) &&
+                   (adev->gfx.pfp_feature_version >= 27) &&
+                   (adev->gfx.mec_fw_version >= 0x0000005b) &&
+                   (adev->gfx.mec_feature_version >= 27))
+                       adev->gfx.cp_fw_write_wait = true;
+               break;
+       default:
+               break;
+       }
+
+       if (adev->gfx.cp_fw_write_wait == false)
+               DRM_WARN_ONCE("Warning: check cp_fw_version and update it to realize \
+                             GRBM requires 1-cycle delay in cp firmware\n");
+}
+
+
 static void gfx_v10_0_init_rlc_ext_microcode(struct amdgpu_device *adev)
 {
        const struct rlc_firmware_header_v2_1 *rlc_hdr;
@@ -832,6 +858,7 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev)
                }
        }
 
+       gfx_v10_0_check_fw_write_wait(adev);
 out:
        if (err) {
                dev_err(adev->dev,
@@ -4766,6 +4793,24 @@ static void gfx_v10_0_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg,
        gfx_v10_0_wait_reg_mem(ring, 0, 0, 0, reg, 0, val, mask, 0x20);
 }
 
+static void gfx_v10_0_ring_emit_reg_write_reg_wait(struct amdgpu_ring *ring,
+                                                  uint32_t reg0, uint32_t reg1,
+                                                  uint32_t ref, uint32_t mask)
+{
+       int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX);
+       struct amdgpu_device *adev = ring->adev;
+       bool fw_version_ok = false;
+
+       fw_version_ok = adev->gfx.cp_fw_write_wait;
+
+       if (fw_version_ok)
+               gfx_v10_0_wait_reg_mem(ring, usepfp, 0, 1, reg0, reg1,
+                                      ref, mask, 0x20);
+       else
+               amdgpu_ring_emit_reg_write_reg_wait_helper(ring, reg0, reg1,
+                                                          ref, mask);
+}
+
 static void
 gfx_v10_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev,
                                      uint32_t me, uint32_t pipe,
@@ -5156,6 +5201,7 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_gfx = {
        .emit_tmz = gfx_v10_0_ring_emit_tmz,
        .emit_wreg = gfx_v10_0_ring_emit_wreg,
        .emit_reg_wait = gfx_v10_0_ring_emit_reg_wait,
+       .emit_reg_write_reg_wait = gfx_v10_0_ring_emit_reg_write_reg_wait,
 };
 
 static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_compute = {
@@ -5189,6 +5235,7 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_compute = {
        .pad_ib = amdgpu_ring_generic_pad_ib,
        .emit_wreg = gfx_v10_0_ring_emit_wreg,
        .emit_reg_wait = gfx_v10_0_ring_emit_reg_wait,
+       .emit_reg_write_reg_wait = gfx_v10_0_ring_emit_reg_write_reg_wait,
 };
 
 static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_kiq = {
@@ -5219,6 +5266,7 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_kiq = {
        .emit_rreg = gfx_v10_0_ring_emit_rreg,
        .emit_wreg = gfx_v10_0_ring_emit_wreg,
        .emit_reg_wait = gfx_v10_0_ring_emit_reg_wait,
+       .emit_reg_write_reg_wait = gfx_v10_0_ring_emit_reg_write_reg_wait,
 };
 
 static void gfx_v10_0_set_ring_funcs(struct amdgpu_device *adev)
index 39297baedfb41ed62c7ad1de67796953859ea75d..3ebd5c20dfd3ca901f27a2cbf874f2ea6476707b 100644 (file)
@@ -986,6 +986,13 @@ static void gfx_v9_0_check_fw_write_wait(struct amdgpu_device *adev)
        adev->gfx.me_fw_write_wait = false;
        adev->gfx.mec_fw_write_wait = false;
 
+       if ((adev->gfx.mec_fw_version < 0x000001a5) ||
+           (adev->gfx.mec_feature_version < 46) ||
+           (adev->gfx.pfp_fw_version < 0x000000b7) ||
+           (adev->gfx.pfp_feature_version < 46))
+               DRM_WARN_ONCE("Warning: check cp_fw_version and update it to realize \
+                             GRBM requires 1-cycle delay in cp firmware\n");
+
        switch (adev->asic_type) {
        case CHIP_VEGA10:
                if ((adev->gfx.me_fw_version >= 0x0000009c) &&
@@ -1052,6 +1059,12 @@ static void gfx_v9_0_check_if_need_gfxoff(struct amdgpu_device *adev)
                            !adev->gfx.rlc.is_rlc_v2_1))
                        adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
 
+               if (adev->pm.pp_feature & PP_GFXOFF_MASK)
+                       adev->pg_flags |= AMD_PG_SUPPORT_GFX_PG |
+                               AMD_PG_SUPPORT_CP |
+                               AMD_PG_SUPPORT_RLC_SMU_HS;
+               break;
+       case CHIP_RENOIR:
                if (adev->pm.pp_feature & PP_GFXOFF_MASK)
                        adev->pg_flags |= AMD_PG_SUPPORT_GFX_PG |
                                AMD_PG_SUPPORT_CP |
@@ -2725,7 +2738,10 @@ static void gfx_v9_0_init_pg(struct amdgpu_device *adev)
         * And it's needed by gfxoff feature.
         */
        if (adev->gfx.rlc.is_rlc_v2_1) {
-               gfx_v9_1_init_rlc_save_restore_list(adev);
+               if (adev->asic_type == CHIP_VEGA12 ||
+                   (adev->asic_type == CHIP_RAVEN &&
+                    adev->rev_id >= 8))
+                       gfx_v9_1_init_rlc_save_restore_list(adev);
                gfx_v9_0_enable_save_restore_machine(adev);
        }
 
@@ -3876,9 +3892,22 @@ static uint64_t gfx_v9_0_get_gpu_clock_counter(struct amdgpu_device *adev)
        uint64_t clock;
 
        mutex_lock(&adev->gfx.gpu_clock_mutex);
-       WREG32_SOC15(GC, 0, mmRLC_CAPTURE_GPU_CLOCK_COUNT, 1);
-       clock = (uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_LSB) |
-               ((uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_MSB) << 32ULL);
+       if (adev->asic_type == CHIP_VEGA10 && amdgpu_sriov_runtime(adev)) {
+               uint32_t tmp, lsb, msb, i = 0;
+               do {
+                       if (i != 0)
+                               udelay(1);
+                       tmp = RREG32_SOC15(GC, 0, mmRLC_REFCLOCK_TIMESTAMP_MSB);
+                       lsb = RREG32_SOC15(GC, 0, mmRLC_REFCLOCK_TIMESTAMP_LSB);
+                       msb = RREG32_SOC15(GC, 0, mmRLC_REFCLOCK_TIMESTAMP_MSB);
+                       i++;
+               } while (unlikely(tmp != msb) && (i < adev->usec_timeout));
+               clock = (uint64_t)lsb | ((uint64_t)msb << 32ULL);
+       } else {
+               WREG32_SOC15(GC, 0, mmRLC_CAPTURE_GPU_CLOCK_COUNT, 1);
+               clock = (uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_LSB) |
+                       ((uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_MSB) << 32ULL);
+       }
        mutex_unlock(&adev->gfx.gpu_clock_mutex);
        return clock;
 }
index 6e1b25bd1fe7c2c98c388fa34bb988f67b0f6889..27f68d32bfec10fa8cf12f14092f381134a4a89f 100644 (file)
@@ -344,11 +344,9 @@ static uint64_t gmc_v10_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
        amdgpu_ring_emit_wreg(ring, hub->ctx0_ptb_addr_hi32 + (2 * vmid),
                              upper_32_bits(pd_addr));
 
-       amdgpu_ring_emit_wreg(ring, hub->vm_inv_eng0_req + eng, req);
-
-       /* wait for the invalidate to complete */
-       amdgpu_ring_emit_reg_wait(ring, hub->vm_inv_eng0_ack + eng,
-                                 1 << vmid, 1 << vmid);
+       amdgpu_ring_emit_reg_write_reg_wait(ring, hub->vm_inv_eng0_req + eng,
+                                           hub->vm_inv_eng0_ack + eng,
+                                           req, 1 << vmid);
 
        return pd_addr;
 }
index 657970f9ebfbe8621ad5309f7308a0ab6e426fa5..2c5adfe803a206717ea85c4a7e5c6cc63f0cbeb7 100644 (file)
@@ -219,6 +219,15 @@ static void mmhub_v9_4_init_cache_regs(struct amdgpu_device *adev, int hubid)
                            hubid * MMHUB_INSTANCE_REGISTER_OFFSET, tmp);
 
        tmp = mmVML2PF0_VM_L2_CNTL3_DEFAULT;
+       if (adev->gmc.translate_further) {
+               tmp = REG_SET_FIELD(tmp, VML2PF0_VM_L2_CNTL3, BANK_SELECT, 12);
+               tmp = REG_SET_FIELD(tmp, VML2PF0_VM_L2_CNTL3,
+                                   L2_CACHE_BIGK_FRAGMENT_SIZE, 9);
+       } else {
+               tmp = REG_SET_FIELD(tmp, VML2PF0_VM_L2_CNTL3, BANK_SELECT, 9);
+               tmp = REG_SET_FIELD(tmp, VML2PF0_VM_L2_CNTL3,
+                                   L2_CACHE_BIGK_FRAGMENT_SIZE, 6);
+       }
        WREG32_SOC15_OFFSET(MMHUB, 0, mmVML2PF0_VM_L2_CNTL3,
                            hubid * MMHUB_INSTANCE_REGISTER_OFFSET, tmp);
 
index a55a2e83fb197afaa4825892bf7de5f398c1d6a2..af68f9815f286da03def5232601da721a10c5c92 100644 (file)
@@ -539,6 +539,16 @@ static bool nv_need_reset_on_init(struct amdgpu_device *adev)
        return false;
 }
 
+static uint64_t nv_get_pcie_replay_count(struct amdgpu_device *adev)
+{
+
+       /* TODO
+        * dummy implement for pcie_replay_count sysfs interface
+        * */
+
+       return 0;
+}
+
 static void nv_init_doorbell_index(struct amdgpu_device *adev)
 {
        adev->doorbell_index.kiq = AMDGPU_NAVI10_DOORBELL_KIQ;
@@ -586,6 +596,7 @@ static const struct amdgpu_asic_funcs nv_asic_funcs =
        .need_full_reset = &nv_need_full_reset,
        .get_pcie_usage = &nv_get_pcie_usage,
        .need_reset_on_init = &nv_need_reset_on_init,
+       .get_pcie_replay_count = &nv_get_pcie_replay_count,
 };
 
 static int nv_common_early_init(void *handle)
index b8fdb192f6d6f07b0da3f0a86d0071b190d246a7..f4ad2990f97303a13f1e3663884bde2572792336 100644 (file)
@@ -1173,6 +1173,16 @@ static void sdma_v5_0_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg,
                          SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(10));
 }
 
+static void sdma_v5_0_ring_emit_reg_write_reg_wait(struct amdgpu_ring *ring,
+                                                  uint32_t reg0, uint32_t reg1,
+                                                  uint32_t ref, uint32_t mask)
+{
+       amdgpu_ring_emit_wreg(ring, reg0, ref);
+       /* wait for a cycle to reset vm_inv_eng*_ack */
+       amdgpu_ring_emit_reg_wait(ring, reg0, 0, 0);
+       amdgpu_ring_emit_reg_wait(ring, reg1, mask, mask);
+}
+
 static int sdma_v5_0_early_init(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -1588,7 +1598,7 @@ static const struct amdgpu_ring_funcs sdma_v5_0_ring_funcs = {
                6 + /* sdma_v5_0_ring_emit_pipeline_sync */
                /* sdma_v5_0_ring_emit_vm_flush */
                SOC15_FLUSH_GPU_TLB_NUM_WREG * 3 +
-               SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 6 +
+               SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 6 * 2 +
                10 + 10 + 10, /* sdma_v5_0_ring_emit_fence x3 for user fence, vm fence */
        .emit_ib_size = 7 + 6, /* sdma_v5_0_ring_emit_ib */
        .emit_ib = sdma_v5_0_ring_emit_ib,
@@ -1602,6 +1612,7 @@ static const struct amdgpu_ring_funcs sdma_v5_0_ring_funcs = {
        .pad_ib = sdma_v5_0_ring_pad_ib,
        .emit_wreg = sdma_v5_0_ring_emit_wreg,
        .emit_reg_wait = sdma_v5_0_ring_emit_reg_wait,
+       .emit_reg_write_reg_wait = sdma_v5_0_ring_emit_reg_write_reg_wait,
        .init_cond_exec = sdma_v5_0_ring_init_cond_exec,
        .patch_cond_exec = sdma_v5_0_ring_patch_cond_exec,
        .preempt_ib = sdma_v5_0_ring_preempt_ib,
index 741b564b4aa54793eb1f96c93503fbd8e30f3513..8e1640bc07aff47de2da4b0a44649c112b69bb5b 100644 (file)
@@ -1145,7 +1145,9 @@ static int soc15_common_early_init(void *handle)
                                AMD_CG_SUPPORT_SDMA_LS |
                                AMD_CG_SUPPORT_VCN_MGCG;
 
-                       adev->pg_flags = AMD_PG_SUPPORT_SDMA | AMD_PG_SUPPORT_VCN;
+                       adev->pg_flags = AMD_PG_SUPPORT_SDMA |
+                               AMD_PG_SUPPORT_VCN |
+                               AMD_PG_SUPPORT_VCN_DPG;
                } else if (adev->pdev->device == 0x15d8) {
                        adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG |
                                AMD_CG_SUPPORT_GFX_MGLS |
@@ -1188,7 +1190,9 @@ static int soc15_common_early_init(void *handle)
                                AMD_CG_SUPPORT_SDMA_LS |
                                AMD_CG_SUPPORT_VCN_MGCG;
 
-                       adev->pg_flags = AMD_PG_SUPPORT_SDMA | AMD_PG_SUPPORT_VCN;
+                       adev->pg_flags = AMD_PG_SUPPORT_SDMA |
+                               AMD_PG_SUPPORT_VCN |
+                               AMD_PG_SUPPORT_VCN_DPG;
                }
                break;
        case CHIP_ARCTURUS:
@@ -1233,11 +1237,6 @@ static int soc15_common_early_init(void *handle)
                                 AMD_PG_SUPPORT_VCN |
                                 AMD_PG_SUPPORT_VCN_DPG;
                adev->external_rev_id = adev->rev_id + 0x91;
-
-               if (adev->pm.pp_feature & PP_GFXOFF_MASK)
-                       adev->pg_flags |= AMD_PG_SUPPORT_GFX_PG |
-                               AMD_PG_SUPPORT_CP |
-                               AMD_PG_SUPPORT_RLC_SMU_HS;
                break;
        default:
                /* FIXME: not supported yet */
index 0a6173d727e398e45d429245d31d20ab953ee5a9..caba9ecac723528241bac5df9e83123031ea170f 100644 (file)
@@ -4239,8 +4239,8 @@ enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connec
                result = MODE_OK;
        else
                DRM_DEBUG_KMS("Mode %dx%d (clk %d) failed DC validation with error %d\n",
-                             mode->vdisplay,
                              mode->hdisplay,
+                             mode->vdisplay,
                              mode->clock,
                              dc_result);
 
index 985633c08a26725a5315557dbadd0f13f3c2fa76..26c6d735cdc78523af4d6186ac05c50cf7845512 100644 (file)
 # It calculates Bandwidth and Watermarks values for HW programming
 #
 
-ifneq ($(call cc-option, -mpreferred-stack-boundary=4),)
-       cc_stack_align := -mpreferred-stack-boundary=4
-else ifneq ($(call cc-option, -mstack-alignment=16),)
-       cc_stack_align := -mstack-alignment=16
-endif
+calcs_ccflags := -mhard-float -msse
 
-calcs_ccflags := -mhard-float -msse $(cc_stack_align)
+ifdef CONFIG_CC_IS_GCC
+ifeq ($(call cc-ifversion, -lt, 0701, y), y)
+IS_OLD_GCC = 1
+endif
+endif
 
-ifdef CONFIG_CC_IS_CLANG
+ifdef IS_OLD_GCC
+# Stack alignment mismatch, proceed with caution.
+# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
+# (8B stack alignment).
+calcs_ccflags += -mpreferred-stack-boundary=4
+else
 calcs_ccflags += -msse2
 endif
 
index cc94c1a73daa0cffecc0c5acc821b8a940a1a3e9..12ba6fdf89b73213dceed7ee0f925a2e79fd11ae 100644 (file)
@@ -3027,15 +3027,6 @@ void core_link_enable_stream(
                                        CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
                                        COLOR_DEPTH_UNDEFINED);
 
-               /* This second call is needed to reconfigure the DIG
-                * as a workaround for the incorrect value being applied
-                * from transmitter control.
-                */
-               if (!dc_is_virtual_signal(pipe_ctx->stream->signal))
-                       stream->link->link_enc->funcs->setup(
-                               stream->link->link_enc,
-                               pipe_ctx->stream->signal);
-
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
                if (pipe_ctx->stream->timing.flags.DSC) {
                        if (dc_is_dp_signal(pipe_ctx->stream->signal) ||
index ddb8d5649e79184f901161668c91fa3098416406..63f3bddba7daaa50ab93dbd9a42fc13327208d84 100644 (file)
@@ -10,15 +10,20 @@ ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
 DCN20 += dcn20_dsc.o
 endif
 
-ifneq ($(call cc-option, -mpreferred-stack-boundary=4),)
-       cc_stack_align := -mpreferred-stack-boundary=4
-else ifneq ($(call cc-option, -mstack-alignment=16),)
-       cc_stack_align := -mstack-alignment=16
-endif
+CFLAGS_$(AMDDALPATH)/dc/dcn20/dcn20_resource.o := -mhard-float -msse
 
-CFLAGS_$(AMDDALPATH)/dc/dcn20/dcn20_resource.o := -mhard-float -msse $(cc_stack_align)
+ifdef CONFIG_CC_IS_GCC
+ifeq ($(call cc-ifversion, -lt, 0701, y), y)
+IS_OLD_GCC = 1
+endif
+endif
 
-ifdef CONFIG_CC_IS_CLANG
+ifdef IS_OLD_GCC
+# Stack alignment mismatch, proceed with caution.
+# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
+# (8B stack alignment).
+CFLAGS_$(AMDDALPATH)/dc/dcn20/dcn20_resource.o += -mpreferred-stack-boundary=4
+else
 CFLAGS_$(AMDDALPATH)/dc/dcn20/dcn20_resource.o += -msse2
 endif
 
index 924c2e303588504750b0f689b91b29b94d1b6631..bbd1c98564be50c0928af800ffb08841fda18ab2 100644 (file)
@@ -1152,6 +1152,11 @@ struct stream_encoder *dcn20_stream_encoder_create(
        if (!enc1)
                return NULL;
 
+       if (ASICREV_IS_NAVI14_M(ctx->asic_id.hw_internal_rev)) {
+               if (eng_id >= ENGINE_ID_DIGD)
+                       eng_id++;
+       }
+
        dcn20_stream_encoder_construct(enc1, ctx, ctx->dc_bios, eng_id,
                                        &stream_enc_regs[eng_id],
                                        &se_shift, &se_mask);
index 19fabac13c65311b15c571d56a5e434a54cd11f8..14113ccf498d27c6d9eb48790cc83821fabb989e 100644 (file)
@@ -3,15 +3,20 @@
 
 DCN21 = dcn21_hubp.o dcn21_hubbub.o dcn21_resource.o dcn21_hwseq.o dcn21_link_encoder.o
 
-ifneq ($(call cc-option, -mpreferred-stack-boundary=4),)
-       cc_stack_align := -mpreferred-stack-boundary=4
-else ifneq ($(call cc-option, -mstack-alignment=16),)
-       cc_stack_align := -mstack-alignment=16
-endif
+CFLAGS_$(AMDDALPATH)/dc/dcn21/dcn21_resource.o := -mhard-float -msse
 
-CFLAGS_$(AMDDALPATH)/dc/dcn21/dcn21_resource.o := -mhard-float -msse $(cc_stack_align)
+ifdef CONFIG_CC_IS_GCC
+ifeq ($(call cc-ifversion, -lt, 0701, y), y)
+IS_OLD_GCC = 1
+endif
+endif
 
-ifdef CONFIG_CC_IS_CLANG
+ifdef IS_OLD_GCC
+# Stack alignment mismatch, proceed with caution.
+# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
+# (8B stack alignment).
+CFLAGS_$(AMDDALPATH)/dc/dcn21/dcn21_resource.o += -mpreferred-stack-boundary=4
+else
 CFLAGS_$(AMDDALPATH)/dc/dcn21/dcn21_resource.o += -msse2
 endif
 
index 5b2a65b424036e07935122dfb38d0a529097c5d5..8df251626e22bf10fd3e8924bea490850b04b228 100644 (file)
 # It provides the general basic services required by other DAL
 # subcomponents.
 
-ifneq ($(call cc-option, -mpreferred-stack-boundary=4),)
-       cc_stack_align := -mpreferred-stack-boundary=4
-else ifneq ($(call cc-option, -mstack-alignment=16),)
-       cc_stack_align := -mstack-alignment=16
-endif
+dml_ccflags := -mhard-float -msse
 
-dml_ccflags := -mhard-float -msse $(cc_stack_align)
+ifdef CONFIG_CC_IS_GCC
+ifeq ($(call cc-ifversion, -lt, 0701, y), y)
+IS_OLD_GCC = 1
+endif
+endif
 
-ifdef CONFIG_CC_IS_CLANG
+ifdef IS_OLD_GCC
+# Stack alignment mismatch, proceed with caution.
+# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
+# (8B stack alignment).
+dml_ccflags += -mpreferred-stack-boundary=4
+else
 dml_ccflags += -msse2
 endif
 
index b456cd23c6fa46e48b7a5b40f9d76074e57b4396..970737217e53a18ee4331e3cc3aa570c63a79780 100644 (file)
@@ -1,15 +1,20 @@
 #
 # Makefile for the 'dsc' sub-component of DAL.
 
-ifneq ($(call cc-option, -mpreferred-stack-boundary=4),)
-       cc_stack_align := -mpreferred-stack-boundary=4
-else ifneq ($(call cc-option, -mstack-alignment=16),)
-       cc_stack_align := -mstack-alignment=16
-endif
+dsc_ccflags := -mhard-float -msse
 
-dsc_ccflags := -mhard-float -msse $(cc_stack_align)
+ifdef CONFIG_CC_IS_GCC
+ifeq ($(call cc-ifversion, -lt, 0701, y), y)
+IS_OLD_GCC = 1
+endif
+endif
 
-ifdef CONFIG_CC_IS_CLANG
+ifdef IS_OLD_GCC
+# Stack alignment mismatch, proceed with caution.
+# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
+# (8B stack alignment).
+dsc_ccflags += -mpreferred-stack-boundary=4
+else
 dsc_ccflags += -msse2
 endif
 
index 5902f80d1fce66906536c20a94e4ea4859e70aa4..a7f92d0b3a90b9e840ad931c56fa92b8a6351b1d 100644 (file)
@@ -220,6 +220,9 @@ enum pp_df_cstate {
                ((group) << PP_GROUP_SHIFT | (block) << PP_BLOCK_SHIFT | \
                (support) << PP_STATE_SUPPORT_SHIFT | (state) << PP_STATE_SHIFT)
 
+#define XGMI_MODE_PSTATE_D3 0
+#define XGMI_MODE_PSTATE_D0 1
+
 struct seq_file;
 enum amd_pp_clock_type;
 struct amd_pp_simple_clock_info;
@@ -318,6 +321,7 @@ struct amd_pm_funcs {
        int (*set_ppfeature_status)(void *handle, uint64_t ppfeature_masks);
        int (*asic_reset_mode_2)(void *handle);
        int (*set_df_cstate)(void *handle, enum pp_df_cstate state);
+       int (*set_xgmi_pstate)(void *handle, uint32_t pstate);
 };
 
 #endif
index f4ff15378e61b478987f552124e7cebe24ad4b60..7932eb163a00c88450532e93b288a1d05120e801 100644 (file)
@@ -969,6 +969,14 @@ static int pp_dpm_switch_power_profile(void *handle,
                workload = hwmgr->workload_setting[index];
        }
 
+       if (type == PP_SMC_POWER_PROFILE_COMPUTE &&
+               hwmgr->hwmgr_func->disable_power_features_for_compute_performance) {
+                       if (hwmgr->hwmgr_func->disable_power_features_for_compute_performance(hwmgr, en)) {
+                               mutex_unlock(&hwmgr->smu_lock);
+                               return -EINVAL;
+                       }
+       }
+
        if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
                hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, &workload, 0);
        mutex_unlock(&hwmgr->smu_lock);
@@ -1566,6 +1574,23 @@ static int pp_set_df_cstate(void *handle, enum pp_df_cstate state)
        return 0;
 }
 
+static int pp_set_xgmi_pstate(void *handle, uint32_t pstate)
+{
+       struct pp_hwmgr *hwmgr = handle;
+
+       if (!hwmgr)
+               return -EINVAL;
+
+       if (!hwmgr->pm_en || !hwmgr->hwmgr_func->set_xgmi_pstate)
+               return 0;
+
+       mutex_lock(&hwmgr->smu_lock);
+       hwmgr->hwmgr_func->set_xgmi_pstate(hwmgr, pstate);
+       mutex_unlock(&hwmgr->smu_lock);
+
+       return 0;
+}
+
 static const struct amd_pm_funcs pp_dpm_funcs = {
        .load_firmware = pp_dpm_load_fw,
        .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
@@ -1625,4 +1650,5 @@ static const struct amd_pm_funcs pp_dpm_funcs = {
        .asic_reset_mode_2 = pp_asic_reset_mode_2,
        .smu_i2c_bus_access = pp_smu_i2c_bus_access,
        .set_df_cstate = pp_set_df_cstate,
+       .set_xgmi_pstate = pp_set_xgmi_pstate,
 };
index 4e468b0272c3927e99f9db7c3d9646f57a1af82d..1e2da4d37567496bf7e39edeb43923be7405efe2 100644 (file)
@@ -383,14 +383,25 @@ bool smu_clk_dpm_is_enabled(struct smu_context *smu, enum smu_clk_type clk_type)
        return true;
 }
 
-
+/**
+ * smu_dpm_set_power_gate - power gate/ungate the specific IP block
+ *
+ * @smu:        smu_context pointer
+ * @block_type: the IP block to power gate/ungate
+ * @gate:       to power gate if true, ungate otherwise
+ *
+ * This API uses no smu->mutex lock protection due to:
+ * 1. It is either called by other IP block(gfx/sdma/vcn/uvd/vce).
+ *    This is guarded to be race condition free by the caller.
+ * 2. Or get called on user setting request of power_dpm_force_performance_level.
+ *    Under this case, the smu->mutex lock protection is already enforced on
+ *    the parent API smu_force_performance_level of the call path.
+ */
 int smu_dpm_set_power_gate(struct smu_context *smu, uint32_t block_type,
                           bool gate)
 {
        int ret = 0;
 
-       mutex_lock(&smu->mutex);
-
        switch (block_type) {
        case AMD_IP_BLOCK_TYPE_UVD:
                ret = smu_dpm_set_uvd_enable(smu, gate);
@@ -408,8 +419,6 @@ int smu_dpm_set_power_gate(struct smu_context *smu, uint32_t block_type,
                break;
        }
 
-       mutex_unlock(&smu->mutex);
-
        return ret;
 }
 
@@ -526,7 +535,7 @@ bool is_support_sw_smu(struct amdgpu_device *adev)
 
 bool is_support_sw_smu_xgmi(struct amdgpu_device *adev)
 {
-       if (amdgpu_dpm != 1)
+       if (!is_support_sw_smu(adev))
                return false;
 
        if (adev->asic_type == CHIP_VEGA20)
@@ -705,6 +714,9 @@ static int smu_set_funcs(struct amdgpu_device *adev)
 {
        struct smu_context *smu = &adev->smu;
 
+       if (adev->pm.pp_feature & PP_OVERDRIVE_MASK)
+               smu->od_enabled = true;
+
        switch (adev->asic_type) {
        case CHIP_VEGA20:
                vega20_set_ppt_funcs(smu);
@@ -716,6 +728,8 @@ static int smu_set_funcs(struct amdgpu_device *adev)
                break;
        case CHIP_ARCTURUS:
                arcturus_set_ppt_funcs(smu);
+               /* OD is not supported on Arcturus */
+               smu->od_enabled =false;
                break;
        case CHIP_RENOIR:
                renoir_set_ppt_funcs(smu);
@@ -724,9 +738,6 @@ static int smu_set_funcs(struct amdgpu_device *adev)
                return -EINVAL;
        }
 
-       if (adev->pm.pp_feature & PP_OVERDRIVE_MASK)
-               smu->od_enabled = true;
-
        return 0;
 }
 
index 4ea63a2e17da7d545532e0dc933e37c953303df3..d71a492c87a325f975121fc656c05d3598c7f42e 100644 (file)
@@ -3689,6 +3689,13 @@ static int vega10_set_power_state_tasks(struct pp_hwmgr *hwmgr,
        PP_ASSERT_WITH_CODE(!result,
                        "Failed to upload PPtable!", return result);
 
+       /*
+        * If a custom pp table is loaded, set DPMTABLE_OD_UPDATE_VDDC flag.
+        * That effectively disables AVFS feature.
+        */
+       if(hwmgr->hardcode_pp_table != NULL)
+               data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_VDDC;
+
        vega10_update_avfs(hwmgr);
 
        /*
@@ -5263,6 +5270,59 @@ static int vega10_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_
        return 0;
 }
 
+static int vega10_disable_power_features_for_compute_performance(struct pp_hwmgr *hwmgr, bool disable)
+{
+       struct vega10_hwmgr *data = hwmgr->backend;
+       uint32_t feature_mask = 0;
+
+       if (disable) {
+               feature_mask |= data->smu_features[GNLD_ULV].enabled ?
+                       data->smu_features[GNLD_ULV].smu_feature_bitmap : 0;
+               feature_mask |= data->smu_features[GNLD_DS_GFXCLK].enabled ?
+                       data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap : 0;
+               feature_mask |= data->smu_features[GNLD_DS_SOCCLK].enabled ?
+                       data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap : 0;
+               feature_mask |= data->smu_features[GNLD_DS_LCLK].enabled ?
+                       data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap : 0;
+               feature_mask |= data->smu_features[GNLD_DS_DCEFCLK].enabled ?
+                       data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap : 0;
+       } else {
+               feature_mask |= (!data->smu_features[GNLD_ULV].enabled) ?
+                       data->smu_features[GNLD_ULV].smu_feature_bitmap : 0;
+               feature_mask |= (!data->smu_features[GNLD_DS_GFXCLK].enabled) ?
+                       data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap : 0;
+               feature_mask |= (!data->smu_features[GNLD_DS_SOCCLK].enabled) ?
+                       data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap : 0;
+               feature_mask |= (!data->smu_features[GNLD_DS_LCLK].enabled) ?
+                       data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap : 0;
+               feature_mask |= (!data->smu_features[GNLD_DS_DCEFCLK].enabled) ?
+                       data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap : 0;
+       }
+
+       if (feature_mask)
+               PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
+                               !disable, feature_mask),
+                               "enable/disable power features for compute performance Failed!",
+                               return -EINVAL);
+
+       if (disable) {
+               data->smu_features[GNLD_ULV].enabled = false;
+               data->smu_features[GNLD_DS_GFXCLK].enabled = false;
+               data->smu_features[GNLD_DS_SOCCLK].enabled = false;
+               data->smu_features[GNLD_DS_LCLK].enabled = false;
+               data->smu_features[GNLD_DS_DCEFCLK].enabled = false;
+       } else {
+               data->smu_features[GNLD_ULV].enabled = true;
+               data->smu_features[GNLD_DS_GFXCLK].enabled = true;
+               data->smu_features[GNLD_DS_SOCCLK].enabled = true;
+               data->smu_features[GNLD_DS_LCLK].enabled = true;
+               data->smu_features[GNLD_DS_DCEFCLK].enabled = true;
+       }
+
+       return 0;
+
+}
+
 static const struct pp_hwmgr_func vega10_hwmgr_funcs = {
        .backend_init = vega10_hwmgr_backend_init,
        .backend_fini = vega10_hwmgr_backend_fini,
@@ -5330,6 +5390,8 @@ static const struct pp_hwmgr_func vega10_hwmgr_funcs = {
        .get_ppfeature_status = vega10_get_ppfeature_status,
        .set_ppfeature_status = vega10_set_ppfeature_status,
        .set_mp1_state = vega10_set_mp1_state,
+       .disable_power_features_for_compute_performance =
+                       vega10_disable_power_features_for_compute_performance,
 };
 
 int vega10_hwmgr_init(struct pp_hwmgr *hwmgr)
index 9295bd90b792271e14e38bf3e86312486eeacaf5..5bcf0d684151457d72aa5cf0f6073bd944837ec0 100644 (file)
@@ -4176,6 +4176,20 @@ static int vega20_set_df_cstate(struct pp_hwmgr *hwmgr,
        return ret;
 }
 
+static int vega20_set_xgmi_pstate(struct pp_hwmgr *hwmgr,
+                                 uint32_t pstate)
+{
+       int ret;
+
+       ret = smum_send_msg_to_smc_with_parameter(hwmgr,
+                                                 PPSMC_MSG_SetXgmiMode,
+                                                 pstate ? XGMI_MODE_PSTATE_D0 : XGMI_MODE_PSTATE_D3);
+       if (ret)
+               pr_err("SetXgmiPstate failed!\n");
+
+       return ret;
+}
+
 static const struct pp_hwmgr_func vega20_hwmgr_funcs = {
        /* init/fini related */
        .backend_init = vega20_hwmgr_backend_init,
@@ -4245,6 +4259,7 @@ static const struct pp_hwmgr_func vega20_hwmgr_funcs = {
        .set_mp1_state = vega20_set_mp1_state,
        .smu_i2c_bus_access = vega20_smu_i2c_bus_access,
        .set_df_cstate = vega20_set_df_cstate,
+       .set_xgmi_pstate = vega20_set_xgmi_pstate,
 };
 
 int vega20_hwmgr_init(struct pp_hwmgr *hwmgr)
index bd8c922dfd3ece5a00772fa7df618573ab6d1c8e..af977675fd3356fc1b25039f9f24335a3545abe1 100644 (file)
@@ -356,6 +356,9 @@ struct pp_hwmgr_func {
        int (*asic_reset)(struct pp_hwmgr *hwmgr, enum SMU_ASIC_RESET_MODE mode);
        int (*smu_i2c_bus_access)(struct pp_hwmgr *hwmgr, bool aquire);
        int (*set_df_cstate)(struct pp_hwmgr *hwmgr, enum pp_df_cstate state);
+       int (*set_xgmi_pstate)(struct pp_hwmgr *hwmgr, uint32_t pstate);
+       int (*disable_power_features_for_compute_performance)(struct pp_hwmgr *hwmgr,
+                                       bool disable);
 };
 
 struct pp_table_func {
index 886b9a21ebd8ebce56ea6fe01f88e1193ed21b39..a886f0644d24589acf1fccbb75fcf097da2bf48b 100644 (file)
 //FIXME need updating
 // Debug Overrides Bitmask
 #define DPM_OVERRIDE_DISABLE_UCLK_PID               0x00000001
-#define DPM_OVERRIDE_ENABLE_VOLT_LINK_VCN_FCLK      0x00000002
+#define DPM_OVERRIDE_DISABLE_VOLT_LINK_VCN_FCLK     0x00000002
 
 // I2C Config Bit Defines
 #define I2C_CONTROLLER_ENABLED           1
index abd4debb3def149f45b59c10f5d8d0a2b209114b..fd6ec9033d06455dcb70bcb26aedb7e51d0e9749 100644 (file)
@@ -27,7 +27,7 @@
 
 #define SMU11_DRIVER_IF_VERSION_INV 0xFFFFFFFF
 #define SMU11_DRIVER_IF_VERSION_VG20 0x13
-#define SMU11_DRIVER_IF_VERSION_ARCT 0x0F
+#define SMU11_DRIVER_IF_VERSION_ARCT 0x10
 #define SMU11_DRIVER_IF_VERSION_NV10 0x33
 #define SMU11_DRIVER_IF_VERSION_NV14 0x34
 
index 769f9451d90437d5ba1017f2990f28c1805e8fc0..354f70978f82336668f17e5187df5a3edca67fc9 100644 (file)
@@ -207,7 +207,7 @@ static struct smu_11_0_cmn2aisc_mapping navi10_workload_map[PP_SMC_POWER_PROFILE
        WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING,          WORKLOAD_PPLIB_POWER_SAVING_BIT),
        WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO,                WORKLOAD_PPLIB_VIDEO_BIT),
        WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR,                   WORKLOAD_PPLIB_VR_BIT),
-       WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE,              WORKLOAD_PPLIB_CUSTOM_BIT),
+       WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE,              WORKLOAD_PPLIB_COMPUTE_BIT),
        WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM,               WORKLOAD_PPLIB_CUSTOM_BIT),
 };
 
index 4a9751971a9dd7762a3e3b9b95cf9a863f60e617..04daf7e9fe0550a2e38f5eb248b7d8d42d8a00f5 100644 (file)
@@ -180,11 +180,13 @@ static int renoir_print_clk_levels(struct smu_context *smu,
        int i, size = 0, ret = 0;
        uint32_t cur_value = 0, value = 0, count = 0, min = 0, max = 0;
        DpmClocks_t *clk_table = smu->smu_table.clocks_table;
-       SmuMetrics_t metrics = {0};
+       SmuMetrics_t metrics;
 
        if (!clk_table || clk_type >= SMU_CLK_COUNT)
                return -EINVAL;
 
+       memset(&metrics, 0, sizeof(metrics));
+
        ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
                               (void *)&metrics, false);
        if (ret)
index bbb74b1d5d8016bcd01122b3fdf93d0d10292381..e859bb1132ac9c3fd202bd9d8d373e97130cc2f8 100644 (file)
@@ -368,6 +368,7 @@ int smu_v11_0_setup_pptable(struct smu_context *smu)
        version_major = le16_to_cpu(hdr->header.header_version_major);
        version_minor = le16_to_cpu(hdr->header.header_version_minor);
        if (version_major == 2 && smu->smu_table.boot_values.pp_table_id > 0) {
+               pr_info("use driver provided pptable %d\n", smu->smu_table.boot_values.pp_table_id);
                switch (version_minor) {
                case 0:
                        ret = smu_v11_0_set_pptable_v2_0(smu, &table, &size);
@@ -384,6 +385,7 @@ int smu_v11_0_setup_pptable(struct smu_context *smu)
                        return ret;
 
        } else {
+               pr_info("use vbios provided pptable\n");
                index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
                                                    powerplayinfo);
 
@@ -1463,16 +1465,13 @@ int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu,
        return ret;
 }
 
-#define XGMI_STATE_D0 1
-#define XGMI_STATE_D3 0
-
 int smu_v11_0_set_xgmi_pstate(struct smu_context *smu,
                                     uint32_t pstate)
 {
        int ret = 0;
        ret = smu_send_smc_msg_with_param(smu,
                                          SMU_MSG_SetXgmiMode,
-                                         pstate ? XGMI_STATE_D0 : XGMI_STATE_D3);
+                                         pstate ? XGMI_MODE_PSTATE_D0 : XGMI_MODE_PSTATE_D3);
        return ret;
 }
 
index 7c8933f987d1511134e28f6379b055a9612d56e6..5b21386f558de256cb2581d4f67a4e3b53c72f4e 100644 (file)
@@ -221,7 +221,7 @@ static struct smu_11_0_cmn2aisc_mapping vega20_workload_map[PP_SMC_POWER_PROFILE
        WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING,          WORKLOAD_PPLIB_POWER_SAVING_BIT),
        WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO,                WORKLOAD_PPLIB_VIDEO_BIT),
        WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR,                   WORKLOAD_PPLIB_VR_BIT),
-       WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE,              WORKLOAD_PPLIB_CUSTOM_BIT),
+       WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE,              WORKLOAD_PPLIB_COMPUTE_BIT),
        WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM,               WORKLOAD_PPLIB_CUSTOM_BIT),
 };
 
index d49772de93e09207d844a1499a863118d9b0852e..52648b4008bc3fb4ce448a777f6b661fe5156189 100644 (file)
@@ -84,7 +84,8 @@ static void komeda_kms_commit_tail(struct drm_atomic_state *old_state)
 
        drm_atomic_helper_commit_modeset_disables(dev, old_state);
 
-       drm_atomic_helper_commit_planes(dev, old_state, 0);
+       drm_atomic_helper_commit_planes(dev, old_state,
+                                       DRM_PLANE_COMMIT_ACTIVE_ONLY);
 
        drm_atomic_helper_commit_modeset_enables(dev, old_state);
 
index 42bdc63dcffad2f581b0122f953959833e4e61a4..52750116aa19b7e640a2ffd7d047d5fe32421b38 100644 (file)
@@ -581,8 +581,8 @@ komeda_splitter_validate(struct komeda_splitter *splitter,
        }
 
        if (!in_range(&splitter->vsize, dflow->in_h)) {
-               DRM_DEBUG_ATOMIC("split in_in: %d exceed the acceptable range.\n",
-                                dflow->in_w);
+               DRM_DEBUG_ATOMIC("split in_h: %d exceeds the acceptable range.\n",
+                                dflow->in_h);
                return -EINVAL;
        }
 
index 587052751b481e8f754962d92f2c8c69d3c616ed..b191d39c071d85ccdfb87d36f15418055cd197a7 100644 (file)
@@ -1571,8 +1571,11 @@ static void commit_tail(struct drm_atomic_state *old_state)
 {
        struct drm_device *dev = old_state->dev;
        const struct drm_mode_config_helper_funcs *funcs;
+       struct drm_crtc_state *new_crtc_state;
+       struct drm_crtc *crtc;
        ktime_t start;
        s64 commit_time_ms;
+       unsigned int i, new_self_refresh_mask = 0;
 
        funcs = dev->mode_config.helper_private;
 
@@ -1592,6 +1595,15 @@ static void commit_tail(struct drm_atomic_state *old_state)
 
        drm_atomic_helper_wait_for_dependencies(old_state);
 
+       /*
+        * We cannot safely access new_crtc_state after
+        * drm_atomic_helper_commit_hw_done() so figure out which crtc's have
+        * self-refresh active beforehand:
+        */
+       for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i)
+               if (new_crtc_state->self_refresh_active)
+                       new_self_refresh_mask |= BIT(i);
+
        if (funcs && funcs->atomic_commit_tail)
                funcs->atomic_commit_tail(old_state);
        else
@@ -1600,7 +1612,8 @@ static void commit_tail(struct drm_atomic_state *old_state)
        commit_time_ms = ktime_ms_delta(ktime_get(), start);
        if (commit_time_ms > 0)
                drm_self_refresh_helper_update_avg_times(old_state,
-                                                (unsigned long)commit_time_ms);
+                                                (unsigned long)commit_time_ms,
+                                                new_self_refresh_mask);
 
        drm_atomic_helper_commit_cleanup_done(old_state);
 
index 68f4765a5896472775500836b7dfc537de0b862a..dd33fec5aabdedcdbac2c99180c56b6737875aab 100644 (file)
@@ -133,29 +133,33 @@ out_drop_locks:
  * drm_self_refresh_helper_update_avg_times - Updates a crtc's SR time averages
  * @state: the state which has just been applied to hardware
  * @commit_time_ms: the amount of time in ms that this commit took to complete
+ * @new_self_refresh_mask: bitmask of crtc's that have self_refresh_active in
+ *    new state
  *
  * Called after &drm_mode_config_funcs.atomic_commit_tail, this function will
  * update the average entry/exit self refresh times on self refresh transitions.
  * These averages will be used when calculating how long to delay before
  * entering self refresh mode after activity.
  */
-void drm_self_refresh_helper_update_avg_times(struct drm_atomic_state *state,
-                                             unsigned int commit_time_ms)
+void
+drm_self_refresh_helper_update_avg_times(struct drm_atomic_state *state,
+                                        unsigned int commit_time_ms,
+                                        unsigned int new_self_refresh_mask)
 {
        struct drm_crtc *crtc;
-       struct drm_crtc_state *old_crtc_state, *new_crtc_state;
+       struct drm_crtc_state *old_crtc_state;
        int i;
 
-       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state,
-                                     new_crtc_state, i) {
+       for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) {
+               bool new_self_refresh_active = new_self_refresh_mask & BIT(i);
                struct drm_self_refresh_data *sr_data = crtc->self_refresh_data;
                struct ewma_psr_time *time;
 
                if (old_crtc_state->self_refresh_active ==
-                   new_crtc_state->self_refresh_active)
+                   new_self_refresh_active)
                        continue;
 
-               if (new_crtc_state->self_refresh_active)
+               if (new_self_refresh_active)
                        time = &sr_data->entry_avg_ms;
                else
                        time = &sr_data->exit_avg_ms;
index 698db540972c3a09ec3f3147bd87eea156681f4a..648cf0207309219362c7d94df777fc00fece30d1 100644 (file)
@@ -180,6 +180,8 @@ void etnaviv_core_dump(struct etnaviv_gem_submit *submit)
                              etnaviv_cmdbuf_get_va(&submit->cmdbuf,
                                        &gpu->mmu_context->cmdbuf_mapping));
 
+       mutex_unlock(&gpu->mmu_context->lock);
+
        /* Reserve space for the bomap */
        if (n_bomap_pages) {
                bomap_start = bomap = iter.data;
@@ -221,8 +223,6 @@ void etnaviv_core_dump(struct etnaviv_gem_submit *submit)
                                         obj->base.size);
        }
 
-       mutex_unlock(&gpu->mmu_context->lock);
-
        etnaviv_core_dump_header(&iter, ETDUMP_BUF_END, iter.data);
 
        dev_coredumpv(gpu->dev, iter.start, iter.data - iter.start, GFP_KERNEL);
index 043111a1d60c4f9712c96abb427bbcfb4816d2e3..f8bf488e9d717360aa21a9f7f3db45ed25dd5278 100644 (file)
@@ -155,9 +155,11 @@ static void etnaviv_iommuv2_dump(struct etnaviv_iommu_context *context, void *bu
 
        memcpy(buf, v2_context->mtlb_cpu, SZ_4K);
        buf += SZ_4K;
-       for (i = 0; i < MMUv2_MAX_STLB_ENTRIES; i++, buf += SZ_4K)
-               if (v2_context->mtlb_cpu[i] & MMUv2_PTE_PRESENT)
+       for (i = 0; i < MMUv2_MAX_STLB_ENTRIES; i++)
+               if (v2_context->mtlb_cpu[i] & MMUv2_PTE_PRESENT) {
                        memcpy(buf, v2_context->stlb_cpu[i], SZ_4K);
+                       buf += SZ_4K;
+               }
 }
 
 static void etnaviv_iommuv2_restore_nonsec(struct etnaviv_gpu *gpu,
index 35ebae6a1be7ddbbbe9b42d8f16349a082fc155a..3607d348c2980f1332e8a7a02faa80ce6619814c 100644 (file)
@@ -328,12 +328,23 @@ etnaviv_iommu_context_init(struct etnaviv_iommu_global *global,
 
        ret = etnaviv_cmdbuf_suballoc_map(suballoc, ctx, &ctx->cmdbuf_mapping,
                                          global->memory_base);
-       if (ret) {
-               global->ops->free(ctx);
-               return NULL;
+       if (ret)
+               goto out_free;
+
+       if (global->version == ETNAVIV_IOMMU_V1 &&
+           ctx->cmdbuf_mapping.iova > 0x80000000) {
+               dev_err(global->dev,
+                       "command buffer outside valid memory window\n");
+               goto out_unmap;
        }
 
        return ctx;
+
+out_unmap:
+       etnaviv_cmdbuf_suballoc_unmap(ctx, &ctx->cmdbuf_mapping);
+out_free:
+       global->ops->free(ctx);
+       return NULL;
 }
 
 void etnaviv_iommu_restore(struct etnaviv_gpu *gpu,
index 9d086133a84ed23b216fae55bf69b1d74668dc80..9458dc6c750cf36397afcb692f65e5e702f07096 100644 (file)
@@ -556,11 +556,11 @@ static int panfrost_probe(struct platform_device *pdev)
        return 0;
 
 err_out2:
+       pm_runtime_disable(pfdev->dev);
        panfrost_devfreq_fini(pfdev);
 err_out1:
        panfrost_device_fini(pfdev);
 err_out0:
-       pm_runtime_disable(pfdev->dev);
        drm_dev_put(ddev);
        return err;
 }
index bdd99056847689c2c88fe67d1435e84662cd0eb6..a3ed64a1f15ecd8fd686b99fce496ddb760ed938 100644 (file)
@@ -224,9 +224,9 @@ static size_t get_pgsize(u64 addr, size_t size)
        return SZ_2M;
 }
 
-void panfrost_mmu_flush_range(struct panfrost_device *pfdev,
-                             struct panfrost_mmu *mmu,
-                             u64 iova, size_t size)
+static void panfrost_mmu_flush_range(struct panfrost_device *pfdev,
+                                    struct panfrost_mmu *mmu,
+                                    u64 iova, size_t size)
 {
        if (mmu->as < 0)
                return;
@@ -406,11 +406,11 @@ addr_to_drm_mm_node(struct panfrost_device *pfdev, int as, u64 addr)
        spin_lock(&pfdev->as_lock);
        list_for_each_entry(mmu, &pfdev->as_lru_list, list) {
                if (as == mmu->as)
-                       break;
+                       goto found_mmu;
        }
-       if (as != mmu->as)
-               goto out;
+       goto out;
 
+found_mmu:
        priv = container_of(mmu, struct panfrost_file_priv, mmu);
 
        spin_lock(&priv->mm_lock);
@@ -432,7 +432,8 @@ out:
 
 #define NUM_FAULT_PAGES (SZ_2M / PAGE_SIZE)
 
-int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as, u64 addr)
+static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
+                                      u64 addr)
 {
        int ret, i;
        struct panfrost_gem_object *bo;
index 83c57d325ca8754519b4949ca817c9187018db16..2dba192bf198454982d54ab9403f253e0529c652 100644 (file)
@@ -16,6 +16,7 @@
 #include "panfrost_issues.h"
 #include "panfrost_job.h"
 #include "panfrost_mmu.h"
+#include "panfrost_perfcnt.h"
 #include "panfrost_regs.h"
 
 #define COUNTERS_PER_BLOCK             64
index 460fd98e40a78ded29005383d0e56b34737f2e3d..a0b382a637a6428d15dfad0ed28558aa7add4677 100644 (file)
@@ -1958,6 +1958,7 @@ static void si_initialize_powertune_defaults(struct radeon_device *rdev)
                case 0x682C:
                        si_pi->cac_weights = cac_weights_cape_verde_pro;
                        si_pi->dte_data = dte_data_sun_xt;
+                       update_dte_from_pl2 = true;
                        break;
                case 0x6825:
                case 0x6827:
index 1a5153197fe972e779a1bb7ba4169c8161907681..461a7a8129f4ebe10996dde4b99235d3aee9cf1f 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <linux/kthread.h>
 #include <linux/slab.h>
+#include <linux/completion.h>
 
 #include <drm/drm_print.h>
 #include <drm/gpu_scheduler.h>
@@ -68,6 +69,8 @@ int drm_sched_entity_init(struct drm_sched_entity *entity,
        if (!entity->rq_list)
                return -ENOMEM;
 
+       init_completion(&entity->entity_idle);
+
        for (i = 0; i < num_rq_list; ++i)
                entity->rq_list[i] = rq_list[i];
 
@@ -286,11 +289,12 @@ void drm_sched_entity_fini(struct drm_sched_entity *entity)
         */
        if (spsc_queue_count(&entity->job_queue)) {
                if (sched) {
-                       /* Park the kernel for a moment to make sure it isn't processing
-                        * our enity.
+                       /*
+                        * Wait for thread to idle to make sure it isn't processing
+                        * this entity.
                         */
-                       kthread_park(sched->thread);
-                       kthread_unpark(sched->thread);
+                       wait_for_completion(&entity->entity_idle);
+
                }
                if (entity->dependency) {
                        dma_fence_remove_callback(entity->dependency,
index 2af64459b3d77023c0554a89e950a57d0b526e6e..3c57e84222ca92f3bec53318a7b9ab02429c6c8d 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/kthread.h>
 #include <linux/wait.h>
 #include <linux/sched.h>
+#include <linux/completion.h>
 #include <uapi/linux/sched/types.h>
 
 #include <drm/drm_print.h>
@@ -134,6 +135,7 @@ drm_sched_rq_select_entity(struct drm_sched_rq *rq)
                list_for_each_entry_continue(entity, &rq->entities, list) {
                        if (drm_sched_entity_is_ready(entity)) {
                                rq->current_entity = entity;
+                               reinit_completion(&entity->entity_idle);
                                spin_unlock(&rq->lock);
                                return entity;
                        }
@@ -144,6 +146,7 @@ drm_sched_rq_select_entity(struct drm_sched_rq *rq)
 
                if (drm_sched_entity_is_ready(entity)) {
                        rq->current_entity = entity;
+                       reinit_completion(&entity->entity_idle);
                        spin_unlock(&rq->lock);
                        return entity;
                }
@@ -496,8 +499,10 @@ void drm_sched_resubmit_jobs(struct drm_gpu_scheduler *sched)
                fence = sched->ops->run_job(s_job);
 
                if (IS_ERR_OR_NULL(fence)) {
+                       if (IS_ERR(fence))
+                               dma_fence_set_error(&s_fence->finished, PTR_ERR(fence));
+
                        s_job->s_fence->parent = NULL;
-                       dma_fence_set_error(&s_fence->finished, PTR_ERR(fence));
                } else {
                        s_job->s_fence->parent = fence;
                }
@@ -645,9 +650,13 @@ drm_sched_get_cleanup_job(struct drm_gpu_scheduler *sched)
        struct drm_sched_job *job;
        unsigned long flags;
 
-       /* Don't destroy jobs while the timeout worker is running */
-       if (sched->timeout != MAX_SCHEDULE_TIMEOUT &&
-           !cancel_delayed_work(&sched->work_tdr))
+       /*
+        * Don't destroy jobs while the timeout worker is running  OR thread
+        * is being parked and hence assumed to not touch ring_mirror_list
+        */
+       if ((sched->timeout != MAX_SCHEDULE_TIMEOUT &&
+           !cancel_delayed_work(&sched->work_tdr)) ||
+           __kthread_should_park(sched->thread))
                return NULL;
 
        spin_lock_irqsave(&sched->job_list_lock, flags);
@@ -724,6 +733,9 @@ static int drm_sched_main(void *param)
                        continue;
 
                sched_job = drm_sched_entity_pop_job(entity);
+
+               complete(&entity->entity_idle);
+
                if (!sched_job)
                        continue;
 
@@ -746,8 +758,9 @@ static int drm_sched_main(void *param)
                                          r);
                        dma_fence_put(fence);
                } else {
+                       if (IS_ERR(fence))
+                               dma_fence_set_error(&s_fence->finished, PTR_ERR(fence));
 
-                       dma_fence_set_error(&s_fence->finished, PTR_ERR(fence));
                        drm_sched_process_job(NULL, &sched_job->cb);
                }
 
index 4c4b59ae2c81067dd39b5113a8edea29dff3a40f..549dde83408b0ffed1b0204702978b351e17917a 100644 (file)
@@ -560,14 +560,17 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
 
        if (args->bcl_start != args->bcl_end) {
                bin = kcalloc(1, sizeof(*bin), GFP_KERNEL);
-               if (!bin)
+               if (!bin) {
+                       v3d_job_put(&render->base);
                        return -ENOMEM;
+               }
 
                ret = v3d_job_init(v3d, file_priv, &bin->base,
                                   v3d_job_free, args->in_sync_bcl);
                if (ret) {
                        kfree(bin);
                        v3d_job_put(&render->base);
+                       kfree(bin);
                        return ret;
                }
 
index 6654c1550e2e7af9e73b439ae6b7cc45ee31cc88..fbe4e16ab0297f778402eca7d9e44d2621bd1154 100644 (file)
@@ -63,13 +63,20 @@ static int axff_init(struct hid_device *hid)
 {
        struct axff_device *axff;
        struct hid_report *report;
-       struct hid_input *hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
+       struct hid_input *hidinput;
        struct list_head *report_list =&hid->report_enum[HID_OUTPUT_REPORT].report_list;
-       struct input_dev *dev = hidinput->input;
+       struct input_dev *dev;
        int field_count = 0;
        int i, j;
        int error;
 
+       if (list_empty(&hid->inputs)) {
+               hid_err(hid, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
+       dev = hidinput->input;
+
        if (list_empty(report_list)) {
                hid_err(hid, "no output reports found\n");
                return -ENODEV;
index 3eaee2c37931bad846decfa127bb905c134770e9..63fdbf09b044f3c8b0211d7e46c25ffa39776eb0 100644 (file)
@@ -1139,6 +1139,7 @@ int hid_open_report(struct hid_device *device)
        __u8 *start;
        __u8 *buf;
        __u8 *end;
+       __u8 *next;
        int ret;
        static int (*dispatch_type[])(struct hid_parser *parser,
                                      struct hid_item *item) = {
@@ -1192,7 +1193,8 @@ int hid_open_report(struct hid_device *device)
        device->collection_size = HID_DEFAULT_NUM_COLLECTIONS;
 
        ret = -EINVAL;
-       while ((start = fetch_item(start, end, &item)) != NULL) {
+       while ((next = fetch_item(start, end, &item)) != NULL) {
+               start = next;
 
                if (item.format != HID_ITEM_FORMAT_SHORT) {
                        hid_err(device, "unexpected long global item\n");
@@ -1230,7 +1232,8 @@ int hid_open_report(struct hid_device *device)
                }
        }
 
-       hid_err(device, "item fetching failed at offset %d\n", (int)(end - start));
+       hid_err(device, "item fetching failed at offset %u/%u\n",
+               size - (unsigned int)(end - start), size);
 err:
        kfree(parser->collection_stack);
 alloc_err:
index 17e17f9a597b5d9edc35b6f85c5b4b3db13e8727..947f19f8685f8668ea6e5568d3dad821156c3fa3 100644 (file)
@@ -75,13 +75,19 @@ static int drff_init(struct hid_device *hid)
 {
        struct drff_device *drff;
        struct hid_report *report;
-       struct hid_input *hidinput = list_first_entry(&hid->inputs,
-                                               struct hid_input, list);
+       struct hid_input *hidinput;
        struct list_head *report_list =
                        &hid->report_enum[HID_OUTPUT_REPORT].report_list;
-       struct input_dev *dev = hidinput->input;
+       struct input_dev *dev;
        int error;
 
+       if (list_empty(&hid->inputs)) {
+               hid_err(hid, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
+       dev = hidinput->input;
+
        if (list_empty(report_list)) {
                hid_err(hid, "no output reports found\n");
                return -ENODEV;
index 7cd5651872d3bd8b8c20455608914322a86c7185..c34f2e5a049f4dd314c72435d41398b2b87b0431 100644 (file)
@@ -47,13 +47,19 @@ static int emsff_init(struct hid_device *hid)
 {
        struct emsff_device *emsff;
        struct hid_report *report;
-       struct hid_input *hidinput = list_first_entry(&hid->inputs,
-                                               struct hid_input, list);
+       struct hid_input *hidinput;
        struct list_head *report_list =
                        &hid->report_enum[HID_OUTPUT_REPORT].report_list;
-       struct input_dev *dev = hidinput->input;
+       struct input_dev *dev;
        int error;
 
+       if (list_empty(&hid->inputs)) {
+               hid_err(hid, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
+       dev = hidinput->input;
+
        if (list_empty(report_list)) {
                hid_err(hid, "no output reports found\n");
                return -ENODEV;
index 0f95c96b70f810114f770d129dd3dd66a12185c6..ecbd3995a4eb1940c689c23ccbda5437f17d237d 100644 (file)
@@ -64,14 +64,20 @@ static int gaff_init(struct hid_device *hid)
 {
        struct gaff_device *gaff;
        struct hid_report *report;
-       struct hid_input *hidinput = list_entry(hid->inputs.next,
-                                               struct hid_input, list);
+       struct hid_input *hidinput;
        struct list_head *report_list =
                        &hid->report_enum[HID_OUTPUT_REPORT].report_list;
        struct list_head *report_ptr = report_list;
-       struct input_dev *dev = hidinput->input;
+       struct input_dev *dev;
        int error;
 
+       if (list_empty(&hid->inputs)) {
+               hid_err(hid, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+       dev = hidinput->input;
+
        if (list_empty(report_list)) {
                hid_err(hid, "no output reports found\n");
                return -ENODEV;
index 84f8c127ebdc745b61723b7ee2dffb532ce599a2..d86a9189e88fd0b56fc9b088313765a151c12f40 100644 (file)
@@ -469,6 +469,10 @@ static int hammer_probe(struct hid_device *hdev,
 static const struct hid_device_id hammer_devices[] = {
        { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
                     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_HAMMER) },
+       { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
+                    USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_MAGNEMITE) },
+       { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
+                    USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_MASTERBALL) },
        { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
                     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_STAFF) },
        { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
index 10a7205588303d5180ef0b4fdecdba93d7d6b2f5..8619b80c834cc0b3c609eed7528b79f60f871ba2 100644 (file)
@@ -124,13 +124,19 @@ static int holtekff_init(struct hid_device *hid)
 {
        struct holtekff_device *holtekff;
        struct hid_report *report;
-       struct hid_input *hidinput = list_entry(hid->inputs.next,
-                                               struct hid_input, list);
+       struct hid_input *hidinput;
        struct list_head *report_list =
                        &hid->report_enum[HID_OUTPUT_REPORT].report_list;
-       struct input_dev *dev = hidinput->input;
+       struct input_dev *dev;
        int error;
 
+       if (list_empty(&hid->inputs)) {
+               hid_err(hid, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+       dev = hidinput->input;
+
        if (list_empty(report_list)) {
                hid_err(hid, "no output report found\n");
                return -ENODEV;
index 76969a22b0f2f796a2b424ed252a8c0d08c3e3bd..447e8db21174ae78d35e372868d9234a31318963 100644 (file)
 #define USB_DEVICE_ID_GOOGLE_STAFF     0x502b
 #define USB_DEVICE_ID_GOOGLE_WAND      0x502d
 #define USB_DEVICE_ID_GOOGLE_WHISKERS  0x5030
+#define USB_DEVICE_ID_GOOGLE_MASTERBALL        0x503c
+#define USB_DEVICE_ID_GOOGLE_MAGNEMITE 0x503d
 
 #define USB_VENDOR_ID_GOTOP            0x08f2
 #define USB_DEVICE_ID_SUPER_Q2         0x007f
index dd1a6c3a7de67464cec36e48fd89fc9e9a66d02c..73d07e35f12aa73dd58714c1792e7e00677b6f2b 100644 (file)
@@ -50,11 +50,17 @@ int lg2ff_init(struct hid_device *hid)
 {
        struct lg2ff_device *lg2ff;
        struct hid_report *report;
-       struct hid_input *hidinput = list_entry(hid->inputs.next,
-                                               struct hid_input, list);
-       struct input_dev *dev = hidinput->input;
+       struct hid_input *hidinput;
+       struct input_dev *dev;
        int error;
 
+       if (list_empty(&hid->inputs)) {
+               hid_err(hid, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+       dev = hidinput->input;
+
        /* Check that the report looks ok */
        report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7);
        if (!report)
index 9ecb6fd062030eb3ea21aab9d99a81c2172ed4d4..b7e1949f3cf779de12accc337981406dd1910f26 100644 (file)
@@ -117,12 +117,19 @@ static const signed short ff3_joystick_ac[] = {
 
 int lg3ff_init(struct hid_device *hid)
 {
-       struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
-       struct input_dev *dev = hidinput->input;
+       struct hid_input *hidinput;
+       struct input_dev *dev;
        const signed short *ff_bits = ff3_joystick_ac;
        int error;
        int i;
 
+       if (list_empty(&hid->inputs)) {
+               hid_err(hid, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+       dev = hidinput->input;
+
        /* Check that the report looks ok */
        if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 35))
                return -ENODEV;
index 03f0220062cab641a725eddc2e4d51c1bedca141..5e6a0cef2a06d061035520a28e24cc4488859498 100644 (file)
@@ -1253,8 +1253,8 @@ static int lg4ff_handle_multimode_wheel(struct hid_device *hid, u16 *real_produc
 
 int lg4ff_init(struct hid_device *hid)
 {
-       struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
-       struct input_dev *dev = hidinput->input;
+       struct hid_input *hidinput;
+       struct input_dev *dev;
        struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
        struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
        const struct usb_device_descriptor *udesc = &(hid_to_usb_dev(hid)->descriptor);
@@ -1266,6 +1266,13 @@ int lg4ff_init(struct hid_device *hid)
        int mmode_ret, mmode_idx = -1;
        u16 real_product_id;
 
+       if (list_empty(&hid->inputs)) {
+               hid_err(hid, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+       dev = hidinput->input;
+
        /* Check that the report looks ok */
        if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7))
                return -1;
index c79a6ec437450029f4490ed4e4dfe9ac1f280d2e..aed4ddc397a963154a041487e8d3c8c455b4cbdd 100644 (file)
@@ -115,12 +115,19 @@ static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude)
 
 int lgff_init(struct hid_device* hid)
 {
-       struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
-       struct input_dev *dev = hidinput->input;
+       struct hid_input *hidinput;
+       struct input_dev *dev;
        const signed short *ff_bits = ff_joystick;
        int error;
        int i;
 
+       if (list_empty(&hid->inputs)) {
+               hid_err(hid, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+       dev = hidinput->input;
+
        /* Check that the report looks ok */
        if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7))
                return -ENODEV;
index 0179f7ed77e5b13f852f4c4fb3fa9619f1c15677..8e91e2f06cb4fc8574e08ca3c8ddd2b4595767e3 100644 (file)
@@ -1669,6 +1669,7 @@ static void hidpp_touchpad_raw_xy_event(struct hidpp_device *hidpp_dev,
 
 #define HIDPP_FF_EFFECTID_NONE         -1
 #define HIDPP_FF_EFFECTID_AUTOCENTER   -2
+#define HIDPP_AUTOCENTER_PARAMS_LENGTH 18
 
 #define HIDPP_FF_MAX_PARAMS    20
 #define HIDPP_FF_RESERVED_SLOTS        1
@@ -2009,7 +2010,7 @@ static int hidpp_ff_erase_effect(struct input_dev *dev, int effect_id)
 static void hidpp_ff_set_autocenter(struct input_dev *dev, u16 magnitude)
 {
        struct hidpp_ff_private_data *data = dev->ff->private;
-       u8 params[18];
+       u8 params[HIDPP_AUTOCENTER_PARAMS_LENGTH];
 
        dbg_hid("Setting autocenter to %d.\n", magnitude);
 
@@ -2077,23 +2078,34 @@ static DEVICE_ATTR(range, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, hidpp
 static void hidpp_ff_destroy(struct ff_device *ff)
 {
        struct hidpp_ff_private_data *data = ff->private;
+       struct hid_device *hid = data->hidpp->hid_dev;
 
+       hid_info(hid, "Unloading HID++ force feedback.\n");
+
+       device_remove_file(&hid->dev, &dev_attr_range);
+       destroy_workqueue(data->wq);
        kfree(data->effect_ids);
 }
 
-static int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index)
+static int hidpp_ff_init(struct hidpp_device *hidpp,
+                        struct hidpp_ff_private_data *data)
 {
        struct hid_device *hid = hidpp->hid_dev;
-       struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
-       struct input_dev *dev = hidinput->input;
+       struct hid_input *hidinput;
+       struct input_dev *dev;
        const struct usb_device_descriptor *udesc = &(hid_to_usb_dev(hid)->descriptor);
        const u16 bcdDevice = le16_to_cpu(udesc->bcdDevice);
        struct ff_device *ff;
-       struct hidpp_report response;
-       struct hidpp_ff_private_data *data;
-       int error, j, num_slots;
+       int error, j, num_slots = data->num_effects;
        u8 version;
 
+       if (list_empty(&hid->inputs)) {
+               hid_err(hid, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+       dev = hidinput->input;
+
        if (!dev) {
                hid_err(hid, "Struct input_dev not set!\n");
                return -EINVAL;
@@ -2109,27 +2121,17 @@ static int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index)
                for (j = 0; hidpp_ff_effects_v2[j] >= 0; j++)
                        set_bit(hidpp_ff_effects_v2[j], dev->ffbit);
 
-       /* Read number of slots available in device */
-       error = hidpp_send_fap_command_sync(hidpp, feature_index,
-               HIDPP_FF_GET_INFO, NULL, 0, &response);
-       if (error) {
-               if (error < 0)
-                       return error;
-               hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n",
-                       __func__, error);
-               return -EPROTO;
-       }
-
-       num_slots = response.fap.params[0] - HIDPP_FF_RESERVED_SLOTS;
-
        error = input_ff_create(dev, num_slots);
 
        if (error) {
                hid_err(dev, "Failed to create FF device!\n");
                return error;
        }
-
-       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       /*
+        * Create a copy of passed data, so we can transfer memory
+        * ownership to FF core
+        */
+       data = kmemdup(data, sizeof(*data), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
        data->effect_ids = kcalloc(num_slots, sizeof(int), GFP_KERNEL);
@@ -2145,10 +2147,7 @@ static int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index)
        }
 
        data->hidpp = hidpp;
-       data->feature_index = feature_index;
        data->version = version;
-       data->slot_autocenter = 0;
-       data->num_effects = num_slots;
        for (j = 0; j < num_slots; j++)
                data->effect_ids[j] = -1;
 
@@ -2162,68 +2161,20 @@ static int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index)
        ff->set_autocenter = hidpp_ff_set_autocenter;
        ff->destroy = hidpp_ff_destroy;
 
-
-       /* reset all forces */
-       error = hidpp_send_fap_command_sync(hidpp, feature_index,
-               HIDPP_FF_RESET_ALL, NULL, 0, &response);
-
-       /* Read current Range */
-       error = hidpp_send_fap_command_sync(hidpp, feature_index,
-               HIDPP_FF_GET_APERTURE, NULL, 0, &response);
-       if (error)
-               hid_warn(hidpp->hid_dev, "Failed to read range from device!\n");
-       data->range = error ? 900 : get_unaligned_be16(&response.fap.params[0]);
-
        /* Create sysfs interface */
        error = device_create_file(&(hidpp->hid_dev->dev), &dev_attr_range);
        if (error)
                hid_warn(hidpp->hid_dev, "Unable to create sysfs interface for \"range\", errno %d!\n", error);
 
-       /* Read the current gain values */
-       error = hidpp_send_fap_command_sync(hidpp, feature_index,
-               HIDPP_FF_GET_GLOBAL_GAINS, NULL, 0, &response);
-       if (error)
-               hid_warn(hidpp->hid_dev, "Failed to read gain values from device!\n");
-       data->gain = error ? 0xffff : get_unaligned_be16(&response.fap.params[0]);
-       /* ignore boost value at response.fap.params[2] */
-
        /* init the hardware command queue */
        atomic_set(&data->workqueue_size, 0);
 
-       /* initialize with zero autocenter to get wheel in usable state */
-       hidpp_ff_set_autocenter(dev, 0);
-
        hid_info(hid, "Force feedback support loaded (firmware release %d).\n",
                 version);
 
        return 0;
 }
 
-static int hidpp_ff_deinit(struct hid_device *hid)
-{
-       struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
-       struct input_dev *dev = hidinput->input;
-       struct hidpp_ff_private_data *data;
-
-       if (!dev) {
-               hid_err(hid, "Struct input_dev not found!\n");
-               return -EINVAL;
-       }
-
-       hid_info(hid, "Unloading HID++ force feedback.\n");
-       data = dev->ff->private;
-       if (!data) {
-               hid_err(hid, "Private data not found!\n");
-               return -EINVAL;
-       }
-
-       destroy_workqueue(data->wq);
-       device_remove_file(&hid->dev, &dev_attr_range);
-
-       return 0;
-}
-
-
 /* ************************************************************************** */
 /*                                                                            */
 /* Device Support                                                             */
@@ -2725,24 +2676,93 @@ static int k400_connect(struct hid_device *hdev, bool connected)
 
 #define HIDPP_PAGE_G920_FORCE_FEEDBACK                 0x8123
 
-static int g920_get_config(struct hidpp_device *hidpp)
+static int g920_ff_set_autocenter(struct hidpp_device *hidpp,
+                                 struct hidpp_ff_private_data *data)
 {
+       struct hidpp_report response;
+       u8 params[HIDPP_AUTOCENTER_PARAMS_LENGTH] = {
+               [1] = HIDPP_FF_EFFECT_SPRING | HIDPP_FF_EFFECT_AUTOSTART,
+       };
+       int ret;
+
+       /* initialize with zero autocenter to get wheel in usable state */
+
+       dbg_hid("Setting autocenter to 0.\n");
+       ret = hidpp_send_fap_command_sync(hidpp, data->feature_index,
+                                         HIDPP_FF_DOWNLOAD_EFFECT,
+                                         params, ARRAY_SIZE(params),
+                                         &response);
+       if (ret)
+               hid_warn(hidpp->hid_dev, "Failed to autocenter device!\n");
+       else
+               data->slot_autocenter = response.fap.params[0];
+
+       return ret;
+}
+
+static int g920_get_config(struct hidpp_device *hidpp,
+                          struct hidpp_ff_private_data *data)
+{
+       struct hidpp_report response;
        u8 feature_type;
-       u8 feature_index;
        int ret;
 
+       memset(data, 0, sizeof(*data));
+
        /* Find feature and store for later use */
        ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_G920_FORCE_FEEDBACK,
-               &feature_index, &feature_type);
+                                    &data->feature_index, &feature_type);
        if (ret)
                return ret;
 
-       ret = hidpp_ff_init(hidpp, feature_index);
+       /* Read number of slots available in device */
+       ret = hidpp_send_fap_command_sync(hidpp, data->feature_index,
+                                         HIDPP_FF_GET_INFO,
+                                         NULL, 0,
+                                         &response);
+       if (ret) {
+               if (ret < 0)
+                       return ret;
+               hid_err(hidpp->hid_dev,
+                       "%s: received protocol error 0x%02x\n", __func__, ret);
+               return -EPROTO;
+       }
+
+       data->num_effects = response.fap.params[0] - HIDPP_FF_RESERVED_SLOTS;
+
+       /* reset all forces */
+       ret = hidpp_send_fap_command_sync(hidpp, data->feature_index,
+                                         HIDPP_FF_RESET_ALL,
+                                         NULL, 0,
+                                         &response);
        if (ret)
-               hid_warn(hidpp->hid_dev, "Unable to initialize force feedback support, errno %d\n",
-                               ret);
+               hid_warn(hidpp->hid_dev, "Failed to reset all forces!\n");
 
-       return 0;
+       ret = hidpp_send_fap_command_sync(hidpp, data->feature_index,
+                                         HIDPP_FF_GET_APERTURE,
+                                         NULL, 0,
+                                         &response);
+       if (ret) {
+               hid_warn(hidpp->hid_dev,
+                        "Failed to read range from device!\n");
+       }
+       data->range = ret ?
+               900 : get_unaligned_be16(&response.fap.params[0]);
+
+       /* Read the current gain values */
+       ret = hidpp_send_fap_command_sync(hidpp, data->feature_index,
+                                         HIDPP_FF_GET_GLOBAL_GAINS,
+                                         NULL, 0,
+                                         &response);
+       if (ret)
+               hid_warn(hidpp->hid_dev,
+                        "Failed to read gain values from device!\n");
+       data->gain = ret ?
+               0xffff : get_unaligned_be16(&response.fap.params[0]);
+
+       /* ignore boost value at response.fap.params[2] */
+
+       return g920_ff_set_autocenter(hidpp, data);
 }
 
 /* -------------------------------------------------------------------------- */
@@ -3458,34 +3478,45 @@ static int hidpp_get_report_length(struct hid_device *hdev, int id)
        return report->field[0]->report_count + 1;
 }
 
-static bool hidpp_validate_report(struct hid_device *hdev, int id,
-                                 int expected_length, bool optional)
+static bool hidpp_validate_device(struct hid_device *hdev)
 {
-       int report_length;
+       struct hidpp_device *hidpp = hid_get_drvdata(hdev);
+       int id, report_length, supported_reports = 0;
 
-       if (id >= HID_MAX_IDS || id < 0) {
-               hid_err(hdev, "invalid HID report id %u\n", id);
-               return false;
+       id = REPORT_ID_HIDPP_SHORT;
+       report_length = hidpp_get_report_length(hdev, id);
+       if (report_length) {
+               if (report_length < HIDPP_REPORT_SHORT_LENGTH)
+                       goto bad_device;
+
+               supported_reports++;
        }
 
+       id = REPORT_ID_HIDPP_LONG;
        report_length = hidpp_get_report_length(hdev, id);
-       if (!report_length)
-               return optional;
+       if (report_length) {
+               if (report_length < HIDPP_REPORT_LONG_LENGTH)
+                       goto bad_device;
 
-       if (report_length < expected_length) {
-               hid_warn(hdev, "not enough values in hidpp report %d\n", id);
-               return false;
+               supported_reports++;
        }
 
-       return true;
-}
+       id = REPORT_ID_HIDPP_VERY_LONG;
+       report_length = hidpp_get_report_length(hdev, id);
+       if (report_length) {
+               if (report_length < HIDPP_REPORT_LONG_LENGTH ||
+                   report_length > HIDPP_REPORT_VERY_LONG_MAX_LENGTH)
+                       goto bad_device;
 
-static bool hidpp_validate_device(struct hid_device *hdev)
-{
-       return hidpp_validate_report(hdev, REPORT_ID_HIDPP_SHORT,
-                                    HIDPP_REPORT_SHORT_LENGTH, false) &&
-              hidpp_validate_report(hdev, REPORT_ID_HIDPP_LONG,
-                                    HIDPP_REPORT_LONG_LENGTH, true);
+               supported_reports++;
+               hidpp->very_long_report_length = report_length;
+       }
+
+       return supported_reports;
+
+bad_device:
+       hid_warn(hdev, "not enough values in hidpp report %d\n", id);
+       return false;
 }
 
 static bool hidpp_application_equals(struct hid_device *hdev,
@@ -3505,6 +3536,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
        int ret;
        bool connected;
        unsigned int connect_mask = HID_CONNECT_DEFAULT;
+       struct hidpp_ff_private_data data;
 
        /* report_fixup needs drvdata to be set before we call hid_parse */
        hidpp = devm_kzalloc(&hdev->dev, sizeof(*hidpp), GFP_KERNEL);
@@ -3531,11 +3563,6 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
                return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
        }
 
-       hidpp->very_long_report_length =
-               hidpp_get_report_length(hdev, REPORT_ID_HIDPP_VERY_LONG);
-       if (hidpp->very_long_report_length > HIDPP_REPORT_VERY_LONG_MAX_LENGTH)
-               hidpp->very_long_report_length = HIDPP_REPORT_VERY_LONG_MAX_LENGTH;
-
        if (id->group == HID_GROUP_LOGITECH_DJ_DEVICE)
                hidpp->quirks |= HIDPP_QUIRK_UNIFYING;
 
@@ -3614,7 +3641,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
                if (ret)
                        goto hid_hw_init_fail;
        } else if (connected && (hidpp->quirks & HIDPP_QUIRK_CLASS_G920)) {
-               ret = g920_get_config(hidpp);
+               ret = g920_get_config(hidpp, &data);
                if (ret)
                        goto hid_hw_init_fail;
        }
@@ -3636,6 +3663,14 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
                goto hid_hw_start_fail;
        }
 
+       if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
+               ret = hidpp_ff_init(hidpp, &data);
+               if (ret)
+                       hid_warn(hidpp->hid_dev,
+                    "Unable to initialize force feedback support, errno %d\n",
+                                ret);
+       }
+
        return ret;
 
 hid_hw_init_fail:
@@ -3658,9 +3693,6 @@ static void hidpp_remove(struct hid_device *hdev)
 
        sysfs_remove_group(&hdev->dev.kobj, &ps_attribute_group);
 
-       if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920)
-               hidpp_ff_deinit(hdev);
-
        hid_hw_stop(hdev);
        cancel_work_sync(&hidpp->work);
        mutex_destroy(&hidpp->send_mutex);
index 2cf83856f2e41c7e6c1456224988eaaa6a370e0f..2d8b589201a4e80c7d2dc7c4a6df35344840bd9a 100644 (file)
@@ -328,11 +328,17 @@ static int ms_play_effect(struct input_dev *dev, void *data,
 
 static int ms_init_ff(struct hid_device *hdev)
 {
-       struct hid_input *hidinput = list_entry(hdev->inputs.next,
-                                               struct hid_input, list);
-       struct input_dev *input_dev = hidinput->input;
+       struct hid_input *hidinput;
+       struct input_dev *input_dev;
        struct ms_data *ms = hid_get_drvdata(hdev);
 
+       if (list_empty(&hdev->inputs)) {
+               hid_err(hdev, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
+       input_dev = hidinput->input;
+
        if (!(ms->quirks & MS_QUIRK_FF))
                return 0;
 
index 5a3b3d974d849c28503f6f6390312384d6e1868f..2666af02d5c1a11f1a32f098eecb61ddc458cf0a 100644 (file)
@@ -516,7 +516,7 @@ static void pcmidi_setup_extra_keys(
                MY PICTURES =>  KEY_WORDPROCESSOR
                MY MUSIC=>      KEY_SPREADSHEET
        */
-       unsigned int keys[] = {
+       static const unsigned int keys[] = {
                KEY_FN,
                KEY_MESSENGER, KEY_CALENDAR,
                KEY_ADDRESSBOOK, KEY_DOCUMENTS,
@@ -532,7 +532,7 @@ static void pcmidi_setup_extra_keys(
                0
        };
 
-       unsigned int *pkeys = &keys[0];
+       const unsigned int *pkeys = &keys[0];
        unsigned short i;
 
        if (pm->ifnum != 1)  /* only set up ONCE for interace 1 */
index 73c0f7a95e2dcea13d10b37176c9d7678074af1c..4c6ed6ef31f1e731be29d06239fe972cc2e4eb4b 100644 (file)
@@ -2254,9 +2254,15 @@ static int sony_play_effect(struct input_dev *dev, void *data,
 
 static int sony_init_ff(struct sony_sc *sc)
 {
-       struct hid_input *hidinput = list_entry(sc->hdev->inputs.next,
-                                               struct hid_input, list);
-       struct input_dev *input_dev = hidinput->input;
+       struct hid_input *hidinput;
+       struct input_dev *input_dev;
+
+       if (list_empty(&sc->hdev->inputs)) {
+               hid_err(sc->hdev, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_entry(sc->hdev->inputs.next, struct hid_input, list);
+       input_dev = hidinput->input;
 
        input_set_capability(input_dev, EV_FF, FF_RUMBLE);
        return input_ff_create_memless(input_dev, NULL, sony_play_effect);
index bdfc5ff3b2c5c9211291f71d8f0304e233f076bd..90acef3045369e15f72abd7c72580952f080c518 100644 (file)
@@ -124,12 +124,18 @@ static int tmff_init(struct hid_device *hid, const signed short *ff_bits)
        struct tmff_device *tmff;
        struct hid_report *report;
        struct list_head *report_list;
-       struct hid_input *hidinput = list_entry(hid->inputs.next,
-                                                       struct hid_input, list);
-       struct input_dev *input_dev = hidinput->input;
+       struct hid_input *hidinput;
+       struct input_dev *input_dev;
        int error;
        int i;
 
+       if (list_empty(&hid->inputs)) {
+               hid_err(hid, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+       input_dev = hidinput->input;
+
        tmff = kzalloc(sizeof(struct tmff_device), GFP_KERNEL);
        if (!tmff)
                return -ENOMEM;
index f90959e940287912e7b64ceed1eb2424f484455d..3abaca045869b0943d179a1af61be564ebdba299 100644 (file)
@@ -54,11 +54,17 @@ static int zpff_init(struct hid_device *hid)
 {
        struct zpff_device *zpff;
        struct hid_report *report;
-       struct hid_input *hidinput = list_entry(hid->inputs.next,
-                                               struct hid_input, list);
-       struct input_dev *dev = hidinput->input;
+       struct hid_input *hidinput;
+       struct input_dev *dev;
        int i, error;
 
+       if (list_empty(&hid->inputs)) {
+               hid_err(hid, "no inputs found\n");
+               return -ENODEV;
+       }
+       hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+       dev = hidinput->input;
+
        for (i = 0; i < 4; i++) {
                report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, i, 1);
                if (!report)
index 2a7c6e33bb1c4322b6851e42988f593e69ae527f..04c088131e044bc649bbe7b414bb892bd01fe2b0 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/pm.h>
-#include <linux/pm_runtime.h>
 #include <linux/device.h>
 #include <linux/wait.h>
 #include <linux/err.h>
@@ -48,8 +47,6 @@
 /* quirks to control the device */
 #define I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV       BIT(0)
 #define I2C_HID_QUIRK_NO_IRQ_AFTER_RESET       BIT(1)
-#define I2C_HID_QUIRK_NO_RUNTIME_PM            BIT(2)
-#define I2C_HID_QUIRK_DELAY_AFTER_SLEEP                BIT(3)
 #define I2C_HID_QUIRK_BOGUS_IRQ                        BIT(4)
 
 /* flags */
@@ -172,14 +169,7 @@ static const struct i2c_hid_quirks {
        { USB_VENDOR_ID_WEIDA, HID_ANY_ID,
                I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV },
        { I2C_VENDOR_ID_HANTICK, I2C_PRODUCT_ID_HANTICK_5288,
-               I2C_HID_QUIRK_NO_IRQ_AFTER_RESET |
-               I2C_HID_QUIRK_NO_RUNTIME_PM },
-       { I2C_VENDOR_ID_RAYDIUM, I2C_PRODUCT_ID_RAYDIUM_4B33,
-               I2C_HID_QUIRK_DELAY_AFTER_SLEEP },
-       { USB_VENDOR_ID_LG, I2C_DEVICE_ID_LG_8001,
-               I2C_HID_QUIRK_NO_RUNTIME_PM },
-       { I2C_VENDOR_ID_GOODIX, I2C_DEVICE_ID_GOODIX_01F0,
-               I2C_HID_QUIRK_NO_RUNTIME_PM },
+               I2C_HID_QUIRK_NO_IRQ_AFTER_RESET },
        { USB_VENDOR_ID_ELAN, HID_ANY_ID,
                 I2C_HID_QUIRK_BOGUS_IRQ },
        { 0, 0 }
@@ -397,7 +387,6 @@ static int i2c_hid_set_power(struct i2c_client *client, int power_state)
 {
        struct i2c_hid *ihid = i2c_get_clientdata(client);
        int ret;
-       unsigned long now, delay;
 
        i2c_hid_dbg(ihid, "%s\n", __func__);
 
@@ -415,22 +404,9 @@ static int i2c_hid_set_power(struct i2c_client *client, int power_state)
                        goto set_pwr_exit;
        }
 
-       if (ihid->quirks & I2C_HID_QUIRK_DELAY_AFTER_SLEEP &&
-           power_state == I2C_HID_PWR_ON) {
-               now = jiffies;
-               if (time_after(ihid->sleep_delay, now)) {
-                       delay = jiffies_to_usecs(ihid->sleep_delay - now);
-                       usleep_range(delay, delay + 1);
-               }
-       }
-
        ret = __i2c_hid_command(client, &hid_set_power_cmd, power_state,
                0, NULL, 0, NULL, 0);
 
-       if (ihid->quirks & I2C_HID_QUIRK_DELAY_AFTER_SLEEP &&
-           power_state == I2C_HID_PWR_SLEEP)
-               ihid->sleep_delay = jiffies + msecs_to_jiffies(20);
-
        if (ret)
                dev_err(&client->dev, "failed to change power setting.\n");
 
@@ -471,8 +447,12 @@ static int i2c_hid_hwreset(struct i2c_client *client)
        if (ret) {
                dev_err(&client->dev, "failed to reset device.\n");
                i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
+               goto out_unlock;
        }
 
+       /* At least some SIS devices need this after reset */
+       ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
+
 out_unlock:
        mutex_unlock(&ihid->reset_lock);
        return ret;
@@ -791,11 +771,6 @@ static int i2c_hid_open(struct hid_device *hid)
 {
        struct i2c_client *client = hid->driver_data;
        struct i2c_hid *ihid = i2c_get_clientdata(client);
-       int ret = 0;
-
-       ret = pm_runtime_get_sync(&client->dev);
-       if (ret < 0)
-               return ret;
 
        set_bit(I2C_HID_STARTED, &ihid->flags);
        return 0;
@@ -807,27 +782,6 @@ static void i2c_hid_close(struct hid_device *hid)
        struct i2c_hid *ihid = i2c_get_clientdata(client);
 
        clear_bit(I2C_HID_STARTED, &ihid->flags);
-
-       /* Save some power */
-       pm_runtime_put(&client->dev);
-}
-
-static int i2c_hid_power(struct hid_device *hid, int lvl)
-{
-       struct i2c_client *client = hid->driver_data;
-       struct i2c_hid *ihid = i2c_get_clientdata(client);
-
-       i2c_hid_dbg(ihid, "%s lvl:%d\n", __func__, lvl);
-
-       switch (lvl) {
-       case PM_HINT_FULLON:
-               pm_runtime_get_sync(&client->dev);
-               break;
-       case PM_HINT_NORMAL:
-               pm_runtime_put(&client->dev);
-               break;
-       }
-       return 0;
 }
 
 struct hid_ll_driver i2c_hid_ll_driver = {
@@ -836,7 +790,6 @@ struct hid_ll_driver i2c_hid_ll_driver = {
        .stop = i2c_hid_stop,
        .open = i2c_hid_open,
        .close = i2c_hid_close,
-       .power = i2c_hid_power,
        .output_report = i2c_hid_output_report,
        .raw_request = i2c_hid_raw_request,
 };
@@ -1104,9 +1057,6 @@ static int i2c_hid_probe(struct i2c_client *client,
 
        i2c_hid_acpi_fix_up_power(&client->dev);
 
-       pm_runtime_get_noresume(&client->dev);
-       pm_runtime_set_active(&client->dev);
-       pm_runtime_enable(&client->dev);
        device_enable_async_suspend(&client->dev);
 
        /* Make sure there is something at this address */
@@ -1114,16 +1064,16 @@ static int i2c_hid_probe(struct i2c_client *client,
        if (ret < 0) {
                dev_dbg(&client->dev, "nothing at this address: %d\n", ret);
                ret = -ENXIO;
-               goto err_pm;
+               goto err_regulator;
        }
 
        ret = i2c_hid_fetch_hid_descriptor(ihid);
        if (ret < 0)
-               goto err_pm;
+               goto err_regulator;
 
        ret = i2c_hid_init_irq(client);
        if (ret < 0)
-               goto err_pm;
+               goto err_regulator;
 
        hid = hid_allocate_device();
        if (IS_ERR(hid)) {
@@ -1154,9 +1104,6 @@ static int i2c_hid_probe(struct i2c_client *client,
                goto err_mem_free;
        }
 
-       if (!(ihid->quirks & I2C_HID_QUIRK_NO_RUNTIME_PM))
-               pm_runtime_put(&client->dev);
-
        return 0;
 
 err_mem_free:
@@ -1165,10 +1112,6 @@ err_mem_free:
 err_irq:
        free_irq(client->irq, ihid);
 
-err_pm:
-       pm_runtime_put_noidle(&client->dev);
-       pm_runtime_disable(&client->dev);
-
 err_regulator:
        regulator_bulk_disable(ARRAY_SIZE(ihid->pdata.supplies),
                               ihid->pdata.supplies);
@@ -1181,12 +1124,6 @@ static int i2c_hid_remove(struct i2c_client *client)
        struct i2c_hid *ihid = i2c_get_clientdata(client);
        struct hid_device *hid;
 
-       if (!(ihid->quirks & I2C_HID_QUIRK_NO_RUNTIME_PM))
-               pm_runtime_get_sync(&client->dev);
-       pm_runtime_disable(&client->dev);
-       pm_runtime_set_suspended(&client->dev);
-       pm_runtime_put_noidle(&client->dev);
-
        hid = ihid->hid;
        hid_destroy_device(hid);
 
@@ -1219,25 +1156,15 @@ static int i2c_hid_suspend(struct device *dev)
        int wake_status;
 
        if (hid->driver && hid->driver->suspend) {
-               /*
-                * Wake up the device so that IO issues in
-                * HID driver's suspend code can succeed.
-                */
-               ret = pm_runtime_resume(dev);
-               if (ret < 0)
-                       return ret;
-
                ret = hid->driver->suspend(hid, PMSG_SUSPEND);
                if (ret < 0)
                        return ret;
        }
 
-       if (!pm_runtime_suspended(dev)) {
-               /* Save some power */
-               i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
+       /* Save some power */
+       i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
 
-               disable_irq(client->irq);
-       }
+       disable_irq(client->irq);
 
        if (device_may_wakeup(&client->dev)) {
                wake_status = enable_irq_wake(client->irq);
@@ -1279,11 +1206,6 @@ static int i2c_hid_resume(struct device *dev)
                                wake_status);
        }
 
-       /* We'll resume to full power */
-       pm_runtime_disable(dev);
-       pm_runtime_set_active(dev);
-       pm_runtime_enable(dev);
-
        enable_irq(client->irq);
 
        /* Instead of resetting device, simply powers the device on. This
@@ -1304,30 +1226,8 @@ static int i2c_hid_resume(struct device *dev)
 }
 #endif
 
-#ifdef CONFIG_PM
-static int i2c_hid_runtime_suspend(struct device *dev)
-{
-       struct i2c_client *client = to_i2c_client(dev);
-
-       i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
-       disable_irq(client->irq);
-       return 0;
-}
-
-static int i2c_hid_runtime_resume(struct device *dev)
-{
-       struct i2c_client *client = to_i2c_client(dev);
-
-       enable_irq(client->irq);
-       i2c_hid_set_power(client, I2C_HID_PWR_ON);
-       return 0;
-}
-#endif
-
 static const struct dev_pm_ops i2c_hid_pm = {
        SET_SYSTEM_SLEEP_PM_OPS(i2c_hid_suspend, i2c_hid_resume)
-       SET_RUNTIME_PM_OPS(i2c_hid_runtime_suspend, i2c_hid_runtime_resume,
-                          NULL)
 };
 
 static const struct i2c_device_id i2c_hid_id_table[] = {
index 75078c83be1af579c9e7ad804271d620d3849dc2..d31ea82b84c173033dd1a6582122ec9197671fbc 100644 (file)
@@ -322,6 +322,25 @@ static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = {
                },
                .driver_data = (void *)&sipodev_desc
        },
+       {
+               /*
+                * There are at least 2 Primebook C11B versions, the older
+                * version has a product-name of "Primebook C11B", and a
+                * bios version / release / firmware revision of:
+                * V2.1.2 / 05/03/2018 / 18.2
+                * The new version has "PRIMEBOOK C11B" as product-name and a
+                * bios version / release / firmware revision of:
+                * CFALKSW05_BIOS_V1.1.2 / 11/19/2018 / 19.2
+                * Only the older version needs this quirk, note the newer
+                * version will not match as it has a different product-name.
+                */
+               .ident = "Trekstor Primebook C11B",
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Primebook C11B"),
+               },
+               .driver_data = (void *)&sipodev_desc
+       },
        {
                .ident = "Direkt-Tek DTLAPY116-2",
                .matches = {
index 1b0a0cc605e7740d07d8e0fd8c976105abdfae2e..513d7a4a1b8acd176a673375d6f594c3820e116a 100644 (file)
@@ -84,7 +84,7 @@ int ishtp_cl_alloc_tx_ring(struct ishtp_cl *cl)
        return  0;
 out:
        dev_err(&cl->device->dev, "error in allocating Tx pool\n");
-       ishtp_cl_free_rx_ring(cl);
+       ishtp_cl_free_tx_ring(cl);
        return  -ENOMEM;
 }
 
index 4a7f8d363220dc1cd507e0476edc92a7d7724ad9..203d27d198b818a364c2614097fb62f3748f0d21 100644 (file)
@@ -202,6 +202,21 @@ static inline void wacom_schedule_work(struct wacom_wac *wacom_wac,
        }
 }
 
+/*
+ * Convert a signed 32-bit integer to an unsigned n-bit integer. Undoes
+ * the normally-helpful work of 'hid_snto32' for fields that use signed
+ * ranges for questionable reasons.
+ */
+static inline __u32 wacom_s32tou(s32 value, __u8 n)
+{
+       switch (n) {
+       case 8:  return ((__u8)value);
+       case 16: return ((__u16)value);
+       case 32: return ((__u32)value);
+       }
+       return value & (1 << (n - 1)) ? value & (~(~0U << n)) : value;
+}
+
 extern const struct hid_device_id wacom_ids[];
 
 void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len);
index 2b0a5b8ca6e692850aa71ab21c3663fc5b56041b..ccb74529bc78243689d0720bbe2d81cfd8a52004 100644 (file)
@@ -2303,7 +2303,7 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
        case HID_DG_TOOLSERIALNUMBER:
                if (value) {
                        wacom_wac->serial[0] = (wacom_wac->serial[0] & ~0xFFFFFFFFULL);
-                       wacom_wac->serial[0] |= (__u32)value;
+                       wacom_wac->serial[0] |= wacom_s32tou(value, field->report_size);
                }
                return;
        case HID_DG_TWIST:
@@ -2319,15 +2319,17 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
                return;
        case WACOM_HID_WD_SERIALHI:
                if (value) {
+                       __u32 raw_value = wacom_s32tou(value, field->report_size);
+
                        wacom_wac->serial[0] = (wacom_wac->serial[0] & 0xFFFFFFFF);
-                       wacom_wac->serial[0] |= ((__u64)value) << 32;
+                       wacom_wac->serial[0] |= ((__u64)raw_value) << 32;
                        /*
                         * Non-USI EMR devices may contain additional tool type
                         * information here. See WACOM_HID_WD_TOOLTYPE case for
                         * more details.
                         */
                        if (value >> 20 == 1) {
-                               wacom_wac->id[0] |= value & 0xFFFFF;
+                               wacom_wac->id[0] |= raw_value & 0xFFFFF;
                        }
                }
                return;
@@ -2339,7 +2341,7 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
                 * bitwise OR so the complete value can be built
                 * up over time :(
                 */
-               wacom_wac->id[0] |= value;
+               wacom_wac->id[0] |= wacom_s32tou(value, field->report_size);
                return;
        case WACOM_HID_WD_OFFSETLEFT:
                if (features->offset_left && value != features->offset_left)
index 0037e2bdacd6b25ea2edca74fa7d11b542e0b843..8a51dcf055eab73222c828a64ba7c4a5b743aefb 100644 (file)
@@ -170,7 +170,7 @@ static inline int ina3221_wait_for_data(struct ina3221_data *ina)
 
        /* Polling the CVRF bit to make sure read data is ready */
        return regmap_field_read_poll_timeout(ina->fields[F_CVRF],
-                                             cvrf, cvrf, wait, 100000);
+                                             cvrf, cvrf, wait, wait * 2);
 }
 
 static int ina3221_read_value(struct ina3221_data *ina, unsigned int reg,
index b26419dbe840cb467ba487f88dd630e118e0e103..281c81edabc65740df60c154b4b1e59c4c995fc7 100644 (file)
 #define FANCTL1_FMR_REG                0x00    /* Bank 3; 1 reg per channel */
 #define FANCTL1_OUT_REG                0x10    /* Bank 3; 1 reg per channel */
 
+#define VOLT_MONITOR_MODE      0x0
+#define THERMAL_DIODE_MODE     0x1
+#define THERMISTOR_MODE                0x3
+
 #define ENABLE_TSI     BIT(1)
 
 static const unsigned short normal_i2c[] = {
@@ -935,11 +939,16 @@ static int nct7904_probe(struct i2c_client *client,
        for (i = 0; i < 4; i++) {
                val = (ret >> (i * 2)) & 0x03;
                bit = (1 << i);
-               if (val == 0) {
+               if (val == VOLT_MONITOR_MODE) {
                        data->tcpu_mask &= ~bit;
+               } else if (val == THERMAL_DIODE_MODE && i < 2) {
+                       data->temp_mode |= bit;
+                       data->vsen_mask &= ~(0x06 << (i * 2));
+               } else if (val == THERMISTOR_MODE) {
+                       data->vsen_mask &= ~(0x02 << (i * 2));
                } else {
-                       if (val == 0x1 || val == 0x2)
-                               data->temp_mode |= bit;
+                       /* Reserved */
+                       data->tcpu_mask &= ~bit;
                        data->vsen_mask &= ~(0x06 << (i * 2));
                }
        }
index fa9d34af87acc0de4d14276a6a037234f0ae7218..f72803a0239109a4c0249f27f45d26247948edbe 100644 (file)
@@ -626,6 +626,9 @@ static void intel_th_gth_switch(struct intel_th_device *thdev,
        if (!count)
                dev_dbg(&thdev->dev, "timeout waiting for CTS Trigger\n");
 
+       /* De-assert the trigger */
+       iowrite32(0, gth->base + REG_CTS_CTL);
+
        intel_th_gth_stop(gth, output, false);
        intel_th_gth_start(gth, output);
 }
index fc9f15f36ad4e1a460f9a7f6aeb49a2e861d36a3..6d240dfae9d9059f68737065e654bc8d369a6836 100644 (file)
@@ -164,7 +164,7 @@ struct msc {
 };
 
 static LIST_HEAD(msu_buffer_list);
-static struct mutex msu_buffer_mutex;
+static DEFINE_MUTEX(msu_buffer_mutex);
 
 /**
  * struct msu_buffer_entry - internal MSU buffer bookkeeping
@@ -327,7 +327,7 @@ static size_t msc_win_total_sz(struct msc_window *win)
                struct msc_block_desc *bdesc = sg_virt(sg);
 
                if (msc_block_wrapped(bdesc))
-                       return win->nr_blocks << PAGE_SHIFT;
+                       return (size_t)win->nr_blocks << PAGE_SHIFT;
 
                size += msc_total_sz(bdesc);
                if (msc_block_last_written(bdesc))
@@ -1848,9 +1848,14 @@ mode_store(struct device *dev, struct device_attribute *attr, const char *buf,
                len = cp - buf;
 
        mode = kstrndup(buf, len, GFP_KERNEL);
+       if (!mode)
+               return -ENOMEM;
+
        i = match_string(msc_mode, ARRAY_SIZE(msc_mode), mode);
-       if (i >= 0)
+       if (i >= 0) {
+               kfree(mode);
                goto found;
+       }
 
        /* Buffer sinks only work with a usable IRQ */
        if (!msc->do_irq) {
index 91dfeba624855b32b3c3c43a2ad276ea87c294da..03ca5b1bef9f4e586257001bf828b125cb3cf3b1 100644 (file)
@@ -199,6 +199,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x02a6),
                .driver_data = (kernel_ulong_t)&intel_th_2x,
        },
+       {
+               /* Comet Lake PCH */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x06a6),
+               .driver_data = (kernel_ulong_t)&intel_th_2x,
+       },
        {
                /* Ice Lake NNPI */
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x45c5),
@@ -209,6 +214,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa0a6),
                .driver_data = (kernel_ulong_t)&intel_th_2x,
        },
+       {
+               /* Jasper Lake PCH */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4da6),
+               .driver_data = (kernel_ulong_t)&intel_th_2x,
+       },
        { 0 },
 };
 
index fa66951b05d06670ffdb79ff7b1532574177594a..7b098ff5f5dd34b5bc9e8a0553a5afcd84b722a3 100644 (file)
 #define ASPEED_I2CD_S_TX_CMD                           BIT(2)
 #define ASPEED_I2CD_M_TX_CMD                           BIT(1)
 #define ASPEED_I2CD_M_START_CMD                                BIT(0)
+#define ASPEED_I2CD_MASTER_CMDS_MASK                                          \
+               (ASPEED_I2CD_M_STOP_CMD |                                      \
+                ASPEED_I2CD_M_S_RX_CMD_LAST |                                 \
+                ASPEED_I2CD_M_RX_CMD |                                        \
+                ASPEED_I2CD_M_TX_CMD |                                        \
+                ASPEED_I2CD_M_START_CMD)
 
 /* 0x18 : I2CD Slave Device Address Register   */
 #define ASPEED_I2CD_DEV_ADDR_MASK                      GENMASK(6, 0)
@@ -336,18 +342,19 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus)
        struct i2c_msg *msg = &bus->msgs[bus->msgs_index];
        u8 slave_addr = i2c_8bit_addr_from_msg(msg);
 
-       bus->master_state = ASPEED_I2C_MASTER_START;
-
 #if IS_ENABLED(CONFIG_I2C_SLAVE)
        /*
         * If it's requested in the middle of a slave session, set the master
         * state to 'pending' then H/W will continue handling this master
         * command when the bus comes back to the idle state.
         */
-       if (bus->slave_state != ASPEED_I2C_SLAVE_INACTIVE)
+       if (bus->slave_state != ASPEED_I2C_SLAVE_INACTIVE) {
                bus->master_state = ASPEED_I2C_MASTER_PENDING;
+               return;
+       }
 #endif /* CONFIG_I2C_SLAVE */
 
+       bus->master_state = ASPEED_I2C_MASTER_START;
        bus->buf_index = 0;
 
        if (msg->flags & I2C_M_RD) {
@@ -422,20 +429,6 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
                }
        }
 
-#if IS_ENABLED(CONFIG_I2C_SLAVE)
-       /*
-        * A pending master command will be started by H/W when the bus comes
-        * back to idle state after completing a slave operation so change the
-        * master state from 'pending' to 'start' at here if slave is inactive.
-        */
-       if (bus->master_state == ASPEED_I2C_MASTER_PENDING) {
-               if (bus->slave_state != ASPEED_I2C_SLAVE_INACTIVE)
-                       goto out_no_complete;
-
-               bus->master_state = ASPEED_I2C_MASTER_START;
-       }
-#endif /* CONFIG_I2C_SLAVE */
-
        /* Master is not currently active, irq was for someone else. */
        if (bus->master_state == ASPEED_I2C_MASTER_INACTIVE ||
            bus->master_state == ASPEED_I2C_MASTER_PENDING)
@@ -462,11 +455,15 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
 #if IS_ENABLED(CONFIG_I2C_SLAVE)
                /*
                 * If a peer master starts a xfer immediately after it queues a
-                * master command, change its state to 'pending' then H/W will
-                * continue the queued master xfer just after completing the
-                * slave mode session.
+                * master command, clear the queued master command and change
+                * its state to 'pending'. To simplify handling of pending
+                * cases, it uses S/W solution instead of H/W command queue
+                * handling.
                 */
                if (unlikely(irq_status & ASPEED_I2CD_INTR_SLAVE_MATCH)) {
+                       writel(readl(bus->base + ASPEED_I2C_CMD_REG) &
+                               ~ASPEED_I2CD_MASTER_CMDS_MASK,
+                              bus->base + ASPEED_I2C_CMD_REG);
                        bus->master_state = ASPEED_I2C_MASTER_PENDING;
                        dev_dbg(bus->dev,
                                "master goes pending due to a slave start\n");
@@ -629,6 +626,14 @@ static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id)
                        irq_handled |= aspeed_i2c_master_irq(bus,
                                                             irq_remaining);
        }
+
+       /*
+        * Start a pending master command at here if a slave operation is
+        * completed.
+        */
+       if (bus->master_state == ASPEED_I2C_MASTER_PENDING &&
+           bus->slave_state == ASPEED_I2C_SLAVE_INACTIVE)
+               aspeed_i2c_do_start(bus);
 #else
        irq_handled = aspeed_i2c_master_irq(bus, irq_remaining);
 #endif /* CONFIG_I2C_SLAVE */
@@ -691,6 +696,15 @@ static int aspeed_i2c_master_xfer(struct i2c_adapter *adap,
                     ASPEED_I2CD_BUS_BUSY_STS))
                        aspeed_i2c_recover_bus(bus);
 
+               /*
+                * If timed out and the state is still pending, drop the pending
+                * master command.
+                */
+               spin_lock_irqsave(&bus->lock, flags);
+               if (bus->master_state == ASPEED_I2C_MASTER_PENDING)
+                       bus->master_state = ASPEED_I2C_MASTER_INACTIVE;
+               spin_unlock_irqrestore(&bus->lock, flags);
+
                return -ETIMEDOUT;
        }
 
index 29eae1bf4f861a39078091644aa329326aa1c2ed..2152ec5f535c19316b0d7800afbf1bd3a44e5768 100644 (file)
@@ -875,7 +875,7 @@ static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id)
 
 static u32 mtk_i2c_functionality(struct i2c_adapter *adap)
 {
-       if (adap->quirks->flags & I2C_AQ_NO_ZERO_LEN)
+       if (i2c_check_quirks(adap, I2C_AQ_NO_ZERO_LEN))
                return I2C_FUNC_I2C |
                        (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
        else
index d36cf08461f76d78edaff2250b21324b2996775c..b24e7b937f210bbb9fc5279f386c1f0e6044f528 100644 (file)
@@ -305,7 +305,7 @@ struct stm32f7_i2c_dev {
        struct regmap *regmap;
 };
 
-/**
+/*
  * All these values are coming from I2C Specification, Version 6.0, 4th of
  * April 2014.
  *
@@ -1192,6 +1192,8 @@ static void stm32f7_i2c_slave_start(struct stm32f7_i2c_dev *i2c_dev)
                        STM32F7_I2C_CR1_TXIE;
                stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, mask);
 
+               /* Write 1st data byte */
+               writel_relaxed(value, base + STM32F7_I2C_TXDR);
        } else {
                /* Notify i2c slave that new write transfer is starting */
                i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &value);
@@ -1501,7 +1503,7 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data)
        void __iomem *base = i2c_dev->base;
        struct device *dev = i2c_dev->dev;
        struct stm32_i2c_dma *dma = i2c_dev->dma;
-       u32 mask, status;
+       u32 status;
 
        status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
 
@@ -1526,12 +1528,15 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data)
                f7_msg->result = -EINVAL;
        }
 
-       /* Disable interrupts */
-       if (stm32f7_i2c_is_slave_registered(i2c_dev))
-               mask = STM32F7_I2C_XFER_IRQ_MASK;
-       else
-               mask = STM32F7_I2C_ALL_IRQ_MASK;
-       stm32f7_i2c_disable_irq(i2c_dev, mask);
+       if (!i2c_dev->slave_running) {
+               u32 mask;
+               /* Disable interrupts */
+               if (stm32f7_i2c_is_slave_registered(i2c_dev))
+                       mask = STM32F7_I2C_XFER_IRQ_MASK;
+               else
+                       mask = STM32F7_I2C_ALL_IRQ_MASK;
+               stm32f7_i2c_disable_irq(i2c_dev, mask);
+       }
 
        /* Disable dma */
        if (i2c_dev->use_dma) {
index 663f8a5012d64123b06a646887c4c75a5f9860e1..73aee5949b6b3cc17cd3b1543a33a23f29c188b3 100644 (file)
@@ -1399,7 +1399,7 @@ static int stm32_adc_dma_start(struct iio_dev *indio_dev)
        cookie = dmaengine_submit(desc);
        ret = dma_submit_error(cookie);
        if (ret) {
-               dmaengine_terminate_all(adc->dma_chan);
+               dmaengine_terminate_sync(adc->dma_chan);
                return ret;
        }
 
@@ -1477,7 +1477,7 @@ static void __stm32_adc_buffer_predisable(struct iio_dev *indio_dev)
                stm32_adc_conv_irq_disable(adc);
 
        if (adc->dma_chan)
-               dmaengine_terminate_all(adc->dma_chan);
+               dmaengine_terminate_sync(adc->dma_chan);
 
        if (stm32_adc_set_trig(indio_dev, NULL))
                dev_err(&indio_dev->dev, "Can't clear trigger\n");
index b99d73887c9f3cd6c74e39cc6acd710663f58821..8743b2f376e277aa34ccefdb5979968d1db32f3a 100644 (file)
@@ -317,8 +317,11 @@ static int adis16480_set_freq(struct iio_dev *indio_dev, int val, int val2)
        struct adis16480 *st = iio_priv(indio_dev);
        unsigned int t, reg;
 
+       if (val < 0 || val2 < 0)
+               return -EINVAL;
+
        t =  val * 1000 + val2 / 1000;
-       if (t <= 0)
+       if (t == 0)
                return -EINVAL;
 
        /*
index b17f060b52fc7ba39f2dc2eb3f7ea7b545beee14..868281b8adb08619c40fc735daacb658e0feca84 100644 (file)
@@ -114,54 +114,63 @@ static const struct inv_mpu6050_hw hw_info[] = {
                .name = "MPU6050",
                .reg = &reg_set_6050,
                .config = &chip_config_6050,
+               .fifo_size = 1024,
        },
        {
                .whoami = INV_MPU6500_WHOAMI_VALUE,
                .name = "MPU6500",
                .reg = &reg_set_6500,
                .config = &chip_config_6050,
+               .fifo_size = 512,
        },
        {
                .whoami = INV_MPU6515_WHOAMI_VALUE,
                .name = "MPU6515",
                .reg = &reg_set_6500,
                .config = &chip_config_6050,
+               .fifo_size = 512,
        },
        {
                .whoami = INV_MPU6000_WHOAMI_VALUE,
                .name = "MPU6000",
                .reg = &reg_set_6050,
                .config = &chip_config_6050,
+               .fifo_size = 1024,
        },
        {
                .whoami = INV_MPU9150_WHOAMI_VALUE,
                .name = "MPU9150",
                .reg = &reg_set_6050,
                .config = &chip_config_6050,
+               .fifo_size = 1024,
        },
        {
                .whoami = INV_MPU9250_WHOAMI_VALUE,
                .name = "MPU9250",
                .reg = &reg_set_6500,
                .config = &chip_config_6050,
+               .fifo_size = 512,
        },
        {
                .whoami = INV_MPU9255_WHOAMI_VALUE,
                .name = "MPU9255",
                .reg = &reg_set_6500,
                .config = &chip_config_6050,
+               .fifo_size = 512,
        },
        {
                .whoami = INV_ICM20608_WHOAMI_VALUE,
                .name = "ICM20608",
                .reg = &reg_set_6500,
                .config = &chip_config_6050,
+               .fifo_size = 512,
        },
        {
                .whoami = INV_ICM20602_WHOAMI_VALUE,
                .name = "ICM20602",
                .reg = &reg_set_icm20602,
                .config = &chip_config_6050,
+               .fifo_size = 1008,
        },
 };
 
index db1c6904388b67f2e39cbccf85f1315caaa61d73..51235677c5345037e789552d1116d83ba8a6af1b 100644 (file)
@@ -100,12 +100,14 @@ struct inv_mpu6050_chip_config {
  *  @name:      name of the chip.
  *  @reg:   register map of the chip.
  *  @config:    configuration of the chip.
+ *  @fifo_size:        size of the FIFO in bytes.
  */
 struct inv_mpu6050_hw {
        u8 whoami;
        u8 *name;
        const struct inv_mpu6050_reg_map *reg;
        const struct inv_mpu6050_chip_config *config;
+       size_t fifo_size;
 };
 
 /*
index 5f9a5de0bab44abe645598fd7bf6beba6a6a98e4..72d8c5790076ab47d4d6ade247566b3fd231323e 100644 (file)
@@ -180,9 +180,6 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
                        "failed to ack interrupt\n");
                goto flush_fifo;
        }
-       /* handle fifo overflow by reseting fifo */
-       if (int_status & INV_MPU6050_BIT_FIFO_OVERFLOW_INT)
-               goto flush_fifo;
        if (!(int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT)) {
                dev_warn(regmap_get_device(st->map),
                        "spurious interrupt with status 0x%x\n", int_status);
@@ -211,6 +208,18 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
        if (result)
                goto end_session;
        fifo_count = get_unaligned_be16(&data[0]);
+
+       /*
+        * Handle fifo overflow by resetting fifo.
+        * Reset if there is only 3 data set free remaining to mitigate
+        * possible delay between reading fifo count and fifo data.
+        */
+       nb = 3 * bytes_per_datum;
+       if (fifo_count >= st->hw->fifo_size - nb) {
+               dev_warn(regmap_get_device(st->map), "fifo overflow reset\n");
+               goto flush_fifo;
+       }
+
        /* compute and process all complete datum */
        nb = fifo_count / bytes_per_datum;
        inv_mpu6050_update_period(st, pf->timestamp, nb);
index 8b50d56b0a03a23faf53421f21198a4411545737..01eb8cc63076f32a18b4a19061252e33796e0d0a 100644 (file)
@@ -110,7 +110,7 @@ static int srf04_read(struct srf04_data *data)
        udelay(data->cfg->trigger_pulse_us);
        gpiod_set_value(data->gpiod_trig, 0);
 
-       /* it cannot take more than 20 ms */
+       /* it should not take more than 20 ms until echo is rising */
        ret = wait_for_completion_killable_timeout(&data->rising, HZ/50);
        if (ret < 0) {
                mutex_unlock(&data->lock);
@@ -120,7 +120,8 @@ static int srf04_read(struct srf04_data *data)
                return -ETIMEDOUT;
        }
 
-       ret = wait_for_completion_killable_timeout(&data->falling, HZ/50);
+       /* it cannot take more than 50 ms until echo is falling */
+       ret = wait_for_completion_killable_timeout(&data->falling, HZ/20);
        if (ret < 0) {
                mutex_unlock(&data->lock);
                return ret;
@@ -135,19 +136,19 @@ static int srf04_read(struct srf04_data *data)
 
        dt_ns = ktime_to_ns(ktime_dt);
        /*
-        * measuring more than 3 meters is beyond the capabilities of
-        * the sensor
+        * measuring more than 6,45 meters is beyond the capabilities of
+        * the supported sensors
         * ==> filter out invalid results for not measuring echos of
         *     another us sensor
         *
         * formula:
-        *         distance       3 m
-        * time = ---------- = --------- = 9404389 ns
-        *          speed       319 m/s
+        *         distance     6,45 * 2 m
+        * time = ---------- = ------------ = 40438871 ns
+        *          speed         319 m/s
         *
         * using a minimum speed at -20 Â°C of 319 m/s
         */
-       if (dt_ns > 9404389)
+       if (dt_ns > 40438871)
                return -EIO;
 
        time_ns = dt_ns;
@@ -159,20 +160,20 @@ static int srf04_read(struct srf04_data *data)
         *   with Temp in Â°C
         *   and speed in m/s
         *
-        * use 343 m/s as ultrasonic speed at 20 Â°C here in absence of the
+        * use 343,5 m/s as ultrasonic speed at 20 Â°C here in absence of the
         * temperature
         *
         * therefore:
-        *             time     343
-        * distance = ------ * -----
-        *             10^6       2
+        *             time     343,5     time * 106
+        * distance = ------ * ------- = ------------
+        *             10^6         2         617176
         *   with time in ns
         *   and distance in mm (one way)
         *
-        * because we limit to 3 meters the multiplication with 343 just
+        * because we limit to 6,45 meters the multiplication with 106 just
         * fits into 32 bit
         */
-       distance_mm = time_ns * 343 / 2000000;
+       distance_mm = time_ns * 106 / 617176;
 
        return distance_mm;
 }
index 3a8b0911c3bc16193032dcf1c678f18ded9d9f70..9d07378b5b4230f6e5f1568f3e6b428e95f7b98a 100644 (file)
@@ -199,6 +199,7 @@ void ib_mad_cleanup(void);
 int ib_sa_init(void);
 void ib_sa_cleanup(void);
 
+void rdma_nl_init(void);
 void rdma_nl_exit(void);
 
 int ib_nl_handle_resolve_resp(struct sk_buff *skb,
index 2dd2cfe9b56136f950fd9648120304e2b21a6904..50a92442c4f7c15ebc0708494cca898d3707c1cb 100644 (file)
@@ -2716,6 +2716,8 @@ static int __init ib_core_init(void)
                goto err_comp_unbound;
        }
 
+       rdma_nl_init();
+
        ret = addr_init();
        if (ret) {
                pr_warn("Could't init IB address resolution\n");
index 72141c5b7c95d8701d66272fa0a697465f2103a8..ade71823370f3335566079599a76dde871cc9333 100644 (file)
@@ -372,6 +372,7 @@ EXPORT_SYMBOL(iw_cm_disconnect);
 static void destroy_cm_id(struct iw_cm_id *cm_id)
 {
        struct iwcm_id_private *cm_id_priv;
+       struct ib_qp *qp;
        unsigned long flags;
 
        cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
@@ -389,6 +390,9 @@ static void destroy_cm_id(struct iw_cm_id *cm_id)
        set_bit(IWCM_F_DROP_EVENTS, &cm_id_priv->flags);
 
        spin_lock_irqsave(&cm_id_priv->lock, flags);
+       qp = cm_id_priv->qp;
+       cm_id_priv->qp = NULL;
+
        switch (cm_id_priv->state) {
        case IW_CM_STATE_LISTEN:
                cm_id_priv->state = IW_CM_STATE_DESTROYING;
@@ -401,7 +405,7 @@ static void destroy_cm_id(struct iw_cm_id *cm_id)
                cm_id_priv->state = IW_CM_STATE_DESTROYING;
                spin_unlock_irqrestore(&cm_id_priv->lock, flags);
                /* Abrupt close of the connection */
-               (void)iwcm_modify_qp_err(cm_id_priv->qp);
+               (void)iwcm_modify_qp_err(qp);
                spin_lock_irqsave(&cm_id_priv->lock, flags);
                break;
        case IW_CM_STATE_IDLE:
@@ -426,11 +430,9 @@ static void destroy_cm_id(struct iw_cm_id *cm_id)
                BUG();
                break;
        }
-       if (cm_id_priv->qp) {
-               cm_id_priv->id.device->ops.iw_rem_ref(cm_id_priv->qp);
-               cm_id_priv->qp = NULL;
-       }
        spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+       if (qp)
+               cm_id_priv->id.device->ops.iw_rem_ref(qp);
 
        if (cm_id->mapped) {
                iwpm_remove_mapinfo(&cm_id->local_addr, &cm_id->m_local_addr);
@@ -671,11 +673,11 @@ int iw_cm_accept(struct iw_cm_id *cm_id,
                BUG_ON(cm_id_priv->state != IW_CM_STATE_CONN_RECV);
                cm_id_priv->state = IW_CM_STATE_IDLE;
                spin_lock_irqsave(&cm_id_priv->lock, flags);
-               if (cm_id_priv->qp) {
-                       cm_id->device->ops.iw_rem_ref(qp);
-                       cm_id_priv->qp = NULL;
-               }
+               qp = cm_id_priv->qp;
+               cm_id_priv->qp = NULL;
                spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+               if (qp)
+                       cm_id->device->ops.iw_rem_ref(qp);
                clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
                wake_up_all(&cm_id_priv->connect_wait);
        }
@@ -696,7 +698,7 @@ int iw_cm_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
        struct iwcm_id_private *cm_id_priv;
        int ret;
        unsigned long flags;
-       struct ib_qp *qp;
+       struct ib_qp *qp = NULL;
 
        cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
 
@@ -730,13 +732,13 @@ int iw_cm_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
                return 0;       /* success */
 
        spin_lock_irqsave(&cm_id_priv->lock, flags);
-       if (cm_id_priv->qp) {
-               cm_id->device->ops.iw_rem_ref(qp);
-               cm_id_priv->qp = NULL;
-       }
+       qp = cm_id_priv->qp;
+       cm_id_priv->qp = NULL;
        cm_id_priv->state = IW_CM_STATE_IDLE;
 err:
        spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+       if (qp)
+               cm_id->device->ops.iw_rem_ref(qp);
        clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
        wake_up_all(&cm_id_priv->connect_wait);
        return ret;
@@ -878,6 +880,7 @@ static int cm_conn_est_handler(struct iwcm_id_private *cm_id_priv,
 static int cm_conn_rep_handler(struct iwcm_id_private *cm_id_priv,
                               struct iw_cm_event *iw_event)
 {
+       struct ib_qp *qp = NULL;
        unsigned long flags;
        int ret;
 
@@ -896,11 +899,13 @@ static int cm_conn_rep_handler(struct iwcm_id_private *cm_id_priv,
                cm_id_priv->state = IW_CM_STATE_ESTABLISHED;
        } else {
                /* REJECTED or RESET */
-               cm_id_priv->id.device->ops.iw_rem_ref(cm_id_priv->qp);
+               qp = cm_id_priv->qp;
                cm_id_priv->qp = NULL;
                cm_id_priv->state = IW_CM_STATE_IDLE;
        }
        spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+       if (qp)
+               cm_id_priv->id.device->ops.iw_rem_ref(qp);
        ret = cm_id_priv->id.cm_handler(&cm_id_priv->id, iw_event);
 
        if (iw_event->private_data_len)
@@ -942,21 +947,18 @@ static void cm_disconnect_handler(struct iwcm_id_private *cm_id_priv,
 static int cm_close_handler(struct iwcm_id_private *cm_id_priv,
                                  struct iw_cm_event *iw_event)
 {
+       struct ib_qp *qp;
        unsigned long flags;
-       int ret = 0;
+       int ret = 0, notify_event = 0;
        spin_lock_irqsave(&cm_id_priv->lock, flags);
+       qp = cm_id_priv->qp;
+       cm_id_priv->qp = NULL;
 
-       if (cm_id_priv->qp) {
-               cm_id_priv->id.device->ops.iw_rem_ref(cm_id_priv->qp);
-               cm_id_priv->qp = NULL;
-       }
        switch (cm_id_priv->state) {
        case IW_CM_STATE_ESTABLISHED:
        case IW_CM_STATE_CLOSING:
                cm_id_priv->state = IW_CM_STATE_IDLE;
-               spin_unlock_irqrestore(&cm_id_priv->lock, flags);
-               ret = cm_id_priv->id.cm_handler(&cm_id_priv->id, iw_event);
-               spin_lock_irqsave(&cm_id_priv->lock, flags);
+               notify_event = 1;
                break;
        case IW_CM_STATE_DESTROYING:
                break;
@@ -965,6 +967,10 @@ static int cm_close_handler(struct iwcm_id_private *cm_id_priv,
        }
        spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 
+       if (qp)
+               cm_id_priv->id.device->ops.iw_rem_ref(qp);
+       if (notify_event)
+               ret = cm_id_priv->id.cm_handler(&cm_id_priv->id, iw_event);
        return ret;
 }
 
index 81dbd5f41beda241c1f815077fcad91a7f019f26..8cd31ef25eff20e3f54e5ab7f8f72243748062e2 100644 (file)
 #include <linux/module.h>
 #include "core_priv.h"
 
-static DEFINE_MUTEX(rdma_nl_mutex);
 static struct {
-       const struct rdma_nl_cbs   *cb_table;
+       const struct rdma_nl_cbs *cb_table;
+       /* Synchronizes between ongoing netlink commands and netlink client
+        * unregistration.
+        */
+       struct rw_semaphore sem;
 } rdma_nl_types[RDMA_NL_NUM_CLIENTS];
 
 bool rdma_nl_chk_listeners(unsigned int group)
@@ -75,70 +78,53 @@ static bool is_nl_msg_valid(unsigned int type, unsigned int op)
        return (op < max_num_ops[type]) ? true : false;
 }
 
-static bool
-is_nl_valid(const struct sk_buff *skb, unsigned int type, unsigned int op)
+static const struct rdma_nl_cbs *
+get_cb_table(const struct sk_buff *skb, unsigned int type, unsigned int op)
 {
        const struct rdma_nl_cbs *cb_table;
 
-       if (!is_nl_msg_valid(type, op))
-               return false;
-
        /*
         * Currently only NLDEV client is supporting netlink commands in
         * non init_net net namespace.
         */
        if (sock_net(skb->sk) != &init_net && type != RDMA_NL_NLDEV)
-               return false;
+               return NULL;
 
-       if (!rdma_nl_types[type].cb_table) {
-               mutex_unlock(&rdma_nl_mutex);
-               request_module("rdma-netlink-subsys-%d", type);
-               mutex_lock(&rdma_nl_mutex);
-       }
+       cb_table = READ_ONCE(rdma_nl_types[type].cb_table);
+       if (!cb_table) {
+               /*
+                * Didn't get valid reference of the table, attempt module
+                * load once.
+                */
+               up_read(&rdma_nl_types[type].sem);
 
-       cb_table = rdma_nl_types[type].cb_table;
+               request_module("rdma-netlink-subsys-%d", type);
 
+               down_read(&rdma_nl_types[type].sem);
+               cb_table = READ_ONCE(rdma_nl_types[type].cb_table);
+       }
        if (!cb_table || (!cb_table[op].dump && !cb_table[op].doit))
-               return false;
-       return true;
+               return NULL;
+       return cb_table;
 }
 
 void rdma_nl_register(unsigned int index,
                      const struct rdma_nl_cbs cb_table[])
 {
-       mutex_lock(&rdma_nl_mutex);
-       if (!is_nl_msg_valid(index, 0)) {
-               /*
-                * All clients are not interesting in success/failure of
-                * this call. They want to see the print to error log and
-                * continue their initialization. Print warning for them,
-                * because it is programmer's error to be here.
-                */
-               mutex_unlock(&rdma_nl_mutex);
-               WARN(true,
-                    "The not-valid %u index was supplied to RDMA netlink\n",
-                    index);
+       if (WARN_ON(!is_nl_msg_valid(index, 0)) ||
+           WARN_ON(READ_ONCE(rdma_nl_types[index].cb_table)))
                return;
-       }
-
-       if (rdma_nl_types[index].cb_table) {
-               mutex_unlock(&rdma_nl_mutex);
-               WARN(true,
-                    "The %u index is already registered in RDMA netlink\n",
-                    index);
-               return;
-       }
 
-       rdma_nl_types[index].cb_table = cb_table;
-       mutex_unlock(&rdma_nl_mutex);
+       /* Pairs with the READ_ONCE in is_nl_valid() */
+       smp_store_release(&rdma_nl_types[index].cb_table, cb_table);
 }
 EXPORT_SYMBOL(rdma_nl_register);
 
 void rdma_nl_unregister(unsigned int index)
 {
-       mutex_lock(&rdma_nl_mutex);
+       down_write(&rdma_nl_types[index].sem);
        rdma_nl_types[index].cb_table = NULL;
-       mutex_unlock(&rdma_nl_mutex);
+       up_write(&rdma_nl_types[index].sem);
 }
 EXPORT_SYMBOL(rdma_nl_unregister);
 
@@ -170,15 +156,21 @@ static int rdma_nl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
        unsigned int index = RDMA_NL_GET_CLIENT(type);
        unsigned int op = RDMA_NL_GET_OP(type);
        const struct rdma_nl_cbs *cb_table;
+       int err = -EINVAL;
 
-       if (!is_nl_valid(skb, index, op))
+       if (!is_nl_msg_valid(index, op))
                return -EINVAL;
 
-       cb_table = rdma_nl_types[index].cb_table;
+       down_read(&rdma_nl_types[index].sem);
+       cb_table = get_cb_table(skb, index, op);
+       if (!cb_table)
+               goto done;
 
        if ((cb_table[op].flags & RDMA_NL_ADMIN_PERM) &&
-           !netlink_capable(skb, CAP_NET_ADMIN))
-               return -EPERM;
+           !netlink_capable(skb, CAP_NET_ADMIN)) {
+               err = -EPERM;
+               goto done;
+       }
 
        /*
         * LS responses overload the 0x100 (NLM_F_ROOT) flag.  Don't
@@ -186,8 +178,8 @@ static int rdma_nl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
         */
        if (index == RDMA_NL_LS) {
                if (cb_table[op].doit)
-                       return cb_table[op].doit(skb, nlh, extack);
-               return -EINVAL;
+                       err = cb_table[op].doit(skb, nlh, extack);
+               goto done;
        }
        /* FIXME: Convert IWCM to properly handle doit callbacks */
        if ((nlh->nlmsg_flags & NLM_F_DUMP) || index == RDMA_NL_IWCM) {
@@ -195,14 +187,15 @@ static int rdma_nl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
                        .dump = cb_table[op].dump,
                };
                if (c.dump)
-                       return netlink_dump_start(skb->sk, skb, nlh, &c);
-               return -EINVAL;
+                       err = netlink_dump_start(skb->sk, skb, nlh, &c);
+               goto done;
        }
 
        if (cb_table[op].doit)
-               return cb_table[op].doit(skb, nlh, extack);
-
-       return 0;
+               err = cb_table[op].doit(skb, nlh, extack);
+done:
+       up_read(&rdma_nl_types[index].sem);
+       return err;
 }
 
 /*
@@ -263,9 +256,7 @@ skip:
 
 static void rdma_nl_rcv(struct sk_buff *skb)
 {
-       mutex_lock(&rdma_nl_mutex);
        rdma_nl_rcv_skb(skb, &rdma_nl_rcv_msg);
-       mutex_unlock(&rdma_nl_mutex);
 }
 
 int rdma_nl_unicast(struct net *net, struct sk_buff *skb, u32 pid)
@@ -297,6 +288,14 @@ int rdma_nl_multicast(struct net *net, struct sk_buff *skb,
 }
 EXPORT_SYMBOL(rdma_nl_multicast);
 
+void rdma_nl_init(void)
+{
+       int idx;
+
+       for (idx = 0; idx < RDMA_NL_NUM_CLIENTS; idx++)
+               init_rwsem(&rdma_nl_types[idx].sem);
+}
+
 void rdma_nl_exit(void)
 {
        int idx;
index 65b36548bc17139b0a2fa5da51a4e0e7d4f9089f..c03af08b80e776688cfa3d4e303d37b1b992a7af 100644 (file)
@@ -778,7 +778,7 @@ static int fill_res_counter_entry(struct sk_buff *msg, bool has_cap_net_admin,
                container_of(res, struct rdma_counter, res);
 
        if (port && port != counter->port)
-               return 0;
+               return -EAGAIN;
 
        /* Dump it even query failed */
        rdma_counter_query_stats(counter);
index 1e5aeb39f774df6a1bc386ea448b89763ee1705f..63f7f7db590286a6e6bdc5d4d5cd037bb841294b 100644 (file)
@@ -98,7 +98,7 @@ ib_uverbs_init_udata_buf_or_null(struct ib_udata *udata,
 
 struct ib_uverbs_device {
        atomic_t                                refcount;
-       int                                     num_comp_vectors;
+       u32                                     num_comp_vectors;
        struct completion                       comp;
        struct device                           dev;
        /* First group for device attributes, NULL terminated array */
index f974b68542245206936e623a6d62d6ef948cecce..35c2841a569e98e73229bc80a99d8f350c00cda7 100644 (file)
@@ -662,16 +662,17 @@ static bool find_gid_index(const union ib_gid *gid,
                           void *context)
 {
        struct find_gid_index_context *ctx = context;
+       u16 vlan_id = 0xffff;
+       int ret;
 
        if (ctx->gid_type != gid_attr->gid_type)
                return false;
 
-       if ((!!(ctx->vlan_id != 0xffff) == !is_vlan_dev(gid_attr->ndev)) ||
-           (is_vlan_dev(gid_attr->ndev) &&
-            vlan_dev_vlan_id(gid_attr->ndev) != ctx->vlan_id))
+       ret = rdma_read_gid_l2_fields(gid_attr, &vlan_id, NULL);
+       if (ret)
                return false;
 
-       return true;
+       return ctx->vlan_id == vlan_id;
 }
 
 static const struct ib_gid_attr *
index e87fc0408470452c4bc5600c127f69848c2c3cb3..347dc242fb8829eab1fca133e61da178cad78081 100644 (file)
@@ -495,7 +495,6 @@ static int _put_ep_safe(struct c4iw_dev *dev, struct sk_buff *skb)
 
        ep = *((struct c4iw_ep **)(skb->cb + 2 * sizeof(void *)));
        release_ep_resources(ep);
-       kfree_skb(skb);
        return 0;
 }
 
@@ -506,7 +505,6 @@ static int _put_pass_ep_safe(struct c4iw_dev *dev, struct sk_buff *skb)
        ep = *((struct c4iw_ep **)(skb->cb + 2 * sizeof(void *)));
        c4iw_put_ep(&ep->parent_ep->com);
        release_ep_resources(ep);
-       kfree_skb(skb);
        return 0;
 }
 
@@ -2424,20 +2422,6 @@ static int accept_cr(struct c4iw_ep *ep, struct sk_buff *skb,
        enum chip_type adapter_type = ep->com.dev->rdev.lldi.adapter_type;
 
        pr_debug("ep %p tid %u\n", ep, ep->hwtid);
-
-       skb_get(skb);
-       rpl = cplhdr(skb);
-       if (!is_t4(adapter_type)) {
-               skb_trim(skb, roundup(sizeof(*rpl5), 16));
-               rpl5 = (void *)rpl;
-               INIT_TP_WR(rpl5, ep->hwtid);
-       } else {
-               skb_trim(skb, sizeof(*rpl));
-               INIT_TP_WR(rpl, ep->hwtid);
-       }
-       OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_PASS_ACCEPT_RPL,
-                                                   ep->hwtid));
-
        cxgb_best_mtu(ep->com.dev->rdev.lldi.mtus, ep->mtu, &mtu_idx,
                      enable_tcp_timestamps && req->tcpopt.tstamp,
                      (ep->com.remote_addr.ss_family == AF_INET) ? 0 : 1);
@@ -2483,6 +2467,20 @@ static int accept_cr(struct c4iw_ep *ep, struct sk_buff *skb,
                if (tcph->ece && tcph->cwr)
                        opt2 |= CCTRL_ECN_V(1);
        }
+
+       skb_get(skb);
+       rpl = cplhdr(skb);
+       if (!is_t4(adapter_type)) {
+               skb_trim(skb, roundup(sizeof(*rpl5), 16));
+               rpl5 = (void *)rpl;
+               INIT_TP_WR(rpl5, ep->hwtid);
+       } else {
+               skb_trim(skb, sizeof(*rpl));
+               INIT_TP_WR(rpl, ep->hwtid);
+       }
+       OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_PASS_ACCEPT_RPL,
+                                                   ep->hwtid));
+
        if (CHELSIO_CHIP_VERSION(adapter_type) > CHELSIO_T4) {
                u32 isn = (prandom_u32() & ~7UL) - 1;
                opt2 |= T5_OPT_2_VALID_F;
index 2ed7bfd5feea6a5ec5206ac77ff583ab1f77daa4..c61b6022575e1abe24a4a7bbf67729a0ad140315 100644 (file)
@@ -65,6 +65,7 @@
 #define SDMA_DESCQ_CNT 2048
 #define SDMA_DESC_INTR 64
 #define INVALID_TAIL 0xffff
+#define SDMA_PAD max_t(size_t, MAX_16B_PADDING, sizeof(u32))
 
 static uint sdma_descq_cnt = SDMA_DESCQ_CNT;
 module_param(sdma_descq_cnt, uint, S_IRUGO);
@@ -1296,7 +1297,7 @@ void sdma_clean(struct hfi1_devdata *dd, size_t num_engines)
        struct sdma_engine *sde;
 
        if (dd->sdma_pad_dma) {
-               dma_free_coherent(&dd->pcidev->dev, 4,
+               dma_free_coherent(&dd->pcidev->dev, SDMA_PAD,
                                  (void *)dd->sdma_pad_dma,
                                  dd->sdma_pad_phys);
                dd->sdma_pad_dma = NULL;
@@ -1491,7 +1492,7 @@ int sdma_init(struct hfi1_devdata *dd, u8 port)
        }
 
        /* Allocate memory for pad */
-       dd->sdma_pad_dma = dma_alloc_coherent(&dd->pcidev->dev, sizeof(u32),
+       dd->sdma_pad_dma = dma_alloc_coherent(&dd->pcidev->dev, SDMA_PAD,
                                              &dd->sdma_pad_phys, GFP_KERNEL);
        if (!dd->sdma_pad_dma) {
                dd_dev_err(dd, "failed to allocate SendDMA pad memory\n");
index b4dcc4d29f84e0e10fcd312b97b520fda0507fd8..f21fca3617d5feae86f97213130c84426efb3218 100644 (file)
@@ -2736,11 +2736,6 @@ static bool handle_read_kdeth_eflags(struct hfi1_ctxtdata *rcd,
                                diff = cmp_psn(psn,
                                               flow->flow_state.r_next_psn);
                                if (diff > 0) {
-                                       if (!(qp->r_flags & RVT_R_RDMAR_SEQ))
-                                               restart_tid_rdma_read_req(rcd,
-                                                                         qp,
-                                                                         wqe);
-
                                        /* Drop the packet.*/
                                        goto s_unlock;
                                } else if (diff < 0) {
index 7bff0a1e713d77535a1ba52de3186b082b1e429e..089e201d75500072f527410a6ea8b1499fef19b1 100644 (file)
@@ -147,9 +147,6 @@ static int pio_wait(struct rvt_qp *qp,
 /* Length of buffer to create verbs txreq cache name */
 #define TXREQ_NAME_LEN 24
 
-/* 16B trailing buffer */
-static const u8 trail_buf[MAX_16B_PADDING];
-
 static uint wss_threshold = 80;
 module_param(wss_threshold, uint, S_IRUGO);
 MODULE_PARM_DESC(wss_threshold, "Percentage (1-100) of LLC to use as a threshold for a cacheless copy");
@@ -820,8 +817,8 @@ static int build_verbs_tx_desc(
 
        /* add icrc, lt byte, and padding to flit */
        if (extra_bytes)
-               ret = sdma_txadd_kvaddr(sde->dd, &tx->txreq,
-                                       (void *)trail_buf, extra_bytes);
+               ret = sdma_txadd_daddr(sde->dd, &tx->txreq,
+                                      sde->dd->sdma_pad_phys, extra_bytes);
 
 bail_txadd:
        return ret;
@@ -1089,7 +1086,8 @@ int hfi1_verbs_send_pio(struct rvt_qp *qp, struct hfi1_pkt_state *ps,
                }
                /* add icrc, lt byte, and padding to flit */
                if (extra_bytes)
-                       seg_pio_copy_mid(pbuf, trail_buf, extra_bytes);
+                       seg_pio_copy_mid(pbuf, ppd->dd->sdma_pad_dma,
+                                        extra_bytes);
 
                seg_pio_copy_end(pbuf);
        }
index 7a89d669f8bfa93265228c855d233a48cd5f5cf6..e82567fcdeb7f05c46110a77176d50563ee3e10f 100644 (file)
@@ -5389,9 +5389,9 @@ static void hns_roce_v2_free_eq(struct hns_roce_dev *hr_dev,
                return;
        }
 
-       if (eq->buf_list)
-               dma_free_coherent(hr_dev->dev, buf_chk_sz,
-                                 eq->buf_list->buf, eq->buf_list->map);
+       dma_free_coherent(hr_dev->dev, buf_chk_sz, eq->buf_list->buf,
+                         eq->buf_list->map);
+       kfree(eq->buf_list);
 }
 
 static void hns_roce_config_eqc(struct hns_roce_dev *hr_dev,
index 630599311586ec23491025dac5603da7d848ead7..7019c12005f4c1fb0606473b0ef72b50af7c3af5 100644 (file)
@@ -1967,8 +1967,8 @@ int mlx5_ib_dealloc_mw(struct ib_mw *mw)
        int err;
 
        if (IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING)) {
-               xa_erase(&dev->mdev->priv.mkey_table,
-                        mlx5_base_mkey(mmw->mmkey.key));
+               xa_erase_irq(&dev->mdev->priv.mkey_table,
+                            mlx5_base_mkey(mmw->mmkey.key));
                /*
                 * pagefault_single_data_segment() may be accessing mmw under
                 * SRCU if the user bound an ODP MR to this MW.
index 8937d72ddcf6bdb44f48b37acbbec178fa2650e0..5fd071c05944d900b95654925dfff09bc47e1e69 100644 (file)
@@ -3249,10 +3249,12 @@ static int modify_raw_packet_qp_sq(
        }
 
        /* Only remove the old rate after new rate was set */
-       if ((old_rl.rate &&
-            !mlx5_rl_are_equal(&old_rl, &new_rl)) ||
-           (new_state != MLX5_SQC_STATE_RDY))
+       if ((old_rl.rate && !mlx5_rl_are_equal(&old_rl, &new_rl)) ||
+           (new_state != MLX5_SQC_STATE_RDY)) {
                mlx5_rl_remove_rate(dev, &old_rl);
+               if (new_state != MLX5_SQC_STATE_RDY)
+                       memset(&new_rl, 0, sizeof(new_rl));
+       }
 
        ibqp->rl = new_rl;
        sq->state = new_state;
index 5136b835e1ba0521050caf388d018125a0ad2347..dc71b6e16a07f300306a2d39b255d546ac3a38ea 100644 (file)
@@ -76,7 +76,7 @@ static void qedr_get_dev_fw_str(struct ib_device *ibdev, char *str)
        struct qedr_dev *qedr = get_qedr_dev(ibdev);
        u32 fw_ver = (u32)qedr->attr.fw_ver;
 
-       snprintf(str, IB_FW_VERSION_NAME_MAX, "%d. %d. %d. %d",
+       snprintf(str, IB_FW_VERSION_NAME_MAX, "%d.%d.%d.%d",
                 (fw_ver >> 24) & 0xFF, (fw_ver >> 16) & 0xFF,
                 (fw_ver >> 8) & 0xFF, fw_ver & 0xFF);
 }
index 52d402f39df93c28771d09ee9b673ea40303101f..b4317480cee7486d2f461d4b870cd801bc636d93 100644 (file)
@@ -1312,6 +1312,7 @@ int siw_qp_add(struct siw_device *sdev, struct siw_qp *qp)
 void siw_free_qp(struct kref *ref)
 {
        struct siw_qp *found, *qp = container_of(ref, struct siw_qp, ref);
+       struct siw_base_qp *siw_base_qp = to_siw_base_qp(qp->ib_qp);
        struct siw_device *sdev = qp->sdev;
        unsigned long flags;
 
@@ -1334,4 +1335,5 @@ void siw_free_qp(struct kref *ref)
        atomic_dec(&sdev->num_qp);
        siw_dbg_qp(qp, "free QP\n");
        kfree_rcu(qp, rcu);
+       kfree(siw_base_qp);
 }
index 869e02b69a012389d6d3533241012b1c1309e401..b18a677832e105ded578bd74d29694c45e55d031 100644 (file)
@@ -604,7 +604,6 @@ out:
 int siw_destroy_qp(struct ib_qp *base_qp, struct ib_udata *udata)
 {
        struct siw_qp *qp = to_siw_qp(base_qp);
-       struct siw_base_qp *siw_base_qp = to_siw_base_qp(base_qp);
        struct siw_ucontext *uctx =
                rdma_udata_to_drv_context(udata, struct siw_ucontext,
                                          base_ucontext);
@@ -641,7 +640,6 @@ int siw_destroy_qp(struct ib_qp *base_qp, struct ib_udata *udata)
        qp->scq = qp->rcq = NULL;
 
        siw_qp_put(qp);
-       kfree(siw_base_qp);
 
        return 0;
 }
index 34923399ece4e98534022f90d8ad4180ef4536b6..1139714e72e2672f26a52be85280e7f8fea22e11 100644 (file)
@@ -81,8 +81,10 @@ static int st1232_ts_read_data(struct st1232_ts_data *ts)
        for (i = 0, y = 0; i < ts->chip_info->max_fingers; i++, y += 3) {
                finger[i].is_valid = buf[i + y] >> 7;
                if (finger[i].is_valid) {
-                       finger[i].x = ((buf[i + y] & 0x0070) << 4) | buf[i + 1];
-                       finger[i].y = ((buf[i + y] & 0x0007) << 8) | buf[i + 2];
+                       finger[i].x = ((buf[i + y] & 0x0070) << 4) |
+                                       buf[i + y + 1];
+                       finger[i].y = ((buf[i + y] & 0x0007) << 8) |
+                                       buf[i + y + 2];
 
                        /* st1232 includes a z-axis / touch strength */
                        if (ts->chip_info->have_z)
index 7b971228df38667f8983572922ad8a971b79fe3c..c498796adc074d5c42fdae5b95bbb809a43850b3 100644 (file)
@@ -405,8 +405,12 @@ void icc_set_tag(struct icc_path *path, u32 tag)
        if (!path)
                return;
 
+       mutex_lock(&icc_lock);
+
        for (i = 0; i < path->num_nodes; i++)
                path->reqs[i].tag = tag;
+
+       mutex_unlock(&icc_lock);
 }
 EXPORT_SYMBOL_GPL(icc_set_tag);
 
index 910081d6ddc00e59a9c8bd4c4e180cdba9d791d0..b4966d8f3348d269e90f2c69f69d167ba613f905 100644 (file)
@@ -433,7 +433,8 @@ static int qnoc_probe(struct platform_device *pdev)
        if (!qp)
                return -ENOMEM;
 
-       data = devm_kcalloc(dev, num_nodes, sizeof(*node), GFP_KERNEL);
+       data = devm_kzalloc(dev, struct_size(data, nodes, num_nodes),
+                           GFP_KERNEL);
        if (!data)
                return -ENOMEM;
 
index 57955596bb5967ec8a7477cd38caa0b4d744acba..502a6c22b41eea9ded02b65a51b68aa028a78ca6 100644 (file)
@@ -790,7 +790,8 @@ static int qnoc_probe(struct platform_device *pdev)
        if (!qp)
                return -ENOMEM;
 
-       data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL);
+       data = devm_kzalloc(&pdev->dev, struct_size(data, nodes, num_nodes),
+                           GFP_KERNEL);
        if (!data)
                return -ENOMEM;
 
index c235f79b7a200c90f8b8d4325a61ce4373de8d86..5120ce4fdce326b6b59185d66e7ba8cb146bf4d5 100644 (file)
@@ -73,6 +73,19 @@ static const struct dmi_system_id ivrs_quirks[] __initconst = {
                },
                .driver_data = (void *)&ivrs_ioapic_quirks[DELL_LATITUDE_5495],
        },
+       {
+               /*
+                * Acer Aspire A315-41 requires the very same workaround as
+                * Dell Latitude 5495
+                */
+               .callback = ivrs_ioapic_quirk_cb,
+               .ident = "Acer Aspire A315-41",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A315-41"),
+               },
+               .driver_data = (void *)&ivrs_ioapic_quirks[DELL_LATITUDE_5495],
+       },
        {
                .callback = ivrs_ioapic_quirk_cb,
                .ident = "Lenovo ideapad 330S-15ARR",
index 3f974919d3bdb4c7ee78adc091f585c4cc7a6da7..6db6d969e31c6adcc5202fa0ea97eabf347b7b63 100644 (file)
@@ -2794,7 +2794,7 @@ static int identity_mapping(struct device *dev)
        struct device_domain_info *info;
 
        info = dev->archdata.iommu;
-       if (info && info != DUMMY_DEVICE_DOMAIN_INFO)
+       if (info && info != DUMMY_DEVICE_DOMAIN_INFO && info != DEFER_DEVICE_DOMAIN_INFO)
                return (info->domain == si_domain);
 
        return 0;
@@ -3471,7 +3471,7 @@ static bool iommu_need_mapping(struct device *dev)
                if (dev->coherent_dma_mask && dev->coherent_dma_mask < dma_mask)
                        dma_mask = dev->coherent_dma_mask;
 
-               if (dma_mask >= dma_get_required_mask(dev))
+               if (dma_mask >= dma_direct_get_required_mask(dev))
                        return false;
 
                /*
@@ -3775,6 +3775,13 @@ static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nele
        return nelems;
 }
 
+static u64 intel_get_required_mask(struct device *dev)
+{
+       if (!iommu_need_mapping(dev))
+               return dma_direct_get_required_mask(dev);
+       return DMA_BIT_MASK(32);
+}
+
 static const struct dma_map_ops intel_dma_ops = {
        .alloc = intel_alloc_coherent,
        .free = intel_free_coherent,
@@ -3787,6 +3794,7 @@ static const struct dma_map_ops intel_dma_ops = {
        .dma_supported = dma_direct_supported,
        .mmap = dma_common_mmap,
        .get_sgtable = dma_common_get_sgtable,
+       .get_required_mask = intel_get_required_mask,
 };
 
 static void
index 237103465b824c513722d67beb3135f21fbb00d0..2639fc7181171c4ab1db52bb0765c8f0a8b24bd6 100644 (file)
@@ -1105,10 +1105,8 @@ static int ipmmu_probe(struct platform_device *pdev)
        /* Root devices have mandatory IRQs */
        if (ipmmu_is_root(mmu)) {
                irq = platform_get_irq(pdev, 0);
-               if (irq < 0) {
-                       dev_err(&pdev->dev, "no IRQ found\n");
+               if (irq < 0)
                        return irq;
-               }
 
                ret = devm_request_irq(&pdev->dev, irq, ipmmu_irq, 0,
                                       dev_name(&pdev->dev), mmu);
index 62e54f1a248ba002942bc0bae0c6b97d52f9f857..787e8eec9a7f1862275587f079d2809715baeeec 100644 (file)
@@ -175,6 +175,22 @@ static DEFINE_IDA(its_vpeid_ida);
 #define gic_data_rdist_rd_base()       (gic_data_rdist()->rd_base)
 #define gic_data_rdist_vlpi_base()     (gic_data_rdist_rd_base() + SZ_128K)
 
+static u16 get_its_list(struct its_vm *vm)
+{
+       struct its_node *its;
+       unsigned long its_list = 0;
+
+       list_for_each_entry(its, &its_nodes, entry) {
+               if (!its->is_v4)
+                       continue;
+
+               if (vm->vlpi_count[its->list_nr])
+                       __set_bit(its->list_nr, &its_list);
+       }
+
+       return (u16)its_list;
+}
+
 static struct its_collection *dev_event_to_col(struct its_device *its_dev,
                                               u32 event)
 {
@@ -976,17 +992,15 @@ static void its_send_vmapp(struct its_node *its,
 
 static void its_send_vmovp(struct its_vpe *vpe)
 {
-       struct its_cmd_desc desc;
+       struct its_cmd_desc desc = {};
        struct its_node *its;
        unsigned long flags;
        int col_id = vpe->col_idx;
 
        desc.its_vmovp_cmd.vpe = vpe;
-       desc.its_vmovp_cmd.its_list = (u16)its_list_map;
 
        if (!its_list_map) {
                its = list_first_entry(&its_nodes, struct its_node, entry);
-               desc.its_vmovp_cmd.seq_num = 0;
                desc.its_vmovp_cmd.col = &its->collections[col_id];
                its_send_single_vcommand(its, its_build_vmovp_cmd, &desc);
                return;
@@ -1003,6 +1017,7 @@ static void its_send_vmovp(struct its_vpe *vpe)
        raw_spin_lock_irqsave(&vmovp_lock, flags);
 
        desc.its_vmovp_cmd.seq_num = vmovp_seq_num++;
+       desc.its_vmovp_cmd.its_list = get_its_list(vpe->its_vm);
 
        /* Emit VMOVPs */
        list_for_each_entry(its, &its_nodes, entry) {
index daefc52b0ec55150ed37c6979642c10e046d4c0d..7d0a12fe2714a72979cf56281be5a78fa644064a 100644 (file)
@@ -252,8 +252,8 @@ static int __init plic_init(struct device_node *node,
                        continue;
                }
 
-               /* skip context holes */
-               if (parent.args[0] == -1)
+               /* skip contexts other than supervisor external interrupt */
+               if (parent.args[0] != IRQ_S_EXT)
                        continue;
 
                hartid = plic_find_hart_id(parent.np);
index c92b405b7646cfbceaed3b6544fb71d145c9bb42..ba8619524231ccde29093076e6196652d17dd69b 100644 (file)
@@ -744,7 +744,7 @@ capi_poll(struct file *file, poll_table *wait)
 
        poll_wait(file, &(cdev->recvwait), wait);
        mask = EPOLLOUT | EPOLLWRNORM;
-       if (!skb_queue_empty(&cdev->recvqueue))
+       if (!skb_queue_empty_lockless(&cdev->recvqueue))
                mask |= EPOLLIN | EPOLLRDNORM;
        return mask;
 }
index 705c6200814b633abf9794b044f3a7b97aa7d269..7b726f00f1834d1cd4aa544090215ad9562e4c08 100644 (file)
@@ -18,7 +18,7 @@
 
 static int clamped;
 static struct wf_control *clamp_control;
-static struct dev_pm_qos_request qos_req;
+static struct freq_qos_request qos_req;
 static unsigned int min_freq, max_freq;
 
 static int clamp_set(struct wf_control *ct, s32 value)
@@ -35,7 +35,7 @@ static int clamp_set(struct wf_control *ct, s32 value)
        }
        clamped = value;
 
-       return dev_pm_qos_update_request(&qos_req, freq);
+       return freq_qos_update_request(&qos_req, freq);
 }
 
 static int clamp_get(struct wf_control *ct, s32 *value)
@@ -77,38 +77,44 @@ static int __init wf_cpufreq_clamp_init(void)
 
        min_freq = policy->cpuinfo.min_freq;
        max_freq = policy->cpuinfo.max_freq;
+
+       ret = freq_qos_add_request(&policy->constraints, &qos_req, FREQ_QOS_MAX,
+                                  max_freq);
+
        cpufreq_cpu_put(policy);
 
+       if (ret < 0) {
+               pr_err("%s: Failed to add freq constraint (%d)\n", __func__,
+                      ret);
+               return ret;
+       }
+
        dev = get_cpu_device(0);
        if (unlikely(!dev)) {
                pr_warn("%s: No cpu device for cpu0\n", __func__);
-               return -ENODEV;
+               ret = -ENODEV;
+               goto fail;
        }
 
        clamp = kmalloc(sizeof(struct wf_control), GFP_KERNEL);
-       if (clamp == NULL)
-               return -ENOMEM;
-
-       ret = dev_pm_qos_add_request(dev, &qos_req, DEV_PM_QOS_MAX_FREQUENCY,
-                                    max_freq);
-       if (ret < 0) {
-               pr_err("%s: Failed to add freq constraint (%d)\n", __func__,
-                      ret);
-               goto free;
+       if (clamp == NULL) {
+               ret = -ENOMEM;
+               goto fail;
        }
 
        clamp->ops = &clamp_ops;
        clamp->name = "cpufreq-clamp";
        ret = wf_register_control(clamp);
        if (ret)
-               goto fail;
+               goto free;
+
        clamp_control = clamp;
        return 0;
- fail:
-       dev_pm_qos_remove_request(&qos_req);
 
  free:
        kfree(clamp);
+ fail:
+       freq_qos_remove_request(&qos_req);
        return ret;
 }
 
@@ -116,7 +122,7 @@ static void __exit wf_cpufreq_clamp_exit(void)
 {
        if (clamp_control) {
                wf_unregister_control(clamp_control);
-               dev_pm_qos_remove_request(&qos_req);
+               freq_qos_remove_request(&qos_req);
        }
 }
 
index 310dae26ddff6283a0b83c05cd5c31b73834cf97..b2c325ead1c8f08b594a9da913ec5013e3068abc 100644 (file)
@@ -129,11 +129,27 @@ static int mt6397_irq_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(mt6397_pm_ops, mt6397_irq_suspend,
                        mt6397_irq_resume);
 
+struct chip_data {
+       u32 cid_addr;
+       u32 cid_shift;
+};
+
+static const struct chip_data mt6323_core = {
+       .cid_addr = MT6323_CID,
+       .cid_shift = 0,
+};
+
+static const struct chip_data mt6397_core = {
+       .cid_addr = MT6397_CID,
+       .cid_shift = 0,
+};
+
 static int mt6397_probe(struct platform_device *pdev)
 {
        int ret;
        unsigned int id;
        struct mt6397_chip *pmic;
+       const struct chip_data *pmic_core;
 
        pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
        if (!pmic)
@@ -149,28 +165,30 @@ static int mt6397_probe(struct platform_device *pdev)
        if (!pmic->regmap)
                return -ENODEV;
 
-       platform_set_drvdata(pdev, pmic);
+       pmic_core = of_device_get_match_data(&pdev->dev);
+       if (!pmic_core)
+               return -ENODEV;
 
-       ret = regmap_read(pmic->regmap, MT6397_CID, &id);
+       ret = regmap_read(pmic->regmap, pmic_core->cid_addr, &id);
        if (ret) {
-               dev_err(pmic->dev, "Failed to read chip id: %d\n", ret);
+               dev_err(&pdev->dev, "Failed to read chip id: %d\n", ret);
                return ret;
        }
 
+       pmic->chip_id = (id >> pmic_core->cid_shift) & 0xff;
+
+       platform_set_drvdata(pdev, pmic);
+
        pmic->irq = platform_get_irq(pdev, 0);
        if (pmic->irq <= 0)
                return pmic->irq;
 
-       switch (id & 0xff) {
-       case MT6323_CHIP_ID:
-               pmic->int_con[0] = MT6323_INT_CON0;
-               pmic->int_con[1] = MT6323_INT_CON1;
-               pmic->int_status[0] = MT6323_INT_STATUS0;
-               pmic->int_status[1] = MT6323_INT_STATUS1;
-               ret = mt6397_irq_init(pmic);
-               if (ret)
-                       return ret;
+       ret = mt6397_irq_init(pmic);
+       if (ret)
+               return ret;
 
+       switch (pmic->chip_id) {
+       case MT6323_CHIP_ID:
                ret = devm_mfd_add_devices(&pdev->dev, -1, mt6323_devs,
                                           ARRAY_SIZE(mt6323_devs), NULL,
                                           0, pmic->irq_domain);
@@ -178,21 +196,13 @@ static int mt6397_probe(struct platform_device *pdev)
 
        case MT6391_CHIP_ID:
        case MT6397_CHIP_ID:
-               pmic->int_con[0] = MT6397_INT_CON0;
-               pmic->int_con[1] = MT6397_INT_CON1;
-               pmic->int_status[0] = MT6397_INT_STATUS0;
-               pmic->int_status[1] = MT6397_INT_STATUS1;
-               ret = mt6397_irq_init(pmic);
-               if (ret)
-                       return ret;
-
                ret = devm_mfd_add_devices(&pdev->dev, -1, mt6397_devs,
                                           ARRAY_SIZE(mt6397_devs), NULL,
                                           0, pmic->irq_domain);
                break;
 
        default:
-               dev_err(&pdev->dev, "unsupported chip: %d\n", id);
+               dev_err(&pdev->dev, "unsupported chip: %d\n", pmic->chip_id);
                return -ENODEV;
        }
 
@@ -205,9 +215,15 @@ static int mt6397_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id mt6397_of_match[] = {
-       { .compatible = "mediatek,mt6397" },
-       { .compatible = "mediatek,mt6323" },
-       { }
+       {
+               .compatible = "mediatek,mt6323",
+               .data = &mt6323_core,
+       }, {
+               .compatible = "mediatek,mt6397",
+               .data = &mt6397_core,
+       }, {
+               /* sentinel */
+       }
 };
 MODULE_DEVICE_TABLE(of, mt6397_of_match);
 
index f7bdae5354c3c48af7bb26d828b83227b057d8bf..5047f7343ffcf41ce3a861ffbb104ac2f6586806 100644 (file)
@@ -611,7 +611,8 @@ static int cqhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
        cq_host->slot[tag].flags = 0;
 
        cq_host->qcnt += 1;
-
+       /* Make sure descriptors are ready before ringing the doorbell */
+       wmb();
        cqhci_writel(cq_host, 1 << tag, CQHCI_TDBR);
        if (!(cqhci_readl(cq_host, CQHCI_TDBR) & (1 << tag)))
                pr_debug("%s: cqhci: doorbell not set for tag %d\n",
index 78e7e350655c7f742970757a4117a8bc00ca8fc5..4031217d21c37be1a847ace9d8369c041ab95561 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
+#include <linux/dma/mxs-dma.h>
 #include <linux/highmem.h>
 #include <linux/clk.h>
 #include <linux/err.h>
@@ -266,7 +267,7 @@ static void mxs_mmc_bc(struct mxs_mmc_host *host)
        ssp->ssp_pio_words[2] = cmd1;
        ssp->dma_dir = DMA_NONE;
        ssp->slave_dirn = DMA_TRANS_NONE;
-       desc = mxs_mmc_prep_dma(host, DMA_CTRL_ACK);
+       desc = mxs_mmc_prep_dma(host, MXS_DMA_CTRL_WAIT4END);
        if (!desc)
                goto out;
 
@@ -311,7 +312,7 @@ static void mxs_mmc_ac(struct mxs_mmc_host *host)
        ssp->ssp_pio_words[2] = cmd1;
        ssp->dma_dir = DMA_NONE;
        ssp->slave_dirn = DMA_TRANS_NONE;
-       desc = mxs_mmc_prep_dma(host, DMA_CTRL_ACK);
+       desc = mxs_mmc_prep_dma(host, MXS_DMA_CTRL_WAIT4END);
        if (!desc)
                goto out;
 
@@ -441,7 +442,7 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
        host->data = data;
        ssp->dma_dir = dma_data_dir;
        ssp->slave_dirn = slave_dirn;
-       desc = mxs_mmc_prep_dma(host, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+       desc = mxs_mmc_prep_dma(host, DMA_PREP_INTERRUPT | MXS_DMA_CTRL_WAIT4END);
        if (!desc)
                goto out;
 
index 41c2677c587f1677366ed14f65cc50cc3da7da96..083e7e053c95401bcc6e87c6e8d5e3a52605e474 100644 (file)
@@ -372,7 +372,7 @@ static int sdhci_omap_execute_tuning(struct mmc_host *mmc, u32 opcode)
         * on temperature
         */
        if (temperature < -20000)
-               phase_delay = min(max_window + 4 * max_len - 24,
+               phase_delay = min(max_window + 4 * (max_len - 1) - 24,
                                  max_window +
                                  DIV_ROUND_UP(13 * max_len, 16) * 4);
        else if (temperature < 20000)
index 8c79bad2a9a57dfd9f1841add3597590ab02e3db..4f2e6910c6232618ab536c83cdc83ba1a398b041 100644 (file)
@@ -952,7 +952,7 @@ static int alb_upper_dev_walk(struct net_device *upper, void *_data)
        struct bond_vlan_tag *tags;
 
        if (is_vlan_dev(upper) &&
-           bond->nest_level == vlan_get_encap_level(upper) - 1) {
+           bond->dev->lower_level == upper->lower_level - 1) {
                if (upper->addr_assign_type == NET_ADDR_STOLEN) {
                        alb_send_lp_vid(slave, mac_addr,
                                        vlan_dev_vlan_proto(upper),
index 21d8fcc83c9ce958b6e9cb4c6f499ed9ef53f4d5..62f65573eb04b190b825694fe772b9bf21836ba8 100644 (file)
@@ -1733,8 +1733,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
                goto err_upper_unlink;
        }
 
-       bond->nest_level = dev_get_nest_level(bond_dev) + 1;
-
        /* If the mode uses primary, then the following is handled by
         * bond_change_active_slave().
         */
@@ -1816,7 +1814,8 @@ err_detach:
        slave_disable_netpoll(new_slave);
 
 err_close:
-       slave_dev->priv_flags &= ~IFF_BONDING;
+       if (!netif_is_bond_master(slave_dev))
+               slave_dev->priv_flags &= ~IFF_BONDING;
        dev_close(slave_dev);
 
 err_restore_mac:
@@ -1956,9 +1955,6 @@ static int __bond_release_one(struct net_device *bond_dev,
        if (!bond_has_slaves(bond)) {
                bond_set_carrier(bond);
                eth_hw_addr_random(bond_dev);
-               bond->nest_level = SINGLE_DEPTH_NESTING;
-       } else {
-               bond->nest_level = dev_get_nest_level(bond_dev) + 1;
        }
 
        unblock_netpoll_tx();
@@ -2017,7 +2013,8 @@ static int __bond_release_one(struct net_device *bond_dev,
        else
                dev_set_mtu(slave_dev, slave->original_mtu);
 
-       slave_dev->priv_flags &= ~IFF_BONDING;
+       if (!netif_is_bond_master(slave_dev))
+               slave_dev->priv_flags &= ~IFF_BONDING;
 
        bond_free_slave(slave);
 
@@ -2086,8 +2083,7 @@ static int bond_miimon_inspect(struct bonding *bond)
        ignore_updelay = !rcu_dereference(bond->curr_active_slave);
 
        bond_for_each_slave_rcu(bond, slave, iter) {
-               slave->new_link = BOND_LINK_NOCHANGE;
-               slave->link_new_state = slave->link;
+               bond_propose_link_state(slave, BOND_LINK_NOCHANGE);
 
                link_state = bond_check_dev_link(bond, slave->dev, 0);
 
@@ -2121,7 +2117,7 @@ static int bond_miimon_inspect(struct bonding *bond)
                        }
 
                        if (slave->delay <= 0) {
-                               slave->new_link = BOND_LINK_DOWN;
+                               bond_propose_link_state(slave, BOND_LINK_DOWN);
                                commit++;
                                continue;
                        }
@@ -2158,7 +2154,7 @@ static int bond_miimon_inspect(struct bonding *bond)
                                slave->delay = 0;
 
                        if (slave->delay <= 0) {
-                               slave->new_link = BOND_LINK_UP;
+                               bond_propose_link_state(slave, BOND_LINK_UP);
                                commit++;
                                ignore_updelay = false;
                                continue;
@@ -2196,7 +2192,7 @@ static void bond_miimon_commit(struct bonding *bond)
        struct slave *slave, *primary;
 
        bond_for_each_slave(bond, slave, iter) {
-               switch (slave->new_link) {
+               switch (slave->link_new_state) {
                case BOND_LINK_NOCHANGE:
                        /* For 802.3ad mode, check current slave speed and
                         * duplex again in case its port was disabled after
@@ -2268,8 +2264,8 @@ static void bond_miimon_commit(struct bonding *bond)
 
                default:
                        slave_err(bond->dev, slave->dev, "invalid new link %d on slave\n",
-                                 slave->new_link);
-                       slave->new_link = BOND_LINK_NOCHANGE;
+                                 slave->link_new_state);
+                       bond_propose_link_state(slave, BOND_LINK_NOCHANGE);
 
                        continue;
                }
@@ -2677,13 +2673,13 @@ static void bond_loadbalance_arp_mon(struct bonding *bond)
        bond_for_each_slave_rcu(bond, slave, iter) {
                unsigned long trans_start = dev_trans_start(slave->dev);
 
-               slave->new_link = BOND_LINK_NOCHANGE;
+               bond_propose_link_state(slave, BOND_LINK_NOCHANGE);
 
                if (slave->link != BOND_LINK_UP) {
                        if (bond_time_in_interval(bond, trans_start, 1) &&
                            bond_time_in_interval(bond, slave->last_rx, 1)) {
 
-                               slave->new_link = BOND_LINK_UP;
+                               bond_propose_link_state(slave, BOND_LINK_UP);
                                slave_state_changed = 1;
 
                                /* primary_slave has no meaning in round-robin
@@ -2708,7 +2704,7 @@ static void bond_loadbalance_arp_mon(struct bonding *bond)
                        if (!bond_time_in_interval(bond, trans_start, 2) ||
                            !bond_time_in_interval(bond, slave->last_rx, 2)) {
 
-                               slave->new_link = BOND_LINK_DOWN;
+                               bond_propose_link_state(slave, BOND_LINK_DOWN);
                                slave_state_changed = 1;
 
                                if (slave->link_failure_count < UINT_MAX)
@@ -2739,8 +2735,8 @@ static void bond_loadbalance_arp_mon(struct bonding *bond)
                        goto re_arm;
 
                bond_for_each_slave(bond, slave, iter) {
-                       if (slave->new_link != BOND_LINK_NOCHANGE)
-                               slave->link = slave->new_link;
+                       if (slave->link_new_state != BOND_LINK_NOCHANGE)
+                               slave->link = slave->link_new_state;
                }
 
                if (slave_state_changed) {
@@ -2763,9 +2759,9 @@ re_arm:
 }
 
 /* Called to inspect slaves for active-backup mode ARP monitor link state
- * changes.  Sets new_link in slaves to specify what action should take
- * place for the slave.  Returns 0 if no changes are found, >0 if changes
- * to link states must be committed.
+ * changes.  Sets proposed link state in slaves to specify what action
+ * should take place for the slave.  Returns 0 if no changes are found, >0
+ * if changes to link states must be committed.
  *
  * Called with rcu_read_lock held.
  */
@@ -2777,12 +2773,12 @@ static int bond_ab_arp_inspect(struct bonding *bond)
        int commit = 0;
 
        bond_for_each_slave_rcu(bond, slave, iter) {
-               slave->new_link = BOND_LINK_NOCHANGE;
+               bond_propose_link_state(slave, BOND_LINK_NOCHANGE);
                last_rx = slave_last_rx(bond, slave);
 
                if (slave->link != BOND_LINK_UP) {
                        if (bond_time_in_interval(bond, last_rx, 1)) {
-                               slave->new_link = BOND_LINK_UP;
+                               bond_propose_link_state(slave, BOND_LINK_UP);
                                commit++;
                        }
                        continue;
@@ -2810,7 +2806,7 @@ static int bond_ab_arp_inspect(struct bonding *bond)
                if (!bond_is_active_slave(slave) &&
                    !rcu_access_pointer(bond->current_arp_slave) &&
                    !bond_time_in_interval(bond, last_rx, 3)) {
-                       slave->new_link = BOND_LINK_DOWN;
+                       bond_propose_link_state(slave, BOND_LINK_DOWN);
                        commit++;
                }
 
@@ -2823,7 +2819,7 @@ static int bond_ab_arp_inspect(struct bonding *bond)
                if (bond_is_active_slave(slave) &&
                    (!bond_time_in_interval(bond, trans_start, 2) ||
                     !bond_time_in_interval(bond, last_rx, 2))) {
-                       slave->new_link = BOND_LINK_DOWN;
+                       bond_propose_link_state(slave, BOND_LINK_DOWN);
                        commit++;
                }
        }
@@ -2843,7 +2839,7 @@ static void bond_ab_arp_commit(struct bonding *bond)
        struct slave *slave;
 
        bond_for_each_slave(bond, slave, iter) {
-               switch (slave->new_link) {
+               switch (slave->link_new_state) {
                case BOND_LINK_NOCHANGE:
                        continue;
 
@@ -2893,8 +2889,9 @@ static void bond_ab_arp_commit(struct bonding *bond)
                        continue;
 
                default:
-                       slave_err(bond->dev, slave->dev, "impossible: new_link %d on slave\n",
-                                 slave->new_link);
+                       slave_err(bond->dev, slave->dev,
+                                 "impossible: link_new_state %d on slave\n",
+                                 slave->link_new_state);
                        continue;
                }
 
@@ -3442,13 +3439,6 @@ static void bond_fold_stats(struct rtnl_link_stats64 *_res,
        }
 }
 
-static int bond_get_nest_level(struct net_device *bond_dev)
-{
-       struct bonding *bond = netdev_priv(bond_dev);
-
-       return bond->nest_level;
-}
-
 static void bond_get_stats(struct net_device *bond_dev,
                           struct rtnl_link_stats64 *stats)
 {
@@ -3457,7 +3447,7 @@ static void bond_get_stats(struct net_device *bond_dev,
        struct list_head *iter;
        struct slave *slave;
 
-       spin_lock_nested(&bond->stats_lock, bond_get_nest_level(bond_dev));
+       spin_lock(&bond->stats_lock);
        memcpy(stats, &bond->bond_stats, sizeof(*stats));
 
        rcu_read_lock();
@@ -4268,7 +4258,6 @@ static const struct net_device_ops bond_netdev_ops = {
        .ndo_neigh_setup        = bond_neigh_setup,
        .ndo_vlan_rx_add_vid    = bond_vlan_rx_add_vid,
        .ndo_vlan_rx_kill_vid   = bond_vlan_rx_kill_vid,
-       .ndo_get_lock_subclass  = bond_get_nest_level,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_netpoll_setup      = bond_netpoll_setup,
        .ndo_netpoll_cleanup    = bond_netpoll_cleanup,
@@ -4296,7 +4285,6 @@ void bond_setup(struct net_device *bond_dev)
        struct bonding *bond = netdev_priv(bond_dev);
 
        spin_lock_init(&bond->mode_lock);
-       spin_lock_init(&bond->stats_lock);
        bond->params = bonding_defaults;
 
        /* Initialize pointers */
@@ -4365,6 +4353,7 @@ static void bond_uninit(struct net_device *bond_dev)
 
        list_del(&bond->bond_list);
 
+       lockdep_unregister_key(&bond->stats_lock_key);
        bond_debug_unregister(bond);
 }
 
@@ -4768,8 +4757,9 @@ static int bond_init(struct net_device *bond_dev)
        if (!bond->wq)
                return -ENOMEM;
 
-       bond->nest_level = SINGLE_DEPTH_NESTING;
-       netdev_lockdep_set_classes(bond_dev);
+       spin_lock_init(&bond->stats_lock);
+       lockdep_register_key(&bond->stats_lock_key);
+       lockdep_set_class(&bond->stats_lock, &bond->stats_lock_key);
 
        list_add_tail(&bond->bond_list, &bn->dev_list);
 
index 606b7d8ffe138f880bfc830eff10b84ba6a01cfe..8e9f5620c9a21e6a921963c4244779201e102ded 100644 (file)
@@ -52,6 +52,7 @@
 #define CONTROL_EX_PDR         BIT(8)
 
 /* control register */
+#define CONTROL_SWR            BIT(15)
 #define CONTROL_TEST           BIT(7)
 #define CONTROL_CCE            BIT(6)
 #define CONTROL_DISABLE_AR     BIT(5)
@@ -97,6 +98,9 @@
 #define BTR_TSEG2_SHIFT                12
 #define BTR_TSEG2_MASK         (0x7 << BTR_TSEG2_SHIFT)
 
+/* interrupt register */
+#define INT_STS_PENDING                0x8000
+
 /* brp extension register */
 #define BRP_EXT_BRPE_MASK      0x0f
 #define BRP_EXT_BRPE_SHIFT     0
@@ -569,6 +573,26 @@ static void c_can_configure_msg_objects(struct net_device *dev)
                                   IF_MCONT_RCV_EOB);
 }
 
+static int c_can_software_reset(struct net_device *dev)
+{
+       struct c_can_priv *priv = netdev_priv(dev);
+       int retry = 0;
+
+       if (priv->type != BOSCH_D_CAN)
+               return 0;
+
+       priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_SWR | CONTROL_INIT);
+       while (priv->read_reg(priv, C_CAN_CTRL_REG) & CONTROL_SWR) {
+               msleep(20);
+               if (retry++ > 100) {
+                       netdev_err(dev, "CCTRL: software reset failed\n");
+                       return -EIO;
+               }
+       }
+
+       return 0;
+}
+
 /*
  * Configure C_CAN chip:
  * - enable/disable auto-retransmission
@@ -578,6 +602,11 @@ static void c_can_configure_msg_objects(struct net_device *dev)
 static int c_can_chip_config(struct net_device *dev)
 {
        struct c_can_priv *priv = netdev_priv(dev);
+       int err;
+
+       err = c_can_software_reset(dev);
+       if (err)
+               return err;
 
        /* enable automatic retransmission */
        priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_ENABLE_AR);
@@ -886,6 +915,9 @@ static int c_can_handle_state_change(struct net_device *dev,
        struct can_berr_counter bec;
 
        switch (error_type) {
+       case C_CAN_NO_ERROR:
+               priv->can.state = CAN_STATE_ERROR_ACTIVE;
+               break;
        case C_CAN_ERROR_WARNING:
                /* error warning state */
                priv->can.can_stats.error_warning++;
@@ -916,6 +948,13 @@ static int c_can_handle_state_change(struct net_device *dev,
                                ERR_CNT_RP_SHIFT;
 
        switch (error_type) {
+       case C_CAN_NO_ERROR:
+               /* error warning state */
+               cf->can_id |= CAN_ERR_CRTL;
+               cf->data[1] = CAN_ERR_CRTL_ACTIVE;
+               cf->data[6] = bec.txerr;
+               cf->data[7] = bec.rxerr;
+               break;
        case C_CAN_ERROR_WARNING:
                /* error warning state */
                cf->can_id |= CAN_ERR_CRTL;
@@ -1029,10 +1068,16 @@ static int c_can_poll(struct napi_struct *napi, int quota)
        u16 curr, last = priv->last_status;
        int work_done = 0;
 
-       priv->last_status = curr = priv->read_reg(priv, C_CAN_STS_REG);
-       /* Ack status on C_CAN. D_CAN is self clearing */
-       if (priv->type != BOSCH_D_CAN)
-               priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED);
+       /* Only read the status register if a status interrupt was pending */
+       if (atomic_xchg(&priv->sie_pending, 0)) {
+               priv->last_status = curr = priv->read_reg(priv, C_CAN_STS_REG);
+               /* Ack status on C_CAN. D_CAN is self clearing */
+               if (priv->type != BOSCH_D_CAN)
+                       priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED);
+       } else {
+               /* no change detected ... */
+               curr = last;
+       }
 
        /* handle state changes */
        if ((curr & STATUS_EWARN) && (!(last & STATUS_EWARN))) {
@@ -1054,11 +1099,17 @@ static int c_can_poll(struct napi_struct *napi, int quota)
        /* handle bus recovery events */
        if ((!(curr & STATUS_BOFF)) && (last & STATUS_BOFF)) {
                netdev_dbg(dev, "left bus off state\n");
-               priv->can.state = CAN_STATE_ERROR_ACTIVE;
+               work_done += c_can_handle_state_change(dev, C_CAN_ERROR_PASSIVE);
        }
+
        if ((!(curr & STATUS_EPASS)) && (last & STATUS_EPASS)) {
                netdev_dbg(dev, "left error passive state\n");
-               priv->can.state = CAN_STATE_ERROR_ACTIVE;
+               work_done += c_can_handle_state_change(dev, C_CAN_ERROR_WARNING);
+       }
+
+       if ((!(curr & STATUS_EWARN)) && (last & STATUS_EWARN)) {
+               netdev_dbg(dev, "left error warning state\n");
+               work_done += c_can_handle_state_change(dev, C_CAN_NO_ERROR);
        }
 
        /* handle lec errors on the bus */
@@ -1083,10 +1134,16 @@ static irqreturn_t c_can_isr(int irq, void *dev_id)
 {
        struct net_device *dev = (struct net_device *)dev_id;
        struct c_can_priv *priv = netdev_priv(dev);
+       int reg_int;
 
-       if (!priv->read_reg(priv, C_CAN_INT_REG))
+       reg_int = priv->read_reg(priv, C_CAN_INT_REG);
+       if (!reg_int)
                return IRQ_NONE;
 
+       /* save for later use */
+       if (reg_int & INT_STS_PENDING)
+               atomic_set(&priv->sie_pending, 1);
+
        /* disable all interrupts and schedule the NAPI */
        c_can_irq_control(priv, false);
        napi_schedule(&priv->napi);
index 8acdc7fa4792f24438cb0cd84d73b44f0c46f7d8..d5567a7c1c6d4652a04f8135b381387e3a2e5304 100644 (file)
@@ -198,6 +198,7 @@ struct c_can_priv {
        struct net_device *dev;
        struct device *device;
        atomic_t tx_active;
+       atomic_t sie_pending;
        unsigned long tx_dir;
        int last_status;
        u16 (*read_reg) (const struct c_can_priv *priv, enum reg index);
index ac86be52b461703fbd512cb528896f2bc9538611..1c88c361938cceb5effdfb8b593f1000be2fc800 100644 (file)
@@ -848,6 +848,7 @@ void of_can_transceiver(struct net_device *dev)
                return;
 
        ret = of_property_read_u32(dn, "max-bitrate", &priv->bitrate_max);
+       of_node_put(dn);
        if ((ret && ret != -EINVAL) || (!ret && !priv->bitrate_max))
                netdev_warn(dev, "Invalid value for transceiver max bitrate. Ignoring bitrate limit.\n");
 }
index dc5695dffc2e371cc13315badd3569ef09786b1f..57f9a2f51085f9095b458f68e28f55ab7137e624 100644 (file)
@@ -677,6 +677,7 @@ static void flexcan_irq_bus_err(struct net_device *dev, u32 reg_esr)
        struct can_frame *cf;
        bool rx_errors = false, tx_errors = false;
        u32 timestamp;
+       int err;
 
        timestamp = priv->read(&regs->timer) << 16;
 
@@ -725,7 +726,9 @@ static void flexcan_irq_bus_err(struct net_device *dev, u32 reg_esr)
        if (tx_errors)
                dev->stats.tx_errors++;
 
-       can_rx_offload_queue_sorted(&priv->offload, skb, timestamp);
+       err = can_rx_offload_queue_sorted(&priv->offload, skb, timestamp);
+       if (err)
+               dev->stats.rx_fifo_errors++;
 }
 
 static void flexcan_irq_state(struct net_device *dev, u32 reg_esr)
@@ -738,6 +741,7 @@ static void flexcan_irq_state(struct net_device *dev, u32 reg_esr)
        int flt;
        struct can_berr_counter bec;
        u32 timestamp;
+       int err;
 
        timestamp = priv->read(&regs->timer) << 16;
 
@@ -769,7 +773,9 @@ static void flexcan_irq_state(struct net_device *dev, u32 reg_esr)
        if (unlikely(new_state == CAN_STATE_BUS_OFF))
                can_bus_off(dev);
 
-       can_rx_offload_queue_sorted(&priv->offload, skb, timestamp);
+       err = can_rx_offload_queue_sorted(&priv->offload, skb, timestamp);
+       if (err)
+               dev->stats.rx_fifo_errors++;
 }
 
 static inline struct flexcan_priv *rx_offload_to_priv(struct can_rx_offload *offload)
@@ -1188,6 +1194,7 @@ static int flexcan_chip_start(struct net_device *dev)
                reg_mecr = priv->read(&regs->mecr);
                reg_mecr &= ~FLEXCAN_MECR_ECRWRDIS;
                priv->write(reg_mecr, &regs->mecr);
+               reg_mecr |= FLEXCAN_MECR_ECCDIS;
                reg_mecr &= ~(FLEXCAN_MECR_NCEFAFRZ | FLEXCAN_MECR_HANCEI_MSK |
                              FLEXCAN_MECR_FANCEI_MSK);
                priv->write(reg_mecr, &regs->mecr);
index e6a668ee77306a1859872cf543d68ef59cf8667d..84cae167e42f654090e0c2f0be8583d541030f19 100644 (file)
@@ -107,37 +107,95 @@ static int can_rx_offload_compare(struct sk_buff *a, struct sk_buff *b)
        return cb_b->timestamp - cb_a->timestamp;
 }
 
-static struct sk_buff *can_rx_offload_offload_one(struct can_rx_offload *offload, unsigned int n)
+/**
+ * can_rx_offload_offload_one() - Read one CAN frame from HW
+ * @offload: pointer to rx_offload context
+ * @n: number of mailbox to read
+ *
+ * The task of this function is to read a CAN frame from mailbox @n
+ * from the device and return the mailbox's content as a struct
+ * sk_buff.
+ *
+ * If the struct can_rx_offload::skb_queue exceeds the maximal queue
+ * length (struct can_rx_offload::skb_queue_len_max) or no skb can be
+ * allocated, the mailbox contents is discarded by reading it into an
+ * overflow buffer. This way the mailbox is marked as free by the
+ * driver.
+ *
+ * Return: A pointer to skb containing the CAN frame on success.
+ *
+ *         NULL if the mailbox @n is empty.
+ *
+ *         ERR_PTR() in case of an error
+ */
+static struct sk_buff *
+can_rx_offload_offload_one(struct can_rx_offload *offload, unsigned int n)
 {
-       struct sk_buff *skb = NULL;
+       struct sk_buff *skb = NULL, *skb_error = NULL;
        struct can_rx_offload_cb *cb;
        struct can_frame *cf;
        int ret;
 
-       /* If queue is full or skb not available, read to discard mailbox */
-       if (likely(skb_queue_len(&offload->skb_queue) <=
-                  offload->skb_queue_len_max))
+       if (likely(skb_queue_len(&offload->skb_queue) <
+                  offload->skb_queue_len_max)) {
                skb = alloc_can_skb(offload->dev, &cf);
+               if (unlikely(!skb))
+                       skb_error = ERR_PTR(-ENOMEM);   /* skb alloc failed */
+       } else {
+               skb_error = ERR_PTR(-ENOBUFS);          /* skb_queue is full */
+       }
 
-       if (!skb) {
+       /* If queue is full or skb not available, drop by reading into
+        * overflow buffer.
+        */
+       if (unlikely(skb_error)) {
                struct can_frame cf_overflow;
                u32 timestamp;
 
                ret = offload->mailbox_read(offload, &cf_overflow,
                                            &timestamp, n);
-               if (ret)
-                       offload->dev->stats.rx_dropped++;
 
-               return NULL;
+               /* Mailbox was empty. */
+               if (unlikely(!ret))
+                       return NULL;
+
+               /* Mailbox has been read and we're dropping it or
+                * there was a problem reading the mailbox.
+                *
+                * Increment error counters in any case.
+                */
+               offload->dev->stats.rx_dropped++;
+               offload->dev->stats.rx_fifo_errors++;
+
+               /* There was a problem reading the mailbox, propagate
+                * error value.
+                */
+               if (unlikely(ret < 0))
+                       return ERR_PTR(ret);
+
+               return skb_error;
        }
 
        cb = can_rx_offload_get_cb(skb);
        ret = offload->mailbox_read(offload, cf, &cb->timestamp, n);
-       if (!ret) {
+
+       /* Mailbox was empty. */
+       if (unlikely(!ret)) {
                kfree_skb(skb);
                return NULL;
        }
 
+       /* There was a problem reading the mailbox, propagate error value. */
+       if (unlikely(ret < 0)) {
+               kfree_skb(skb);
+
+               offload->dev->stats.rx_dropped++;
+               offload->dev->stats.rx_fifo_errors++;
+
+               return ERR_PTR(ret);
+       }
+
+       /* Mailbox was read. */
        return skb;
 }
 
@@ -157,8 +215,8 @@ int can_rx_offload_irq_offload_timestamp(struct can_rx_offload *offload, u64 pen
                        continue;
 
                skb = can_rx_offload_offload_one(offload, i);
-               if (!skb)
-                       break;
+               if (IS_ERR_OR_NULL(skb))
+                       continue;
 
                __skb_queue_add_sort(&skb_queue, skb, can_rx_offload_compare);
        }
@@ -188,7 +246,13 @@ int can_rx_offload_irq_offload_fifo(struct can_rx_offload *offload)
        struct sk_buff *skb;
        int received = 0;
 
-       while ((skb = can_rx_offload_offload_one(offload, 0))) {
+       while (1) {
+               skb = can_rx_offload_offload_one(offload, 0);
+               if (IS_ERR(skb))
+                       continue;
+               if (!skb)
+                       break;
+
                skb_queue_tail(&offload->skb_queue, skb);
                received++;
        }
@@ -207,8 +271,10 @@ int can_rx_offload_queue_sorted(struct can_rx_offload *offload,
        unsigned long flags;
 
        if (skb_queue_len(&offload->skb_queue) >
-           offload->skb_queue_len_max)
-               return -ENOMEM;
+           offload->skb_queue_len_max) {
+               kfree_skb(skb);
+               return -ENOBUFS;
+       }
 
        cb = can_rx_offload_get_cb(skb);
        cb->timestamp = timestamp;
@@ -250,8 +316,10 @@ int can_rx_offload_queue_tail(struct can_rx_offload *offload,
                              struct sk_buff *skb)
 {
        if (skb_queue_len(&offload->skb_queue) >
-           offload->skb_queue_len_max)
-               return -ENOMEM;
+           offload->skb_queue_len_max) {
+               kfree_skb(skb);
+               return -ENOBUFS;
+       }
 
        skb_queue_tail(&offload->skb_queue, skb);
        can_rx_offload_schedule(offload);
index bee9f7b8dad61d27e1c1cd16a0f4a8e706aa0622..bb20a9b75cc66bd2ea3ec1406bbb8d3dac3435a7 100644 (file)
@@ -717,6 +717,7 @@ static void mcp251x_restart_work_handler(struct work_struct *ws)
        if (priv->after_suspend) {
                mcp251x_hw_reset(spi);
                mcp251x_setup(net, spi);
+               priv->force_quit = 0;
                if (priv->after_suspend & AFTER_SUSPEND_RESTART) {
                        mcp251x_set_normal_mode(spi);
                } else if (priv->after_suspend & AFTER_SUSPEND_UP) {
@@ -728,7 +729,6 @@ static void mcp251x_restart_work_handler(struct work_struct *ws)
                        mcp251x_hw_sleep(spi);
                }
                priv->after_suspend = 0;
-               priv->force_quit = 0;
        }
 
        if (priv->restart_tx) {
index f8b19eef5d26868f6132b2d465af7de18136dfdc..31ad364a89bbe61295b63d83f719a1888642a3e3 100644 (file)
@@ -73,6 +73,7 @@ MODULE_VERSION(HECC_MODULE_VERSION);
  */
 #define HECC_MAX_RX_MBOX       (HECC_MAX_MAILBOXES - HECC_MAX_TX_MBOX)
 #define HECC_RX_FIRST_MBOX     (HECC_MAX_MAILBOXES - 1)
+#define HECC_RX_LAST_MBOX      (HECC_MAX_TX_MBOX)
 
 /* TI HECC module registers */
 #define HECC_CANME             0x0     /* Mailbox enable */
@@ -82,7 +83,7 @@ MODULE_VERSION(HECC_MODULE_VERSION);
 #define HECC_CANTA             0x10    /* Transmission acknowledge */
 #define HECC_CANAA             0x14    /* Abort acknowledge */
 #define HECC_CANRMP            0x18    /* Receive message pending */
-#define HECC_CANRML            0x1C    /* Remote message lost */
+#define HECC_CANRML            0x1C    /* Receive message lost */
 #define HECC_CANRFP            0x20    /* Remote frame pending */
 #define HECC_CANGAM            0x24    /* SECC only:Global acceptance mask */
 #define HECC_CANMC             0x28    /* Master control */
@@ -149,6 +150,8 @@ MODULE_VERSION(HECC_MODULE_VERSION);
 #define HECC_BUS_ERROR         (HECC_CANES_FE | HECC_CANES_BE |\
                                HECC_CANES_CRCE | HECC_CANES_SE |\
                                HECC_CANES_ACKE)
+#define HECC_CANES_FLAGS       (HECC_BUS_ERROR | HECC_CANES_BO |\
+                               HECC_CANES_EP | HECC_CANES_EW)
 
 #define HECC_CANMCF_RTR                BIT(4)  /* Remote transmit request */
 
@@ -382,8 +385,18 @@ static void ti_hecc_start(struct net_device *ndev)
                hecc_set_bit(priv, HECC_CANMIM, mbx_mask);
        }
 
-       /* Prevent message over-write & Enable interrupts */
-       hecc_write(priv, HECC_CANOPC, HECC_SET_REG);
+       /* Enable tx interrupts */
+       hecc_set_bit(priv, HECC_CANMIM, BIT(HECC_MAX_TX_MBOX) - 1);
+
+       /* Prevent message over-write to create a rx fifo, but not for
+        * the lowest priority mailbox, since that allows detecting
+        * overflows instead of the hardware silently dropping the
+        * messages.
+        */
+       mbx_mask = ~BIT(HECC_RX_LAST_MBOX);
+       hecc_write(priv, HECC_CANOPC, mbx_mask);
+
+       /* Enable interrupts */
        if (priv->use_hecc1int) {
                hecc_write(priv, HECC_CANMIL, HECC_SET_REG);
                hecc_write(priv, HECC_CANGIM, HECC_CANGIM_DEF_MASK |
@@ -400,6 +413,9 @@ static void ti_hecc_stop(struct net_device *ndev)
 {
        struct ti_hecc_priv *priv = netdev_priv(ndev);
 
+       /* Disable the CPK; stop sending, erroring and acking */
+       hecc_set_bit(priv, HECC_CANMC, HECC_CANMC_CCR);
+
        /* Disable interrupts and disable mailboxes */
        hecc_write(priv, HECC_CANGIM, 0);
        hecc_write(priv, HECC_CANMIM, 0);
@@ -508,8 +524,6 @@ static netdev_tx_t ti_hecc_xmit(struct sk_buff *skb, struct net_device *ndev)
        hecc_set_bit(priv, HECC_CANME, mbx_mask);
        spin_unlock_irqrestore(&priv->mbx_lock, flags);
 
-       hecc_clear_bit(priv, HECC_CANMD, mbx_mask);
-       hecc_set_bit(priv, HECC_CANMIM, mbx_mask);
        hecc_write(priv, HECC_CANTRS, mbx_mask);
 
        return NETDEV_TX_OK;
@@ -526,8 +540,10 @@ static unsigned int ti_hecc_mailbox_read(struct can_rx_offload *offload,
                                         u32 *timestamp, unsigned int mbxno)
 {
        struct ti_hecc_priv *priv = rx_offload_to_priv(offload);
-       u32 data;
+       u32 data, mbx_mask;
+       int ret = 1;
 
+       mbx_mask = BIT(mbxno);
        data = hecc_read_mbx(priv, mbxno, HECC_CANMID);
        if (data & HECC_CANMID_IDE)
                cf->can_id = (data & CAN_EFF_MASK) | CAN_EFF_FLAG;
@@ -548,7 +564,25 @@ static unsigned int ti_hecc_mailbox_read(struct can_rx_offload *offload,
 
        *timestamp = hecc_read_stamp(priv, mbxno);
 
-       return 1;
+       /* Check for FIFO overrun.
+        *
+        * All but the last RX mailbox have activated overwrite
+        * protection. So skip check for overrun, if we're not
+        * handling the last RX mailbox.
+        *
+        * As the overwrite protection for the last RX mailbox is
+        * disabled, the CAN core might update while we're reading
+        * it. This means the skb might be inconsistent.
+        *
+        * Return an error to let rx-offload discard this CAN frame.
+        */
+       if (unlikely(mbxno == HECC_RX_LAST_MBOX &&
+                    hecc_read(priv, HECC_CANRML) & mbx_mask))
+               ret = -ENOBUFS;
+
+       hecc_write(priv, HECC_CANRMP, mbx_mask);
+
+       return ret;
 }
 
 static int ti_hecc_error(struct net_device *ndev, int int_status,
@@ -558,92 +592,73 @@ static int ti_hecc_error(struct net_device *ndev, int int_status,
        struct can_frame *cf;
        struct sk_buff *skb;
        u32 timestamp;
+       int err;
 
-       /* propagate the error condition to the can stack */
-       skb = alloc_can_err_skb(ndev, &cf);
-       if (!skb) {
-               if (printk_ratelimit())
-                       netdev_err(priv->ndev,
-                                  "%s: alloc_can_err_skb() failed\n",
-                                  __func__);
-               return -ENOMEM;
-       }
-
-       if (int_status & HECC_CANGIF_WLIF) { /* warning level int */
-               if ((int_status & HECC_CANGIF_BOIF) == 0) {
-                       priv->can.state = CAN_STATE_ERROR_WARNING;
-                       ++priv->can.can_stats.error_warning;
-                       cf->can_id |= CAN_ERR_CRTL;
-                       if (hecc_read(priv, HECC_CANTEC) > 96)
-                               cf->data[1] |= CAN_ERR_CRTL_TX_WARNING;
-                       if (hecc_read(priv, HECC_CANREC) > 96)
-                               cf->data[1] |= CAN_ERR_CRTL_RX_WARNING;
-               }
-               hecc_set_bit(priv, HECC_CANES, HECC_CANES_EW);
-               netdev_dbg(priv->ndev, "Error Warning interrupt\n");
-               hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_CCR);
-       }
-
-       if (int_status & HECC_CANGIF_EPIF) { /* error passive int */
-               if ((int_status & HECC_CANGIF_BOIF) == 0) {
-                       priv->can.state = CAN_STATE_ERROR_PASSIVE;
-                       ++priv->can.can_stats.error_passive;
-                       cf->can_id |= CAN_ERR_CRTL;
-                       if (hecc_read(priv, HECC_CANTEC) > 127)
-                               cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
-                       if (hecc_read(priv, HECC_CANREC) > 127)
-                               cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
+       if (err_status & HECC_BUS_ERROR) {
+               /* propagate the error condition to the can stack */
+               skb = alloc_can_err_skb(ndev, &cf);
+               if (!skb) {
+                       if (net_ratelimit())
+                               netdev_err(priv->ndev,
+                                          "%s: alloc_can_err_skb() failed\n",
+                                          __func__);
+                       return -ENOMEM;
                }
-               hecc_set_bit(priv, HECC_CANES, HECC_CANES_EP);
-               netdev_dbg(priv->ndev, "Error passive interrupt\n");
-               hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_CCR);
-       }
-
-       /* Need to check busoff condition in error status register too to
-        * ensure warning interrupts don't hog the system
-        */
-       if ((int_status & HECC_CANGIF_BOIF) || (err_status & HECC_CANES_BO)) {
-               priv->can.state = CAN_STATE_BUS_OFF;
-               cf->can_id |= CAN_ERR_BUSOFF;
-               hecc_set_bit(priv, HECC_CANES, HECC_CANES_BO);
-               hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_CCR);
-               /* Disable all interrupts in bus-off to avoid int hog */
-               hecc_write(priv, HECC_CANGIM, 0);
-               ++priv->can.can_stats.bus_off;
-               can_bus_off(ndev);
-       }
 
-       if (err_status & HECC_BUS_ERROR) {
                ++priv->can.can_stats.bus_error;
                cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT;
-               if (err_status & HECC_CANES_FE) {
-                       hecc_set_bit(priv, HECC_CANES, HECC_CANES_FE);
+               if (err_status & HECC_CANES_FE)
                        cf->data[2] |= CAN_ERR_PROT_FORM;
-               }
-               if (err_status & HECC_CANES_BE) {
-                       hecc_set_bit(priv, HECC_CANES, HECC_CANES_BE);
+               if (err_status & HECC_CANES_BE)
                        cf->data[2] |= CAN_ERR_PROT_BIT;
-               }
-               if (err_status & HECC_CANES_SE) {
-                       hecc_set_bit(priv, HECC_CANES, HECC_CANES_SE);
+               if (err_status & HECC_CANES_SE)
                        cf->data[2] |= CAN_ERR_PROT_STUFF;
-               }
-               if (err_status & HECC_CANES_CRCE) {
-                       hecc_set_bit(priv, HECC_CANES, HECC_CANES_CRCE);
+               if (err_status & HECC_CANES_CRCE)
                        cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
-               }
-               if (err_status & HECC_CANES_ACKE) {
-                       hecc_set_bit(priv, HECC_CANES, HECC_CANES_ACKE);
+               if (err_status & HECC_CANES_ACKE)
                        cf->data[3] = CAN_ERR_PROT_LOC_ACK;
-               }
+
+               timestamp = hecc_read(priv, HECC_CANLNT);
+               err = can_rx_offload_queue_sorted(&priv->offload, skb,
+                                                 timestamp);
+               if (err)
+                       ndev->stats.rx_fifo_errors++;
        }
 
-       timestamp = hecc_read(priv, HECC_CANLNT);
-       can_rx_offload_queue_sorted(&priv->offload, skb, timestamp);
+       hecc_write(priv, HECC_CANES, HECC_CANES_FLAGS);
 
        return 0;
 }
 
+static void ti_hecc_change_state(struct net_device *ndev,
+                                enum can_state rx_state,
+                                enum can_state tx_state)
+{
+       struct ti_hecc_priv *priv = netdev_priv(ndev);
+       struct can_frame *cf;
+       struct sk_buff *skb;
+       u32 timestamp;
+       int err;
+
+       skb = alloc_can_err_skb(priv->ndev, &cf);
+       if (unlikely(!skb)) {
+               priv->can.state = max(tx_state, rx_state);
+               return;
+       }
+
+       can_change_state(priv->ndev, cf, tx_state, rx_state);
+
+       if (max(tx_state, rx_state) != CAN_STATE_BUS_OFF) {
+               cf->data[6] = hecc_read(priv, HECC_CANTEC);
+               cf->data[7] = hecc_read(priv, HECC_CANREC);
+       }
+
+       timestamp = hecc_read(priv, HECC_CANLNT);
+       err = can_rx_offload_queue_sorted(&priv->offload, skb, timestamp);
+       if (err)
+               ndev->stats.rx_fifo_errors++;
+}
+
 static irqreturn_t ti_hecc_interrupt(int irq, void *dev_id)
 {
        struct net_device *ndev = (struct net_device *)dev_id;
@@ -651,6 +666,7 @@ static irqreturn_t ti_hecc_interrupt(int irq, void *dev_id)
        struct net_device_stats *stats = &ndev->stats;
        u32 mbxno, mbx_mask, int_status, err_status, stamp;
        unsigned long flags, rx_pending;
+       u32 handled = 0;
 
        int_status = hecc_read(priv,
                               priv->use_hecc1int ?
@@ -660,17 +676,66 @@ static irqreturn_t ti_hecc_interrupt(int irq, void *dev_id)
                return IRQ_NONE;
 
        err_status = hecc_read(priv, HECC_CANES);
-       if (err_status & (HECC_BUS_ERROR | HECC_CANES_BO |
-                         HECC_CANES_EP | HECC_CANES_EW))
+       if (unlikely(err_status & HECC_CANES_FLAGS))
                ti_hecc_error(ndev, int_status, err_status);
 
+       if (unlikely(int_status & HECC_CANGIM_DEF_MASK)) {
+               enum can_state rx_state, tx_state;
+               u32 rec = hecc_read(priv, HECC_CANREC);
+               u32 tec = hecc_read(priv, HECC_CANTEC);
+
+               if (int_status & HECC_CANGIF_WLIF) {
+                       handled |= HECC_CANGIF_WLIF;
+                       rx_state = rec >= tec ? CAN_STATE_ERROR_WARNING : 0;
+                       tx_state = rec <= tec ? CAN_STATE_ERROR_WARNING : 0;
+                       netdev_dbg(priv->ndev, "Error Warning interrupt\n");
+                       ti_hecc_change_state(ndev, rx_state, tx_state);
+               }
+
+               if (int_status & HECC_CANGIF_EPIF) {
+                       handled |= HECC_CANGIF_EPIF;
+                       rx_state = rec >= tec ? CAN_STATE_ERROR_PASSIVE : 0;
+                       tx_state = rec <= tec ? CAN_STATE_ERROR_PASSIVE : 0;
+                       netdev_dbg(priv->ndev, "Error passive interrupt\n");
+                       ti_hecc_change_state(ndev, rx_state, tx_state);
+               }
+
+               if (int_status & HECC_CANGIF_BOIF) {
+                       handled |= HECC_CANGIF_BOIF;
+                       rx_state = CAN_STATE_BUS_OFF;
+                       tx_state = CAN_STATE_BUS_OFF;
+                       netdev_dbg(priv->ndev, "Bus off interrupt\n");
+
+                       /* Disable all interrupts */
+                       hecc_write(priv, HECC_CANGIM, 0);
+                       can_bus_off(ndev);
+                       ti_hecc_change_state(ndev, rx_state, tx_state);
+               }
+       } else if (unlikely(priv->can.state != CAN_STATE_ERROR_ACTIVE)) {
+               enum can_state new_state, tx_state, rx_state;
+               u32 rec = hecc_read(priv, HECC_CANREC);
+               u32 tec = hecc_read(priv, HECC_CANTEC);
+
+               if (rec >= 128 || tec >= 128)
+                       new_state = CAN_STATE_ERROR_PASSIVE;
+               else if (rec >= 96 || tec >= 96)
+                       new_state = CAN_STATE_ERROR_WARNING;
+               else
+                       new_state = CAN_STATE_ERROR_ACTIVE;
+
+               if (new_state < priv->can.state) {
+                       rx_state = rec >= tec ? new_state : 0;
+                       tx_state = rec <= tec ? new_state : 0;
+                       ti_hecc_change_state(ndev, rx_state, tx_state);
+               }
+       }
+
        if (int_status & HECC_CANGIF_GMIF) {
                while (priv->tx_tail - priv->tx_head > 0) {
                        mbxno = get_tx_tail_mb(priv);
                        mbx_mask = BIT(mbxno);
                        if (!(mbx_mask & hecc_read(priv, HECC_CANTA)))
                                break;
-                       hecc_clear_bit(priv, HECC_CANMIM, mbx_mask);
                        hecc_write(priv, HECC_CANTA, mbx_mask);
                        spin_lock_irqsave(&priv->mbx_lock, flags);
                        hecc_clear_bit(priv, HECC_CANME, mbx_mask);
@@ -695,16 +760,15 @@ static irqreturn_t ti_hecc_interrupt(int irq, void *dev_id)
                while ((rx_pending = hecc_read(priv, HECC_CANRMP))) {
                        can_rx_offload_irq_offload_timestamp(&priv->offload,
                                                             rx_pending);
-                       hecc_write(priv, HECC_CANRMP, rx_pending);
                }
        }
 
        /* clear all interrupt conditions - read back to avoid spurious ints */
        if (priv->use_hecc1int) {
-               hecc_write(priv, HECC_CANGIF1, HECC_SET_REG);
+               hecc_write(priv, HECC_CANGIF1, handled);
                int_status = hecc_read(priv, HECC_CANGIF1);
        } else {
-               hecc_write(priv, HECC_CANGIF0, HECC_SET_REG);
+               hecc_write(priv, HECC_CANGIF0, handled);
                int_status = hecc_read(priv, HECC_CANGIF0);
        }
 
@@ -877,7 +941,7 @@ static int ti_hecc_probe(struct platform_device *pdev)
 
        priv->offload.mailbox_read = ti_hecc_mailbox_read;
        priv->offload.mb_first = HECC_RX_FIRST_MBOX;
-       priv->offload.mb_last = HECC_MAX_TX_MBOX;
+       priv->offload.mb_last = HECC_RX_LAST_MBOX;
        err = can_rx_offload_add_timestamp(ndev, &priv->offload);
        if (err) {
                dev_err(&pdev->dev, "can_rx_offload_add_timestamp() failed\n");
index bd6eb9967630b2ceb5db47dd3d1334784b546093..2f74f6704c1286dc678c323aceaa34f0c64396ab 100644 (file)
@@ -623,6 +623,7 @@ static int gs_can_open(struct net_device *netdev)
                                           rc);
 
                                usb_unanchor_urb(urb);
+                               usb_free_urb(urb);
                                break;
                        }
 
index 19a702ac49e41f76dfbeb0463f13ddccba34c3ae..21faa2ec46327976425e73a8c7d5410b5825906b 100644 (file)
@@ -876,9 +876,8 @@ static void mcba_usb_disconnect(struct usb_interface *intf)
        netdev_info(priv->netdev, "device disconnected\n");
 
        unregister_candev(priv->netdev);
-       free_candev(priv->netdev);
-
        mcba_urb_unlink(priv);
+       free_candev(priv->netdev);
 }
 
 static struct usb_driver mcba_usb_driver = {
index 617da295b6c12647d48ee8b4e88c5a099d53e13a..d2539c95adb65cc24cc7bdb73a954d721071d1a1 100644 (file)
@@ -100,7 +100,7 @@ struct pcan_usb_msg_context {
        u8 *end;
        u8 rec_cnt;
        u8 rec_idx;
-       u8 rec_data_idx;
+       u8 rec_ts_idx;
        struct net_device *netdev;
        struct pcan_usb *pdev;
 };
@@ -436,8 +436,8 @@ static int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n,
                }
                if ((n & PCAN_USB_ERROR_BUS_LIGHT) == 0) {
                        /* no error (back to active state) */
-                       mc->pdev->dev.can.state = CAN_STATE_ERROR_ACTIVE;
-                       return 0;
+                       new_state = CAN_STATE_ERROR_ACTIVE;
+                       break;
                }
                break;
 
@@ -460,9 +460,9 @@ static int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n,
                }
 
                if ((n & PCAN_USB_ERROR_BUS_HEAVY) == 0) {
-                       /* no error (back to active state) */
-                       mc->pdev->dev.can.state = CAN_STATE_ERROR_ACTIVE;
-                       return 0;
+                       /* no error (back to warning state) */
+                       new_state = CAN_STATE_ERROR_WARNING;
+                       break;
                }
                break;
 
@@ -501,6 +501,11 @@ static int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n,
                mc->pdev->dev.can.can_stats.error_warning++;
                break;
 
+       case CAN_STATE_ERROR_ACTIVE:
+               cf->can_id |= CAN_ERR_CRTL;
+               cf->data[1] = CAN_ERR_CRTL_ACTIVE;
+               break;
+
        default:
                /* CAN_STATE_MAX (trick to handle other errors) */
                cf->can_id |= CAN_ERR_CRTL;
@@ -547,10 +552,15 @@ static int pcan_usb_decode_status(struct pcan_usb_msg_context *mc,
        mc->ptr += PCAN_USB_CMD_ARGS;
 
        if (status_len & PCAN_USB_STATUSLEN_TIMESTAMP) {
-               int err = pcan_usb_decode_ts(mc, !mc->rec_idx);
+               int err = pcan_usb_decode_ts(mc, !mc->rec_ts_idx);
 
                if (err)
                        return err;
+
+               /* Next packet in the buffer will have a timestamp on a single
+                * byte
+                */
+               mc->rec_ts_idx++;
        }
 
        switch (f) {
@@ -632,10 +642,13 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len)
 
        cf->can_dlc = get_can_dlc(rec_len);
 
-       /* first data packet timestamp is a word */
-       if (pcan_usb_decode_ts(mc, !mc->rec_data_idx))
+       /* Only first packet timestamp is a word */
+       if (pcan_usb_decode_ts(mc, !mc->rec_ts_idx))
                goto decode_failed;
 
+       /* Next packet in the buffer will have a timestamp on a single byte */
+       mc->rec_ts_idx++;
+
        /* read data */
        memset(cf->data, 0x0, sizeof(cf->data));
        if (status_len & PCAN_USB_STATUSLEN_RTR) {
@@ -688,7 +701,6 @@ static int pcan_usb_decode_msg(struct peak_usb_device *dev, u8 *ibuf, u32 lbuf)
                /* handle normal can frames here */
                } else {
                        err = pcan_usb_decode_data(&mc, sl);
-                       mc.rec_data_idx++;
                }
        }
 
index 65dce642b86b54c8378bece93bfdc738573470ae..0b7766b715fd22a26adaecb6491e69bef7d2798b 100644 (file)
@@ -750,7 +750,7 @@ static int peak_usb_create_dev(const struct peak_usb_adapter *peak_usb_adapter,
        dev = netdev_priv(netdev);
 
        /* allocate a buffer large enough to send commands */
-       dev->cmd_buf = kmalloc(PCAN_USB_MAX_CMD_LEN, GFP_KERNEL);
+       dev->cmd_buf = kzalloc(PCAN_USB_MAX_CMD_LEN, GFP_KERNEL);
        if (!dev->cmd_buf) {
                err = -ENOMEM;
                goto lbl_free_candev;
index d596a2ad7f78bca8689dcbe3244c755ba5a1c8d1..8fa224b28218b262f132106203f2c0279c94d213 100644 (file)
@@ -996,9 +996,8 @@ static void usb_8dev_disconnect(struct usb_interface *intf)
                netdev_info(priv->netdev, "device disconnected\n");
 
                unregister_netdev(priv->netdev);
-               free_candev(priv->netdev);
-
                unlink_all_urbs(priv);
+               free_candev(priv->netdev);
        }
 
 }
index 911b34316c9d4394464070af8a071537f6c796fc..7c482b2d78d22281f706a3a6d567b1a7c61d07a6 100644 (file)
@@ -1599,7 +1599,6 @@ static const struct xcan_devtype_data xcan_zynq_data = {
 
 static const struct xcan_devtype_data xcan_axi_data = {
        .cantype = XAXI_CAN,
-       .flags = XCAN_FLAG_TXFEMP,
        .bittiming_const = &xcan_bittiming_const,
        .btr_ts2_shift = XCAN_BTR_TS2_SHIFT,
        .btr_sjw_shift = XCAN_BTR_SJW_SHIFT,
index 26509fa37a50b4d4137adfef9878ac969464da18..69fc13046ac718aa763d2719d7d964df3fe64893 100644 (file)
@@ -37,22 +37,11 @@ static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port)
        unsigned int i;
        u32 reg, offset;
 
-       if (priv->type == BCM7445_DEVICE_ID)
-               offset = CORE_STS_OVERRIDE_IMP;
-       else
-               offset = CORE_STS_OVERRIDE_IMP2;
-
        /* Enable the port memories */
        reg = core_readl(priv, CORE_MEM_PSM_VDD_CTRL);
        reg &= ~P_TXQ_PSM_VDD(port);
        core_writel(priv, reg, CORE_MEM_PSM_VDD_CTRL);
 
-       /* Enable Broadcast, Multicast, Unicast forwarding to IMP port */
-       reg = core_readl(priv, CORE_IMP_CTL);
-       reg |= (RX_BCST_EN | RX_MCST_EN | RX_UCST_EN);
-       reg &= ~(RX_DIS | TX_DIS);
-       core_writel(priv, reg, CORE_IMP_CTL);
-
        /* Enable forwarding */
        core_writel(priv, SW_FWDG_EN, CORE_SWMODE);
 
@@ -71,10 +60,27 @@ static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port)
 
        b53_brcm_hdr_setup(ds, port);
 
-       /* Force link status for IMP port */
-       reg = core_readl(priv, offset);
-       reg |= (MII_SW_OR | LINK_STS);
-       core_writel(priv, reg, offset);
+       if (port == 8) {
+               if (priv->type == BCM7445_DEVICE_ID)
+                       offset = CORE_STS_OVERRIDE_IMP;
+               else
+                       offset = CORE_STS_OVERRIDE_IMP2;
+
+               /* Force link status for IMP port */
+               reg = core_readl(priv, offset);
+               reg |= (MII_SW_OR | LINK_STS);
+               core_writel(priv, reg, offset);
+
+               /* Enable Broadcast, Multicast, Unicast forwarding to IMP port */
+               reg = core_readl(priv, CORE_IMP_CTL);
+               reg |= (RX_BCST_EN | RX_MCST_EN | RX_UCST_EN);
+               reg &= ~(RX_DIS | TX_DIS);
+               core_writel(priv, reg, CORE_IMP_CTL);
+       } else {
+               reg = core_readl(priv, CORE_G_PCTL_PORT(port));
+               reg &= ~(RX_DIS | TX_DIS);
+               core_writel(priv, reg, CORE_G_PCTL_PORT(port));
+       }
 }
 
 static void bcm_sf2_gphy_enable_set(struct dsa_switch *ds, bool enable)
@@ -1209,10 +1215,10 @@ static int bcm_sf2_sw_remove(struct platform_device *pdev)
        struct bcm_sf2_priv *priv = platform_get_drvdata(pdev);
 
        priv->wol_ports_mask = 0;
+       /* Disable interrupts */
+       bcm_sf2_intr_disable(priv);
        dsa_unregister_switch(priv->dev->ds);
        bcm_sf2_cfp_exit(priv->dev->ds);
-       /* Disable all ports and interrupts */
-       bcm_sf2_sw_suspend(priv->dev->ds);
        bcm_sf2_mdio_unregister(priv);
 
        return 0;
index f40b248f0b23a5581ffa3b3eefd69e4369f3c79b..ffac0ea4e8d56e61cb17858c3f9e1aac96b08885 100644 (file)
@@ -26,8 +26,8 @@ config NET_DSA_SJA1105_PTP
 
 config NET_DSA_SJA1105_TAS
        bool "Support for the Time-Aware Scheduler on NXP SJA1105"
-       depends on NET_DSA_SJA1105
-       depends on NET_SCH_TAPRIO
+       depends on NET_DSA_SJA1105 && NET_SCH_TAPRIO
+       depends on NET_SCH_TAPRIO=y || NET_DSA_SJA1105=m
        help
          This enables support for the TTEthernet-based egress scheduling
          engine in the SJA1105 DSA driver, which is controlled using a
index 42d2e1b02c440b98971ef1f8798f84ac94f6eadf..664d664e09250ef94167485fe52914005de99e4d 100644 (file)
@@ -256,6 +256,9 @@ static int emac_rockchip_remove(struct platform_device *pdev)
        if (priv->regulator)
                regulator_disable(priv->regulator);
 
+       if (priv->soc_data->need_div_macclk)
+               clk_disable_unprepare(priv->macclk);
+
        free_netdev(ndev);
        return err;
 }
index b4a8cf620a0c73d9b0d5e0eb0578ff1ca6d0988f..04ec909e06dfd72ec197871f8aff2701a3fc64bb 100644 (file)
@@ -10382,7 +10382,8 @@ static void bnxt_cleanup_pci(struct bnxt *bp)
 {
        bnxt_unmap_bars(bp, bp->pdev);
        pci_release_regions(bp->pdev);
-       pci_disable_device(bp->pdev);
+       if (pci_is_enabled(bp->pdev))
+               pci_disable_device(bp->pdev);
 }
 
 static void bnxt_init_dflt_coal(struct bnxt *bp)
@@ -10669,14 +10670,11 @@ static void bnxt_fw_reset_task(struct work_struct *work)
                bp->fw_reset_state = BNXT_FW_RESET_STATE_RESET_FW;
        }
        /* fall through */
-       case BNXT_FW_RESET_STATE_RESET_FW: {
-               u32 wait_dsecs = bp->fw_health->post_reset_wait_dsecs;
-
+       case BNXT_FW_RESET_STATE_RESET_FW:
                bnxt_reset_all(bp);
                bp->fw_reset_state = BNXT_FW_RESET_STATE_ENABLE_DEV;
-               bnxt_queue_fw_reset_work(bp, wait_dsecs * HZ / 10);
+               bnxt_queue_fw_reset_work(bp, bp->fw_reset_min_dsecs * HZ / 10);
                return;
-       }
        case BNXT_FW_RESET_STATE_ENABLE_DEV:
                if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state) &&
                    bp->fw_health) {
index e664392dccc0e3580bdb44943b4663894f671562..7151244f8c7d2f24f4fb5ad347aadabc799cee2e 100644 (file)
@@ -29,25 +29,20 @@ static int bnxt_fw_reporter_diagnose(struct devlink_health_reporter *reporter,
        val = bnxt_fw_health_readl(bp, BNXT_FW_HEALTH_REG);
        health_status = val & 0xffff;
 
-       if (health_status == BNXT_FW_STATUS_HEALTHY) {
-               rc = devlink_fmsg_string_pair_put(fmsg, "FW status",
-                                                 "Healthy;");
-               if (rc)
-                       return rc;
-       } else if (health_status < BNXT_FW_STATUS_HEALTHY) {
-               rc = devlink_fmsg_string_pair_put(fmsg, "FW status",
-                                                 "Not yet completed initialization;");
+       if (health_status < BNXT_FW_STATUS_HEALTHY) {
+               rc = devlink_fmsg_string_pair_put(fmsg, "Description",
+                                                 "Not yet completed initialization");
                if (rc)
                        return rc;
        } else if (health_status > BNXT_FW_STATUS_HEALTHY) {
-               rc = devlink_fmsg_string_pair_put(fmsg, "FW status",
-                                                 "Encountered fatal error and cannot recover;");
+               rc = devlink_fmsg_string_pair_put(fmsg, "Description",
+                                                 "Encountered fatal error and cannot recover");
                if (rc)
                        return rc;
        }
 
        if (val >> 16) {
-               rc = devlink_fmsg_u32_pair_put(fmsg, "Error", val >> 16);
+               rc = devlink_fmsg_u32_pair_put(fmsg, "Error code", val >> 16);
                if (rc)
                        return rc;
        }
@@ -215,25 +210,68 @@ enum bnxt_dl_param_id {
 
 static const struct bnxt_dl_nvm_param nvm_params[] = {
        {DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV, NVM_OFF_ENABLE_SRIOV,
-        BNXT_NVM_SHARED_CFG, 1},
+        BNXT_NVM_SHARED_CFG, 1, 1},
        {DEVLINK_PARAM_GENERIC_ID_IGNORE_ARI, NVM_OFF_IGNORE_ARI,
-        BNXT_NVM_SHARED_CFG, 1},
+        BNXT_NVM_SHARED_CFG, 1, 1},
        {DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX,
-        NVM_OFF_MSIX_VEC_PER_PF_MAX, BNXT_NVM_SHARED_CFG, 10},
+        NVM_OFF_MSIX_VEC_PER_PF_MAX, BNXT_NVM_SHARED_CFG, 10, 4},
        {DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN,
-        NVM_OFF_MSIX_VEC_PER_PF_MIN, BNXT_NVM_SHARED_CFG, 7},
+        NVM_OFF_MSIX_VEC_PER_PF_MIN, BNXT_NVM_SHARED_CFG, 7, 4},
        {BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK, NVM_OFF_DIS_GRE_VER_CHECK,
-        BNXT_NVM_SHARED_CFG, 1},
+        BNXT_NVM_SHARED_CFG, 1, 1},
 };
 
+union bnxt_nvm_data {
+       u8      val8;
+       __le32  val32;
+};
+
+static void bnxt_copy_to_nvm_data(union bnxt_nvm_data *dst,
+                                 union devlink_param_value *src,
+                                 int nvm_num_bits, int dl_num_bytes)
+{
+       u32 val32 = 0;
+
+       if (nvm_num_bits == 1) {
+               dst->val8 = src->vbool;
+               return;
+       }
+       if (dl_num_bytes == 4)
+               val32 = src->vu32;
+       else if (dl_num_bytes == 2)
+               val32 = (u32)src->vu16;
+       else if (dl_num_bytes == 1)
+               val32 = (u32)src->vu8;
+       dst->val32 = cpu_to_le32(val32);
+}
+
+static void bnxt_copy_from_nvm_data(union devlink_param_value *dst,
+                                   union bnxt_nvm_data *src,
+                                   int nvm_num_bits, int dl_num_bytes)
+{
+       u32 val32;
+
+       if (nvm_num_bits == 1) {
+               dst->vbool = src->val8;
+               return;
+       }
+       val32 = le32_to_cpu(src->val32);
+       if (dl_num_bytes == 4)
+               dst->vu32 = val32;
+       else if (dl_num_bytes == 2)
+               dst->vu16 = (u16)val32;
+       else if (dl_num_bytes == 1)
+               dst->vu8 = (u8)val32;
+}
+
 static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg,
                             int msg_len, union devlink_param_value *val)
 {
        struct hwrm_nvm_get_variable_input *req = msg;
-       void *data_addr = NULL, *buf = NULL;
        struct bnxt_dl_nvm_param nvm_param;
-       int bytesize, idx = 0, rc, i;
+       union bnxt_nvm_data *data;
        dma_addr_t data_dma_addr;
+       int idx = 0, rc, i;
 
        /* Get/Set NVM CFG parameter is supported only on PFs */
        if (BNXT_VF(bp))
@@ -254,47 +292,31 @@ static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg,
        else if (nvm_param.dir_type == BNXT_NVM_FUNC_CFG)
                idx = bp->pf.fw_fid - BNXT_FIRST_PF_FID;
 
-       bytesize = roundup(nvm_param.num_bits, BITS_PER_BYTE) / BITS_PER_BYTE;
-       switch (bytesize) {
-       case 1:
-               if (nvm_param.num_bits == 1)
-                       buf = &val->vbool;
-               else
-                       buf = &val->vu8;
-               break;
-       case 2:
-               buf = &val->vu16;
-               break;
-       case 4:
-               buf = &val->vu32;
-               break;
-       default:
-               return -EFAULT;
-       }
-
-       data_addr = dma_alloc_coherent(&bp->pdev->dev, bytesize,
-                                      &data_dma_addr, GFP_KERNEL);
-       if (!data_addr)
+       data = dma_alloc_coherent(&bp->pdev->dev, sizeof(*data),
+                                 &data_dma_addr, GFP_KERNEL);
+       if (!data)
                return -ENOMEM;
 
        req->dest_data_addr = cpu_to_le64(data_dma_addr);
-       req->data_len = cpu_to_le16(nvm_param.num_bits);
+       req->data_len = cpu_to_le16(nvm_param.nvm_num_bits);
        req->option_num = cpu_to_le16(nvm_param.offset);
        req->index_0 = cpu_to_le16(idx);
        if (idx)
                req->dimensions = cpu_to_le16(1);
 
        if (req->req_type == cpu_to_le16(HWRM_NVM_SET_VARIABLE)) {
-               memcpy(data_addr, buf, bytesize);
+               bnxt_copy_to_nvm_data(data, val, nvm_param.nvm_num_bits,
+                                     nvm_param.dl_num_bytes);
                rc = hwrm_send_message(bp, msg, msg_len, HWRM_CMD_TIMEOUT);
        } else {
                rc = hwrm_send_message_silent(bp, msg, msg_len,
                                              HWRM_CMD_TIMEOUT);
+               if (!rc)
+                       bnxt_copy_from_nvm_data(val, data,
+                                               nvm_param.nvm_num_bits,
+                                               nvm_param.dl_num_bytes);
        }
-       if (!rc && req->req_type == cpu_to_le16(HWRM_NVM_GET_VARIABLE))
-               memcpy(buf, data_addr, bytesize);
-
-       dma_free_coherent(&bp->pdev->dev, bytesize, data_addr, data_dma_addr);
+       dma_free_coherent(&bp->pdev->dev, sizeof(*data), data, data_dma_addr);
        if (rc == -EACCES)
                netdev_err(bp->dev, "PF does not have admin privileges to modify NVM config\n");
        return rc;
index b97e0baeb42d6b2a07d9af7770e551429b90df1b..2f4fd0a7d04bfae168cc9aefc6e0faac0eacd7e4 100644 (file)
@@ -52,7 +52,8 @@ struct bnxt_dl_nvm_param {
        u16 id;
        u16 offset;
        u16 dir_type;
-       u16 num_bits;
+       u16 nvm_num_bits;
+       u8 dl_num_bytes;
 };
 
 void bnxt_devlink_health_report(struct bnxt *bp, unsigned long event);
index 0f138280315a82f753de8b1243a8ef2331228a31..1de51811fcb4ac443adaa9fb7ab02ad873fbaf7b 100644 (file)
@@ -1996,8 +1996,6 @@ static void reset_umac(struct bcmgenet_priv *priv)
 
        /* issue soft reset with (rg)mii loopback to ensure a stable rxclk */
        bcmgenet_umac_writel(priv, CMD_SW_RESET | CMD_LCL_LOOP_EN, UMAC_CMD);
-       udelay(2);
-       bcmgenet_umac_writel(priv, 0, UMAC_CMD);
 }
 
 static void bcmgenet_intr_disable(struct bcmgenet_priv *priv)
@@ -2614,8 +2612,10 @@ static void bcmgenet_irq_task(struct work_struct *work)
        spin_unlock_irq(&priv->lock);
 
        if (status & UMAC_IRQ_PHY_DET_R &&
-           priv->dev->phydev->autoneg != AUTONEG_ENABLE)
+           priv->dev->phydev->autoneg != AUTONEG_ENABLE) {
                phy_init_hw(priv->dev->phydev);
+               genphy_config_aneg(priv->dev->phydev);
+       }
 
        /* Link UP/DOWN event */
        if (status & UMAC_IRQ_LINK_EVENT)
@@ -2879,12 +2879,6 @@ static int bcmgenet_open(struct net_device *dev)
        if (priv->internal_phy)
                bcmgenet_power_up(priv, GENET_POWER_PASSIVE);
 
-       ret = bcmgenet_mii_connect(dev);
-       if (ret) {
-               netdev_err(dev, "failed to connect to PHY\n");
-               goto err_clk_disable;
-       }
-
        /* take MAC out of reset */
        bcmgenet_umac_reset(priv);
 
@@ -2894,12 +2888,6 @@ static int bcmgenet_open(struct net_device *dev)
        reg = bcmgenet_umac_readl(priv, UMAC_CMD);
        priv->crc_fwd_en = !!(reg & CMD_CRC_FWD);
 
-       ret = bcmgenet_mii_config(dev, true);
-       if (ret) {
-               netdev_err(dev, "unsupported PHY\n");
-               goto err_disconnect_phy;
-       }
-
        bcmgenet_set_hw_addr(priv, dev->dev_addr);
 
        if (priv->internal_phy) {
@@ -2915,7 +2903,7 @@ static int bcmgenet_open(struct net_device *dev)
        ret = bcmgenet_init_dma(priv);
        if (ret) {
                netdev_err(dev, "failed to initialize DMA\n");
-               goto err_disconnect_phy;
+               goto err_clk_disable;
        }
 
        /* Always enable ring 16 - descriptor ring */
@@ -2938,19 +2926,25 @@ static int bcmgenet_open(struct net_device *dev)
                goto err_irq0;
        }
 
+       ret = bcmgenet_mii_probe(dev);
+       if (ret) {
+               netdev_err(dev, "failed to connect to PHY\n");
+               goto err_irq1;
+       }
+
        bcmgenet_netif_start(dev);
 
        netif_tx_start_all_queues(dev);
 
        return 0;
 
+err_irq1:
+       free_irq(priv->irq1, priv);
 err_irq0:
        free_irq(priv->irq0, priv);
 err_fini_dma:
        bcmgenet_dma_teardown(priv);
        bcmgenet_fini_dma(priv);
-err_disconnect_phy:
-       phy_disconnect(dev->phydev);
 err_clk_disable:
        if (priv->internal_phy)
                bcmgenet_power_down(priv, GENET_POWER_PASSIVE);
@@ -3631,8 +3625,6 @@ static int bcmgenet_resume(struct device *d)
        if (priv->internal_phy)
                bcmgenet_power_up(priv, GENET_POWER_PASSIVE);
 
-       phy_init_hw(dev->phydev);
-
        bcmgenet_umac_reset(priv);
 
        init_umac(priv);
@@ -3641,7 +3633,10 @@ static int bcmgenet_resume(struct device *d)
        if (priv->wolopts)
                clk_disable_unprepare(priv->clk_wol);
 
+       phy_init_hw(dev->phydev);
+
        /* Speed settings must be restored */
+       genphy_config_aneg(dev->phydev);
        bcmgenet_mii_config(priv->dev, false);
 
        bcmgenet_set_hw_addr(priv, dev->dev_addr);
index 7fbf573d8d52a8ff45c1399ece76a3808490c624..dbc69d8fa05f510a5e504bd4a91282f6c94e5c3b 100644 (file)
@@ -720,8 +720,8 @@ GENET_IO_MACRO(rbuf, GENET_RBUF_OFF);
 
 /* MDIO routines */
 int bcmgenet_mii_init(struct net_device *dev);
-int bcmgenet_mii_connect(struct net_device *dev);
 int bcmgenet_mii_config(struct net_device *dev, bool init);
+int bcmgenet_mii_probe(struct net_device *dev);
 void bcmgenet_mii_exit(struct net_device *dev);
 void bcmgenet_phy_power_set(struct net_device *dev, bool enable);
 void bcmgenet_mii_setup(struct net_device *dev);
index 17bb8d60a157cb4da2a792521c9bcb8aa97b851d..dbe18cdf6c1b844d65c475c589deecd4010f0ec8 100644 (file)
@@ -173,46 +173,6 @@ static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
                                          bcmgenet_fixed_phy_link_update);
 }
 
-int bcmgenet_mii_connect(struct net_device *dev)
-{
-       struct bcmgenet_priv *priv = netdev_priv(dev);
-       struct device_node *dn = priv->pdev->dev.of_node;
-       struct phy_device *phydev;
-       u32 phy_flags = 0;
-       int ret;
-
-       /* Communicate the integrated PHY revision */
-       if (priv->internal_phy)
-               phy_flags = priv->gphy_rev;
-
-       /* Initialize link state variables that bcmgenet_mii_setup() uses */
-       priv->old_link = -1;
-       priv->old_speed = -1;
-       priv->old_duplex = -1;
-       priv->old_pause = -1;
-
-       if (dn) {
-               phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup,
-                                       phy_flags, priv->phy_interface);
-               if (!phydev) {
-                       pr_err("could not attach to PHY\n");
-                       return -ENODEV;
-               }
-       } else {
-               phydev = dev->phydev;
-               phydev->dev_flags = phy_flags;
-
-               ret = phy_connect_direct(dev, phydev, bcmgenet_mii_setup,
-                                        priv->phy_interface);
-               if (ret) {
-                       pr_err("could not attach to PHY\n");
-                       return -ENODEV;
-               }
-       }
-
-       return 0;
-}
-
 int bcmgenet_mii_config(struct net_device *dev, bool init)
 {
        struct bcmgenet_priv *priv = netdev_priv(dev);
@@ -221,8 +181,38 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
        const char *phy_name = NULL;
        u32 id_mode_dis = 0;
        u32 port_ctrl;
+       int bmcr = -1;
+       int ret;
        u32 reg;
 
+       /* MAC clocking workaround during reset of umac state machines */
+       reg = bcmgenet_umac_readl(priv, UMAC_CMD);
+       if (reg & CMD_SW_RESET) {
+               /* An MII PHY must be isolated to prevent TXC contention */
+               if (priv->phy_interface == PHY_INTERFACE_MODE_MII) {
+                       ret = phy_read(phydev, MII_BMCR);
+                       if (ret >= 0) {
+                               bmcr = ret;
+                               ret = phy_write(phydev, MII_BMCR,
+                                               bmcr | BMCR_ISOLATE);
+                       }
+                       if (ret) {
+                               netdev_err(dev, "failed to isolate PHY\n");
+                               return ret;
+                       }
+               }
+               /* Switch MAC clocking to RGMII generated clock */
+               bcmgenet_sys_writel(priv, PORT_MODE_EXT_GPHY, SYS_PORT_CTRL);
+               /* Ensure 5 clks with Rx disabled
+                * followed by 5 clks with Reset asserted
+                */
+               udelay(4);
+               reg &= ~(CMD_SW_RESET | CMD_LCL_LOOP_EN);
+               bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+               /* Ensure 5 more clocks before Rx is enabled */
+               udelay(2);
+       }
+
        priv->ext_phy = !priv->internal_phy &&
                        (priv->phy_interface != PHY_INTERFACE_MODE_MOCA);
 
@@ -254,6 +244,9 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
                phy_set_max_speed(phydev, SPEED_100);
                bcmgenet_sys_writel(priv,
                                    PORT_MODE_EXT_EPHY, SYS_PORT_CTRL);
+               /* Restore the MII PHY after isolation */
+               if (bmcr >= 0)
+                       phy_write(phydev, MII_BMCR, bmcr);
                break;
 
        case PHY_INTERFACE_MODE_REVMII:
@@ -306,21 +299,71 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
                bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
        }
 
-       if (init) {
-               linkmode_copy(phydev->advertising, phydev->supported);
+       if (init)
+               dev_info(kdev, "configuring instance for %s\n", phy_name);
 
-               /* The internal PHY has its link interrupts routed to the
-                * Ethernet MAC ISRs. On GENETv5 there is a hardware issue
-                * that prevents the signaling of link UP interrupts when
-                * the link operates at 10Mbps, so fallback to polling for
-                * those versions of GENET.
-                */
-               if (priv->internal_phy && !GENET_IS_V5(priv))
-                       phydev->irq = PHY_IGNORE_INTERRUPT;
+       return 0;
+}
 
-               dev_info(kdev, "configuring instance for %s\n", phy_name);
+int bcmgenet_mii_probe(struct net_device *dev)
+{
+       struct bcmgenet_priv *priv = netdev_priv(dev);
+       struct device_node *dn = priv->pdev->dev.of_node;
+       struct phy_device *phydev;
+       u32 phy_flags = 0;
+       int ret;
+
+       /* Communicate the integrated PHY revision */
+       if (priv->internal_phy)
+               phy_flags = priv->gphy_rev;
+
+       /* Initialize link state variables that bcmgenet_mii_setup() uses */
+       priv->old_link = -1;
+       priv->old_speed = -1;
+       priv->old_duplex = -1;
+       priv->old_pause = -1;
+
+       if (dn) {
+               phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup,
+                                       phy_flags, priv->phy_interface);
+               if (!phydev) {
+                       pr_err("could not attach to PHY\n");
+                       return -ENODEV;
+               }
+       } else {
+               phydev = dev->phydev;
+               phydev->dev_flags = phy_flags;
+
+               ret = phy_connect_direct(dev, phydev, bcmgenet_mii_setup,
+                                        priv->phy_interface);
+               if (ret) {
+                       pr_err("could not attach to PHY\n");
+                       return -ENODEV;
+               }
        }
 
+       /* Configure port multiplexer based on what the probed PHY device since
+        * reading the 'max-speed' property determines the maximum supported
+        * PHY speed which is needed for bcmgenet_mii_config() to configure
+        * things appropriately.
+        */
+       ret = bcmgenet_mii_config(dev, true);
+       if (ret) {
+               phy_disconnect(dev->phydev);
+               return ret;
+       }
+
+       linkmode_copy(phydev->advertising, phydev->supported);
+
+       /* The internal PHY has its link interrupts routed to the
+        * Ethernet MAC ISRs. On GENETv5 there is a hardware issue
+        * that prevents the signaling of link UP interrupts when
+        * the link operates at 10Mbps, so fallback to polling for
+        * those versions of GENET.
+        */
+       if (priv->internal_phy && !GENET_IS_V5(priv))
+               dev->phydev->irq = PHY_IGNORE_INTERRUPT;
+
        return 0;
 }
 
index 0e5de88fd6e8522ac0e35e9940d1d083f170c3ea..cdd7e5da4a74ab183d8d80a07461e989f5f69172 100644 (file)
@@ -1499,7 +1499,7 @@ static int octeon_mgmt_probe(struct platform_device *pdev)
        netdev->ethtool_ops = &octeon_mgmt_ethtool_ops;
 
        netdev->min_mtu = 64 - OCTEON_MGMT_RX_HEADROOM;
-       netdev->max_mtu = 16383 - OCTEON_MGMT_RX_HEADROOM;
+       netdev->max_mtu = 16383 - OCTEON_MGMT_RX_HEADROOM - VLAN_HLEN;
 
        mac = of_get_mac_address(pdev->dev.of_node);
 
index a4dead4ab0edba004db13542ad6f1073e430df02..86b528d8364c0712d8c26f684f140901463089a4 100644 (file)
@@ -695,10 +695,10 @@ static void uld_init(struct adapter *adap, struct cxgb4_lld_info *lld)
        lld->write_cmpl_support = adap->params.write_cmpl_support;
 }
 
-static void uld_attach(struct adapter *adap, unsigned int uld)
+static int uld_attach(struct adapter *adap, unsigned int uld)
 {
-       void *handle;
        struct cxgb4_lld_info lli;
+       void *handle;
 
        uld_init(adap, &lli);
        uld_queue_init(adap, uld, &lli);
@@ -708,7 +708,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
                dev_warn(adap->pdev_dev,
                         "could not attach to the %s driver, error %ld\n",
                         adap->uld[uld].name, PTR_ERR(handle));
-               return;
+               return PTR_ERR(handle);
        }
 
        adap->uld[uld].handle = handle;
@@ -716,22 +716,22 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
 
        if (adap->flags & CXGB4_FULL_INIT_DONE)
                adap->uld[uld].state_change(handle, CXGB4_STATE_UP);
+
+       return 0;
 }
 
-/**
- *     cxgb4_register_uld - register an upper-layer driver
- *     @type: the ULD type
- *     @p: the ULD methods
+/* cxgb4_register_uld - register an upper-layer driver
+ * @type: the ULD type
+ * @p: the ULD methods
  *
- *     Registers an upper-layer driver with this driver and notifies the ULD
- *     about any presently available devices that support its type.  Returns
- *     %-EBUSY if a ULD of the same type is already registered.
+ * Registers an upper-layer driver with this driver and notifies the ULD
+ * about any presently available devices that support its type.
  */
 void cxgb4_register_uld(enum cxgb4_uld type,
                        const struct cxgb4_uld_info *p)
 {
-       int ret = 0;
        struct adapter *adap;
+       int ret = 0;
 
        if (type >= CXGB4_ULD_MAX)
                return;
@@ -763,8 +763,12 @@ void cxgb4_register_uld(enum cxgb4_uld type,
                if (ret)
                        goto free_irq;
                adap->uld[type] = *p;
-               uld_attach(adap, type);
+               ret = uld_attach(adap, type);
+               if (ret)
+                       goto free_txq;
                continue;
+free_txq:
+               release_sge_txq_uld(adap, type);
 free_irq:
                if (adap->flags & CXGB4_FULL_INIT_DONE)
                        quiesce_rx_uld(adap, type);
index b3da81e90132fd74d26b007ca5414a066547774f..928bfea5457bb2856e0781872e524476afec96cb 100644 (file)
@@ -3791,15 +3791,11 @@ int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq,
         * write the CIDX Updates into the Status Page at the end of the
         * TX Queue.
         */
-       c.autoequiqe_to_viid = htonl((dbqt
-                                     ? FW_EQ_ETH_CMD_AUTOEQUIQE_F
-                                     : FW_EQ_ETH_CMD_AUTOEQUEQE_F) |
+       c.autoequiqe_to_viid = htonl(FW_EQ_ETH_CMD_AUTOEQUEQE_F |
                                     FW_EQ_ETH_CMD_VIID_V(pi->viid));
 
        c.fetchszm_to_iqid =
-               htonl(FW_EQ_ETH_CMD_HOSTFCMODE_V(dbqt
-                                                ? HOSTFCMODE_INGRESS_QUEUE_X
-                                                : HOSTFCMODE_STATUS_PAGE_X) |
+               htonl(FW_EQ_ETH_CMD_HOSTFCMODE_V(HOSTFCMODE_STATUS_PAGE_X) |
                      FW_EQ_ETH_CMD_PCIECHN_V(pi->tx_chan) |
                      FW_EQ_ETH_CMD_FETCHRO_F | FW_EQ_ETH_CMD_IQID_V(iqid));
 
index 0b12f89bf89a313f574f8e8a7295dbc112bcdeab..9fdf77d5eb3740982c28f5758b595aec33dbf692 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 /* Register definitions for Gemini GMAC Ethernet device driver
  *
  * Copyright (C) 2006 Storlink, Corp.
index 9b7af94a40bb028414a178c1cc7f77daa125f3e5..96e9565f1e08a165ac48705265d93259d58b1060 100644 (file)
@@ -727,6 +727,18 @@ static netdev_tx_t ftgmac100_hard_start_xmit(struct sk_buff *skb,
         */
        nfrags = skb_shinfo(skb)->nr_frags;
 
+       /* Setup HW checksumming */
+       csum_vlan = 0;
+       if (skb->ip_summed == CHECKSUM_PARTIAL &&
+           !ftgmac100_prep_tx_csum(skb, &csum_vlan))
+               goto drop;
+
+       /* Add VLAN tag */
+       if (skb_vlan_tag_present(skb)) {
+               csum_vlan |= FTGMAC100_TXDES1_INS_VLANTAG;
+               csum_vlan |= skb_vlan_tag_get(skb) & 0xffff;
+       }
+
        /* Get header len */
        len = skb_headlen(skb);
 
@@ -753,19 +765,6 @@ static netdev_tx_t ftgmac100_hard_start_xmit(struct sk_buff *skb,
        if (nfrags == 0)
                f_ctl_stat |= FTGMAC100_TXDES0_LTS;
        txdes->txdes3 = cpu_to_le32(map);
-
-       /* Setup HW checksumming */
-       csum_vlan = 0;
-       if (skb->ip_summed == CHECKSUM_PARTIAL &&
-           !ftgmac100_prep_tx_csum(skb, &csum_vlan))
-               goto drop;
-
-       /* Add VLAN tag */
-       if (skb_vlan_tag_present(skb)) {
-               csum_vlan |= FTGMAC100_TXDES1_INS_VLANTAG;
-               csum_vlan |= skb_vlan_tag_get(skb) & 0xffff;
-       }
-
        txdes->txdes1 = cpu_to_le32(csum_vlan);
 
        /* Next descriptor */
index ff2e177395d49498cfefccb08314b8b98697e568..df2458a5e9ef5b0a444cccee404a89993d3c747e 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright 2018 NXP
  */
index 720cd50f5895ce77818fedd256ced50bbb1ab3cb..4ac05bfef338098b2bba5f1c697b36f816107ce8 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright 2013-2016 Freescale Semiconductor Inc.
  * Copyright 2016-2018 NXP
index be7914c1634dfcb2ba8658506ce6c504f0a36bc7..311c184e1aef675f02ea14892225ce0947d3baee 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright 2013-2016 Freescale Semiconductor Inc.
  * Copyright 2016-2018 NXP
index d4d4c72adf498e78ef8de5af9e6eb76e83ae4c4d..a9c386b635811f0f65c4af79d51cef346da54b4b 100644 (file)
@@ -3558,7 +3558,7 @@ fec_probe(struct platform_device *pdev)
 
        for (i = 0; i < irq_cnt; i++) {
                snprintf(irq_name, sizeof(irq_name), "int%d", i);
-               irq = platform_get_irq_byname(pdev, irq_name);
+               irq = platform_get_irq_byname_optional(pdev, irq_name);
                if (irq < 0)
                        irq = platform_get_irq(pdev, i);
                if (irq < 0) {
@@ -3645,6 +3645,8 @@ fec_drv_remove(struct platform_device *pdev)
                regulator_disable(fep->reg_phy);
        pm_runtime_put(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
+       clk_disable_unprepare(fep->clk_ahb);
+       clk_disable_unprepare(fep->clk_ipg);
        if (of_phy_is_fixed_link(np))
                of_phy_deregister_fixed_link(np);
        of_node_put(fep->phy_node);
index 19e2365be7d8fa19020aa687608d26441329df30..945643c026155f83fcb38ecfac40d7ef37c2d888 100644 (file)
@@ -600,9 +600,9 @@ void fec_ptp_init(struct platform_device *pdev, int irq_idx)
 
        INIT_DELAYED_WORK(&fep->time_keep, fec_time_keep);
 
-       irq = platform_get_irq_byname(pdev, "pps");
+       irq = platform_get_irq_byname_optional(pdev, "pps");
        if (irq < 0)
-               irq = platform_get_irq(pdev, irq_idx);
+               irq = platform_get_irq_optional(pdev, irq_idx);
        /* Failure to get an irq is not fatal,
         * only the PTP_CLOCK_PPS clock events should stop
         */
index 59564ac99d2a6df5c589d89521b5513f78ae16fc..edec61dfc8687fff6f4867e4463753d28aab202e 100644 (file)
@@ -289,6 +289,8 @@ static bool gve_rx(struct gve_rx_ring *rx, struct gve_rx_desc *rx_desc,
 
        len = be16_to_cpu(rx_desc->len) - GVE_RX_PAD;
        page_info = &rx->data.page_info[idx];
+       dma_sync_single_for_cpu(&priv->pdev->dev, rx->data.qpl->page_buses[idx],
+                               PAGE_SIZE, DMA_FROM_DEVICE);
 
        /* gvnic can only receive into registered segments. If the buffer
         * can't be recycled, our only choice is to copy the data out of
index 778b87b5a06c255eaff6544302aca044240814f6..0a9a7ee2a866838cce439172af87edc6ef0106e7 100644 (file)
@@ -390,7 +390,21 @@ static void gve_tx_fill_seg_desc(union gve_tx_desc *seg_desc,
        seg_desc->seg.seg_addr = cpu_to_be64(addr);
 }
 
-static int gve_tx_add_skb(struct gve_tx_ring *tx, struct sk_buff *skb)
+static void gve_dma_sync_for_device(struct device *dev, dma_addr_t *page_buses,
+                                   u64 iov_offset, u64 iov_len)
+{
+       dma_addr_t dma;
+       u64 addr;
+
+       for (addr = iov_offset; addr < iov_offset + iov_len;
+            addr += PAGE_SIZE) {
+               dma = page_buses[addr / PAGE_SIZE];
+               dma_sync_single_for_device(dev, dma, PAGE_SIZE, DMA_TO_DEVICE);
+       }
+}
+
+static int gve_tx_add_skb(struct gve_tx_ring *tx, struct sk_buff *skb,
+                         struct device *dev)
 {
        int pad_bytes, hlen, hdr_nfrags, payload_nfrags, l4_hdr_offset;
        union gve_tx_desc *pkt_desc, *seg_desc;
@@ -432,6 +446,9 @@ static int gve_tx_add_skb(struct gve_tx_ring *tx, struct sk_buff *skb)
        skb_copy_bits(skb, 0,
                      tx->tx_fifo.base + info->iov[hdr_nfrags - 1].iov_offset,
                      hlen);
+       gve_dma_sync_for_device(dev, tx->tx_fifo.qpl->page_buses,
+                               info->iov[hdr_nfrags - 1].iov_offset,
+                               info->iov[hdr_nfrags - 1].iov_len);
        copy_offset = hlen;
 
        for (i = payload_iov; i < payload_nfrags + payload_iov; i++) {
@@ -445,6 +462,9 @@ static int gve_tx_add_skb(struct gve_tx_ring *tx, struct sk_buff *skb)
                skb_copy_bits(skb, copy_offset,
                              tx->tx_fifo.base + info->iov[i].iov_offset,
                              info->iov[i].iov_len);
+               gve_dma_sync_for_device(dev, tx->tx_fifo.qpl->page_buses,
+                                       info->iov[i].iov_offset,
+                                       info->iov[i].iov_len);
                copy_offset += info->iov[i].iov_len;
        }
 
@@ -473,7 +493,7 @@ netdev_tx_t gve_tx(struct sk_buff *skb, struct net_device *dev)
                gve_tx_put_doorbell(priv, tx->q_resources, tx->req);
                return NETDEV_TX_BUSY;
        }
-       nsegs = gve_tx_add_skb(tx, skb);
+       nsegs = gve_tx_add_skb(tx, skb, &priv->pdev->dev);
 
        netdev_tx_sent_queue(tx->netdev_txq, skb->len);
        skb_tx_timestamp(skb);
index c84167447abe650c36186eae40343b2584ac4fbb..4606a7e4a6d19a2471adb6cdb2f2c5f810bc8c37 100644 (file)
@@ -237,6 +237,7 @@ struct hip04_priv {
        dma_addr_t rx_phys[RX_DESC_NUM];
        unsigned int rx_head;
        unsigned int rx_buf_size;
+       unsigned int rx_cnt_remaining;
 
        struct device_node *phy_node;
        struct phy_device *phy;
@@ -575,7 +576,6 @@ static int hip04_rx_poll(struct napi_struct *napi, int budget)
        struct hip04_priv *priv = container_of(napi, struct hip04_priv, napi);
        struct net_device *ndev = priv->ndev;
        struct net_device_stats *stats = &ndev->stats;
-       unsigned int cnt = hip04_recv_cnt(priv);
        struct rx_desc *desc;
        struct sk_buff *skb;
        unsigned char *buf;
@@ -588,8 +588,8 @@ static int hip04_rx_poll(struct napi_struct *napi, int budget)
 
        /* clean up tx descriptors */
        tx_remaining = hip04_tx_reclaim(ndev, false);
-
-       while (cnt && !last) {
+       priv->rx_cnt_remaining += hip04_recv_cnt(priv);
+       while (priv->rx_cnt_remaining && !last) {
                buf = priv->rx_buf[priv->rx_head];
                skb = build_skb(buf, priv->rx_buf_size);
                if (unlikely(!skb)) {
@@ -635,11 +635,13 @@ refill:
                hip04_set_recv_desc(priv, phys);
 
                priv->rx_head = RX_NEXT(priv->rx_head);
-               if (rx >= budget)
+               if (rx >= budget) {
+                       --priv->rx_cnt_remaining;
                        goto done;
+               }
 
-               if (--cnt == 0)
-                       cnt = hip04_recv_cnt(priv);
+               if (--priv->rx_cnt_remaining == 0)
+                       priv->rx_cnt_remaining += hip04_recv_cnt(priv);
        }
 
        if (!(priv->reg_inten & RCV_INT)) {
@@ -724,6 +726,7 @@ static int hip04_mac_open(struct net_device *ndev)
        int i;
 
        priv->rx_head = 0;
+       priv->rx_cnt_remaining = 0;
        priv->tx_head = 0;
        priv->tx_tail = 0;
        hip04_reset_ppe(priv);
@@ -1038,7 +1041,6 @@ static int hip04_remove(struct platform_device *pdev)
 
        hip04_free_ring(ndev, d);
        unregister_netdev(ndev);
-       free_irq(ndev->irq, ndev);
        of_node_put(priv->phy_node);
        cancel_work_sync(&priv->tx_timeout_task);
        free_netdev(ndev);
index 6d0457eb4faa901810ce78a5c04b162d2dce08b3..08339278c722a622bf4feaa79ecd919d55ee4a5b 100644 (file)
@@ -199,7 +199,6 @@ hnae_init_ring(struct hnae_queue *q, struct hnae_ring *ring, int flags)
 
        ring->q = q;
        ring->flags = flags;
-       spin_lock_init(&ring->lock);
        ring->coal_param = q->handle->coal_param;
        assert(!ring->desc && !ring->desc_cb && !ring->desc_dma_addr);
 
index e9c67c06bfd22514064f4992011b6c5d5b9f2984..6ab9458302e121a49a381e431f478f9d12ec1a09 100644 (file)
@@ -274,9 +274,6 @@ struct hnae_ring {
        /* statistic */
        struct ring_stats stats;
 
-       /* ring lock for poll one */
-       spinlock_t lock;
-
        dma_addr_t desc_dma_addr;
        u32 buf_size;       /* size for hnae_desc->addr, preset by AE */
        u16 desc_num;       /* total number of desc */
index a48396dd4ebb2f7c08029eab99d20f3a386fe7a0..14ab20491fd02b1c867460ce42b4aa310f50a162 100644 (file)
@@ -943,15 +943,6 @@ static int is_valid_clean_head(struct hnae_ring *ring, int h)
        return u > c ? (h > c && h <= u) : (h > c || h <= u);
 }
 
-/* netif_tx_lock will turn down the performance, set only when necessary */
-#ifdef CONFIG_NET_POLL_CONTROLLER
-#define NETIF_TX_LOCK(ring) spin_lock(&(ring)->lock)
-#define NETIF_TX_UNLOCK(ring) spin_unlock(&(ring)->lock)
-#else
-#define NETIF_TX_LOCK(ring)
-#define NETIF_TX_UNLOCK(ring)
-#endif
-
 /* reclaim all desc in one budget
  * return error or number of desc left
  */
@@ -965,21 +956,16 @@ static int hns_nic_tx_poll_one(struct hns_nic_ring_data *ring_data,
        int head;
        int bytes, pkts;
 
-       NETIF_TX_LOCK(ring);
-
        head = readl_relaxed(ring->io_base + RCB_REG_HEAD);
        rmb(); /* make sure head is ready before touch any data */
 
-       if (is_ring_empty(ring) || head == ring->next_to_clean) {
-               NETIF_TX_UNLOCK(ring);
+       if (is_ring_empty(ring) || head == ring->next_to_clean)
                return 0; /* no data to poll */
-       }
 
        if (!is_valid_clean_head(ring, head)) {
                netdev_err(ndev, "wrong head (%d, %d-%d)\n", head,
                           ring->next_to_use, ring->next_to_clean);
                ring->stats.io_err_cnt++;
-               NETIF_TX_UNLOCK(ring);
                return -EIO;
        }
 
@@ -994,8 +980,6 @@ static int hns_nic_tx_poll_one(struct hns_nic_ring_data *ring_data,
        ring->stats.tx_pkts += pkts;
        ring->stats.tx_bytes += bytes;
 
-       NETIF_TX_UNLOCK(ring);
-
        dev_queue = netdev_get_tx_queue(ndev, ring_data->queue_index);
        netdev_tx_completed_queue(dev_queue, pkts, bytes);
 
@@ -1055,16 +1039,12 @@ static void hns_nic_tx_clr_all_bufs(struct hns_nic_ring_data *ring_data)
        int head;
        int bytes, pkts;
 
-       NETIF_TX_LOCK(ring);
-
        head = ring->next_to_use; /* ntu :soft setted ring position*/
        bytes = 0;
        pkts = 0;
        while (head != ring->next_to_clean)
                hns_nic_reclaim_one_desc(ring, &bytes, &pkts);
 
-       NETIF_TX_UNLOCK(ring);
-
        dev_queue = netdev_get_tx_queue(ndev, ring_data->queue_index);
        netdev_tx_reset_queue(dev_queue);
 }
index 75ccc1e7076bde9a5bd681f0e6d3370f333f54db..a0998937727d89b7d9bd4a38944c273dd01effad 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 // Copyright (c) 2016-2017 Hisilicon Limited.
 
 #ifndef __HNAE3_H
index 2110fa3b447980beecf46976a39f37b72be0a3ba..5d468ed404a647fcc4584a40d8d476d637e493c3 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 // Copyright (c) 2016-2017 Hisilicon Limited.
 
 #ifndef __HNS3_ENET_H
index 4821fe08b5e4919a3d3f94472f83ede49fed8d7c..1426eb5ddf3df1aafe44a293cdf2e95dd716a46f 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 // Copyright (c) 2016-2017 Hisilicon Limited.
 
 #ifndef __HCLGE_CMD_H
index 278f21e027367ce65f5a848cbb67eabb2af893e0..b04702e656890e124ed54f77ee531f3d8880e0a1 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 // Copyright (c) 2016-2017 Hisilicon Limited.
 
 #ifndef __HCLGE_DCB_H__
index e02e01bd9effec698b740baa35e56a685eb325fb..16f7d0e15b4f39285d9ee8b8363758f038858b56 100644 (file)
@@ -3587,12 +3587,28 @@ static int hclge_set_rst_done(struct hclge_dev *hdev)
 {
        struct hclge_pf_rst_done_cmd *req;
        struct hclge_desc desc;
+       int ret;
 
        req = (struct hclge_pf_rst_done_cmd *)desc.data;
        hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PF_RST_DONE, false);
        req->pf_rst_done |= HCLGE_PF_RESET_DONE_BIT;
 
-       return hclge_cmd_send(&hdev->hw, &desc, 1);
+       ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+       /* To be compatible with the old firmware, which does not support
+        * command HCLGE_OPC_PF_RST_DONE, just print a warning and
+        * return success
+        */
+       if (ret == -EOPNOTSUPP) {
+               dev_warn(&hdev->pdev->dev,
+                        "current firmware does not support command(0x%x)!\n",
+                        HCLGE_OPC_PF_RST_DONE);
+               return 0;
+       } else if (ret) {
+               dev_err(&hdev->pdev->dev, "assert PF reset done fail %d!\n",
+                       ret);
+       }
+
+       return ret;
 }
 
 static int hclge_reset_prepare_up(struct hclge_dev *hdev)
index c3d56b872ed7342893c93a31524bf3844e1e3acf..59b824347ba4d8d66b4941baa682a5da22f7cebc 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 // Copyright (c) 2016-2017 Hisilicon Limited.
 
 #ifndef __HCLGE_MAIN_H
index ef095d9c566f4918713b0e029e2200f4b90fd0ca..dd9a1218a7b03018a30359970218163af4d052b4 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 // Copyright (c) 2016-2017 Hisilicon Limited.
 
 #ifndef __HCLGE_MDIO_H
index 818610988d342fddaaf1474ccaf7f985536f828c..260f22d19d81aaf774f4a60c7dbe356ec4a75ecf 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 // Copyright (c) 2016-2017 Hisilicon Limited.
 
 #ifndef __HCLGE_TM_H
index 71d3d8854d8f124293399e5ac23aae6f328593fb..be56e631d693884a40568effdda9b2aa1bf2696d 100644 (file)
@@ -607,6 +607,7 @@ static int e1000_set_ringparam(struct net_device *netdev,
        for (i = 0; i < adapter->num_rx_queues; i++)
                rxdr[i].count = rxdr->count;
 
+       err = 0;
        if (netif_running(adapter->netdev)) {
                /* Try to get new resources before deleting old */
                err = e1000_setup_all_rx_resources(adapter);
@@ -627,14 +628,13 @@ static int e1000_set_ringparam(struct net_device *netdev,
                adapter->rx_ring = rxdr;
                adapter->tx_ring = txdr;
                err = e1000_up(adapter);
-               if (err)
-                       goto err_setup;
        }
        kfree(tx_old);
        kfree(rx_old);
 
        clear_bit(__E1000_RESETTING, &adapter->flags);
-       return 0;
+       return err;
+
 err_setup_tx:
        e1000_free_all_rx_resources(adapter);
 err_setup_rx:
@@ -646,7 +646,6 @@ err_alloc_rx:
 err_alloc_tx:
        if (netif_running(adapter->netdev))
                e1000_up(adapter);
-err_setup:
        clear_bit(__E1000_RESETTING, &adapter->flags);
        return err;
 }
index 530613f31527db5e0721bd26ad883e2e3f62d1a9..69a2daaca5c560e7bfd1f28dc894ef8c6304ab5d 100644 (file)
@@ -20,6 +20,8 @@
 
 /* API version 1.7 implements additional link and PHY-specific APIs  */
 #define I40E_MINOR_VER_GET_LINK_INFO_XL710 0x0007
+/* API version 1.9 for X722 implements additional link and PHY-specific APIs */
+#define I40E_MINOR_VER_GET_LINK_INFO_X722 0x0009
 /* API version 1.6 for X722 devices adds ability to stop FW LLDP agent */
 #define I40E_MINOR_VER_FW_LLDP_STOPPABLE_X722 0x0006
 
index d37c6e0e5f088eed43c429136182dc203b4e04c9..7560f06768e0626fcd8356ab7e0d9d63e0695686 100644 (file)
@@ -1876,7 +1876,8 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,
             hw->aq.fw_min_ver < 40)) && hw_link_info->phy_type == 0xE)
                hw_link_info->phy_type = I40E_PHY_TYPE_10GBASE_SFPP_CU;
 
-       if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
+       if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE &&
+           hw->mac.type != I40E_MAC_X722) {
                __le32 tmp;
 
                memcpy(&tmp, resp->link_type, sizeof(tmp));
index b1c3227ae4ab8b923af7ef270403a37a47e35a69..d07e1a8904283684f448e4a1346db6cfc6d4d9eb 100644 (file)
@@ -157,11 +157,6 @@ static int i40e_xsk_umem_disable(struct i40e_vsi *vsi, u16 qid)
                err = i40e_queue_pair_enable(vsi, qid);
                if (err)
                        return err;
-
-               /* Kick start the NAPI context so that receiving will start */
-               err = i40e_xsk_wakeup(vsi->netdev, qid, XDP_WAKEUP_RX);
-               if (err)
-                       return err;
        }
 
        return 0;
@@ -694,8 +689,6 @@ static bool i40e_xmit_zc(struct i40e_ring *xdp_ring, unsigned int budget)
                i40e_xdp_ring_update_tail(xdp_ring);
 
                xsk_umem_consume_tx_done(xdp_ring->xsk_umem);
-               if (xsk_umem_uses_need_wakeup(xdp_ring->xsk_umem))
-                       xsk_clear_tx_need_wakeup(xdp_ring->xsk_umem);
        }
 
        return !!budget && work_done;
@@ -774,12 +767,8 @@ bool i40e_clean_xdp_tx_irq(struct i40e_vsi *vsi,
        i40e_update_tx_stats(tx_ring, completed_frames, total_bytes);
 
 out_xmit:
-       if (xsk_umem_uses_need_wakeup(tx_ring->xsk_umem)) {
-               if (tx_ring->next_to_clean == tx_ring->next_to_use)
-                       xsk_set_tx_need_wakeup(tx_ring->xsk_umem);
-               else
-                       xsk_clear_tx_need_wakeup(tx_ring->xsk_umem);
-       }
+       if (xsk_umem_uses_need_wakeup(tx_ring->xsk_umem))
+               xsk_set_tx_need_wakeup(tx_ring->xsk_umem);
 
        xmit_done = i40e_xmit_zc(tx_ring, budget);
 
index 8f310e520b069bd2903d7ee353238c84018201e0..821987da5698ac8cf0468ac90e6f0fee460916ba 100644 (file)
@@ -314,7 +314,7 @@ iavf_map_vector_to_rxq(struct iavf_adapter *adapter, int v_idx, int r_idx)
        q_vector->rx.target_itr = ITR_TO_REG(rx_ring->itr_setting);
        q_vector->ring_mask |= BIT(r_idx);
        wr32(hw, IAVF_VFINT_ITRN1(IAVF_RX_ITR, q_vector->reg_idx),
-            q_vector->rx.current_itr);
+            q_vector->rx.current_itr >> 1);
        q_vector->rx.current_itr = q_vector->rx.target_itr;
 }
 
@@ -340,7 +340,7 @@ iavf_map_vector_to_txq(struct iavf_adapter *adapter, int v_idx, int t_idx)
        q_vector->tx.target_itr = ITR_TO_REG(tx_ring->itr_setting);
        q_vector->num_ringpairs++;
        wr32(hw, IAVF_VFINT_ITRN1(IAVF_TX_ITR, q_vector->reg_idx),
-            q_vector->tx.target_itr);
+            q_vector->tx.target_itr >> 1);
        q_vector->tx.current_itr = q_vector->tx.target_itr;
 }
 
index fc624b73d05dcfe0e1819398b1948a122e9b1cc2..2fde9653a608fb7bc520006561e01d1335b9f24a 100644 (file)
@@ -1036,7 +1036,7 @@ enum ice_status ice_sched_query_res_alloc(struct ice_hw *hw)
        struct ice_aqc_query_txsched_res_resp *buf;
        enum ice_status status = 0;
        __le16 max_sibl;
-       u8 i;
+       u16 i;
 
        if (hw->layer_info)
                return status;
index 3ec2ce0725d536f2a2110f551e7f80371aaaf798..8a6ef351412921c729db50e686201b51ff4795ec 100644 (file)
@@ -466,7 +466,7 @@ static s32 igb_init_mac_params_82575(struct e1000_hw *hw)
                        ? igb_setup_copper_link_82575
                        : igb_setup_serdes_link_82575;
 
-       if (mac->type == e1000_82580) {
+       if (mac->type == e1000_82580 || mac->type == e1000_i350) {
                switch (hw->device_id) {
                /* feature not supported on these id's */
                case E1000_DEV_ID_DH89XXCC_SGMII:
index 105b0624081a12bb6d375247856aacfa43bb6bd6..ed7e667d7eb2923a0c89f1a3344795245702162f 100644 (file)
@@ -753,7 +753,8 @@ u32 igb_rd32(struct e1000_hw *hw, u32 reg)
                struct net_device *netdev = igb->netdev;
                hw->hw_addr = NULL;
                netdev_err(netdev, "PCIe link lost\n");
-               WARN(1, "igb: Failed to read reg 0x%x!\n", reg);
+               WARN(pci_device_is_present(igb->pdev),
+                    "igb: Failed to read reg 0x%x!\n", reg);
        }
 
        return value;
@@ -2064,7 +2065,8 @@ static void igb_check_swap_media(struct igb_adapter *adapter)
        if ((hw->phy.media_type == e1000_media_type_copper) &&
            (!(connsw & E1000_CONNSW_AUTOSENSE_EN))) {
                swap_now = true;
-       } else if (!(connsw & E1000_CONNSW_SERDESD)) {
+       } else if ((hw->phy.media_type != e1000_media_type_copper) &&
+                  !(connsw & E1000_CONNSW_SERDESD)) {
                /* copper signal takes time to appear */
                if (adapter->copper_tries < 4) {
                        adapter->copper_tries++;
@@ -2370,7 +2372,7 @@ void igb_reset(struct igb_adapter *adapter)
                adapter->ei.get_invariants(hw);
                adapter->flags &= ~IGB_FLAG_MEDIA_RESET;
        }
-       if ((mac->type == e1000_82575) &&
+       if ((mac->type == e1000_82575 || mac->type == e1000_i350) &&
            (adapter->flags & IGB_FLAG_MAS_ENABLE)) {
                igb_enable_mas(adapter);
        }
@@ -5673,8 +5675,8 @@ static void igb_tx_ctxtdesc(struct igb_ring *tx_ring,
         * should have been handled by the upper layers.
         */
        if (tx_ring->launchtime_enable) {
-               ts = ns_to_timespec64(first->skb->tstamp);
-               first->skb->tstamp = 0;
+               ts = ktime_to_timespec64(first->skb->tstamp);
+               first->skb->tstamp = ktime_set(0, 0);
                context_desc->seqnum_seed = cpu_to_le32(ts.tv_nsec / 32);
        } else {
                context_desc->seqnum_seed = 0;
index 63b62d74f9610c744fbd7f6c0a1e2e768291dc19..24888676f69ba0896a19a56ab53a6c78e8f77e82 100644 (file)
@@ -824,8 +824,8 @@ static void igc_tx_ctxtdesc(struct igc_ring *tx_ring,
         * should have been handled by the upper layers.
         */
        if (tx_ring->launchtime_enable) {
-               ts = ns_to_timespec64(first->skb->tstamp);
-               first->skb->tstamp = 0;
+               ts = ktime_to_timespec64(first->skb->tstamp);
+               first->skb->tstamp = ktime_set(0, 0);
                context_desc->launch_time = cpu_to_le32(ts.tv_nsec / 32);
        } else {
                context_desc->launch_time = 0;
@@ -4047,7 +4047,8 @@ u32 igc_rd32(struct igc_hw *hw, u32 reg)
                hw->hw_addr = NULL;
                netif_device_detach(netdev);
                netdev_err(netdev, "PCIe link lost, device now detached\n");
-               WARN(1, "igc: Failed to read reg 0x%x!\n", reg);
+               WARN(pci_device_is_present(igc->pdev),
+                    "igc: Failed to read reg 0x%x!\n", reg);
        }
 
        return value;
index 1ce2397306b9261826a736396ff5600fb6a115ec..91b3780ddb040de656e46a234f5c58e9b4fd71f2 100644 (file)
@@ -4310,7 +4310,6 @@ static void ixgbe_set_rx_buffer_len(struct ixgbe_adapter *adapter)
                if (test_bit(__IXGBE_RX_FCOE, &rx_ring->state))
                        set_bit(__IXGBE_RX_3K_BUFFER, &rx_ring->state);
 
-               clear_bit(__IXGBE_RX_BUILD_SKB_ENABLED, &rx_ring->state);
                if (adapter->flags2 & IXGBE_FLAG2_RX_LEGACY)
                        continue;
 
index 100ac89b345d2cd1a6a85f8bc4ec2dd85a8ba55b..d6feaacfbf898a285036d6d48308f01558c00486 100644 (file)
@@ -622,8 +622,6 @@ static bool ixgbe_xmit_zc(struct ixgbe_ring *xdp_ring, unsigned int budget)
        if (tx_desc) {
                ixgbe_xdp_ring_update_tail(xdp_ring);
                xsk_umem_consume_tx_done(xdp_ring->xsk_umem);
-               if (xsk_umem_uses_need_wakeup(xdp_ring->xsk_umem))
-                       xsk_clear_tx_need_wakeup(xdp_ring->xsk_umem);
        }
 
        return !!budget && work_done;
@@ -691,12 +689,8 @@ bool ixgbe_clean_xdp_tx_irq(struct ixgbe_q_vector *q_vector,
        if (xsk_frames)
                xsk_umem_complete_tx(umem, xsk_frames);
 
-       if (xsk_umem_uses_need_wakeup(tx_ring->xsk_umem)) {
-               if (tx_ring->next_to_clean == tx_ring->next_to_use)
-                       xsk_set_tx_need_wakeup(tx_ring->xsk_umem);
-               else
-                       xsk_clear_tx_need_wakeup(tx_ring->xsk_umem);
-       }
+       if (xsk_umem_uses_need_wakeup(tx_ring->xsk_umem))
+               xsk_set_tx_need_wakeup(tx_ring->xsk_umem);
 
        return ixgbe_xmit_zc(tx_ring, q_vector->tx.work_limit);
 }
index c8425d35c049bc8cf232eee65731ea0b166227cc..e47783ce77e08de2b935a983dc0c6bf782e0d5d9 100644 (file)
@@ -160,16 +160,23 @@ static inline u32 mvneta_bm_pool_get_bp(struct mvneta_bm *priv,
                             (bm_pool->id << MVNETA_BM_POOL_ACCESS_OFFS));
 }
 #else
-void mvneta_bm_pool_destroy(struct mvneta_bm *priv,
-                           struct mvneta_bm_pool *bm_pool, u8 port_map) {}
-void mvneta_bm_bufs_free(struct mvneta_bm *priv, struct mvneta_bm_pool *bm_pool,
-                        u8 port_map) {}
-int mvneta_bm_construct(struct hwbm_pool *hwbm_pool, void *buf) { return 0; }
-int mvneta_bm_pool_refill(struct mvneta_bm *priv,
-                         struct mvneta_bm_pool *bm_pool) {return 0; }
-struct mvneta_bm_pool *mvneta_bm_pool_use(struct mvneta_bm *priv, u8 pool_id,
-                                         enum mvneta_bm_type type, u8 port_id,
-                                         int pkt_size) { return NULL; }
+static inline void mvneta_bm_pool_destroy(struct mvneta_bm *priv,
+                                         struct mvneta_bm_pool *bm_pool,
+                                         u8 port_map) {}
+static inline void mvneta_bm_bufs_free(struct mvneta_bm *priv,
+                                      struct mvneta_bm_pool *bm_pool,
+                                      u8 port_map) {}
+static inline int mvneta_bm_construct(struct hwbm_pool *hwbm_pool, void *buf)
+{ return 0; }
+static inline int mvneta_bm_pool_refill(struct mvneta_bm *priv,
+                                       struct mvneta_bm_pool *bm_pool)
+{ return 0; }
+static inline struct mvneta_bm_pool *mvneta_bm_pool_use(struct mvneta_bm *priv,
+                                                       u8 pool_id,
+                                                       enum mvneta_bm_type type,
+                                                       u8 port_id,
+                                                       int pkt_size)
+{ return NULL; }
 
 static inline void mvneta_bm_pool_put_bp(struct mvneta_bm *priv,
                                         struct mvneta_bm_pool *bm_pool,
@@ -178,7 +185,8 @@ static inline void mvneta_bm_pool_put_bp(struct mvneta_bm *priv,
 static inline u32 mvneta_bm_pool_get_bp(struct mvneta_bm *priv,
                                        struct mvneta_bm_pool *bm_pool)
 { return 0; }
-struct mvneta_bm *mvneta_bm_get(struct device_node *node) { return NULL; }
-void mvneta_bm_put(struct mvneta_bm *priv) {}
+static inline struct mvneta_bm *mvneta_bm_get(struct device_node *node)
+{ return NULL; }
+static inline void mvneta_bm_put(struct mvneta_bm *priv) {}
 #endif /* CONFIG_MVNETA_BM */
 #endif
index fce9b3a2434720ac3ec2f0a9562e8b5cc2176b0f..69bb6bb06e769a2b944d523980f31f7a491976e3 100644 (file)
@@ -514,8 +514,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
        dev->caps.max_rq_desc_sz     = dev_cap->max_rq_desc_sz;
        /*
         * Subtract 1 from the limit because we need to allocate a
-        * spare CQE so the HCA HW can tell the difference between an
-        * empty CQ and a full CQ.
+        * spare CQE to enable resizing the CQ.
         */
        dev->caps.max_cqes           = dev_cap->max_cq_sz - 1;
        dev->caps.reserved_cqs       = dev_cap->reserved_cqs;
index 4356f3a580027602b84f7d550b3b56244e757307..1187ef1375e298bc1ae309a72064308f6e382c34 100644 (file)
@@ -471,12 +471,31 @@ void mlx4_init_quotas(struct mlx4_dev *dev)
                priv->mfunc.master.res_tracker.res_alloc[RES_MPT].quota[pf];
 }
 
-static int get_max_gauranteed_vfs_counter(struct mlx4_dev *dev)
+static int
+mlx4_calc_res_counter_guaranteed(struct mlx4_dev *dev,
+                                struct resource_allocator *res_alloc,
+                                int vf)
 {
-       /* reduce the sink counter */
-       return (dev->caps.max_counters - 1 -
-               (MLX4_PF_COUNTERS_PER_PORT * MLX4_MAX_PORTS))
-               / MLX4_MAX_PORTS;
+       struct mlx4_active_ports actv_ports;
+       int ports, counters_guaranteed;
+
+       /* For master, only allocate according to the number of phys ports */
+       if (vf == mlx4_master_func_num(dev))
+               return MLX4_PF_COUNTERS_PER_PORT * dev->caps.num_ports;
+
+       /* calculate real number of ports for the VF */
+       actv_ports = mlx4_get_active_ports(dev, vf);
+       ports = bitmap_weight(actv_ports.ports, dev->caps.num_ports);
+       counters_guaranteed = ports * MLX4_VF_COUNTERS_PER_PORT;
+
+       /* If we do not have enough counters for this VF, do not
+        * allocate any for it. '-1' to reduce the sink counter.
+        */
+       if ((res_alloc->res_reserved + counters_guaranteed) >
+           (dev->caps.max_counters - 1))
+               return 0;
+
+       return counters_guaranteed;
 }
 
 int mlx4_init_resource_tracker(struct mlx4_dev *dev)
@@ -484,7 +503,6 @@ int mlx4_init_resource_tracker(struct mlx4_dev *dev)
        struct mlx4_priv *priv = mlx4_priv(dev);
        int i, j;
        int t;
-       int max_vfs_guarantee_counter = get_max_gauranteed_vfs_counter(dev);
 
        priv->mfunc.master.res_tracker.slave_list =
                kcalloc(dev->num_slaves, sizeof(struct slave_list),
@@ -603,16 +621,8 @@ int mlx4_init_resource_tracker(struct mlx4_dev *dev)
                                break;
                        case RES_COUNTER:
                                res_alloc->quota[t] = dev->caps.max_counters;
-                               if (t == mlx4_master_func_num(dev))
-                                       res_alloc->guaranteed[t] =
-                                               MLX4_PF_COUNTERS_PER_PORT *
-                                               MLX4_MAX_PORTS;
-                               else if (t <= max_vfs_guarantee_counter)
-                                       res_alloc->guaranteed[t] =
-                                               MLX4_VF_COUNTERS_PER_PORT *
-                                               MLX4_MAX_PORTS;
-                               else
-                                       res_alloc->guaranteed[t] = 0;
+                               res_alloc->guaranteed[t] =
+                                       mlx4_calc_res_counter_guaranteed(dev, res_alloc, t);
                                break;
                        default:
                                break;
index 8d76452cacdc0fa22135f5f42bb1f003ec7467c3..f1a7bc46f1c0c67a886e0a9ecb06f628b3bc505f 100644 (file)
@@ -345,7 +345,7 @@ struct mlx5e_tx_wqe_info {
        u8  num_wqebbs;
        u8  num_dma;
 #ifdef CONFIG_MLX5_EN_TLS
-       skb_frag_t *resync_dump_frag;
+       struct page *resync_dump_frag_page;
 #endif
 };
 
@@ -410,6 +410,7 @@ struct mlx5e_txqsq {
        struct device             *pdev;
        __be32                     mkey_be;
        unsigned long              state;
+       unsigned int               hw_mtu;
        struct hwtstamp_config    *tstamp;
        struct mlx5_clock         *clock;
 
index b3a249b2a482fbd65ee6e857c572d66727d4ad45..ac44bbe95c5c1b653366252662fddb54e92188fa 100644 (file)
@@ -141,7 +141,7 @@ int mlx5e_hv_vhca_stats_create(struct mlx5e_priv *priv)
                                    "Failed to create hv vhca stats agent, err = %ld\n",
                                    PTR_ERR(agent));
 
-               kfree(priv->stats_agent.buf);
+               kvfree(priv->stats_agent.buf);
                return IS_ERR_OR_NULL(agent);
        }
 
@@ -157,5 +157,5 @@ void mlx5e_hv_vhca_stats_destroy(struct mlx5e_priv *priv)
                return;
 
        mlx5_hv_vhca_agent_destroy(priv->stats_agent.agent);
-       kfree(priv->stats_agent.buf);
+       kvfree(priv->stats_agent.buf);
 }
index f8ee18b4da6fa92818f515a30de826d183558475..13af72556987ffe6ffd5dbf2a32d240a1a545cc0 100644 (file)
@@ -97,15 +97,19 @@ static int mlx5e_route_lookup_ipv4(struct mlx5e_priv *priv,
        if (ret)
                return ret;
 
-       if (mlx5_lag_is_multipath(mdev) && rt->rt_gw_family != AF_INET)
+       if (mlx5_lag_is_multipath(mdev) && rt->rt_gw_family != AF_INET) {
+               ip_rt_put(rt);
                return -ENETUNREACH;
+       }
 #else
        return -EOPNOTSUPP;
 #endif
 
        ret = get_route_and_out_devs(priv, rt->dst.dev, route_dev, out_dev);
-       if (ret < 0)
+       if (ret < 0) {
+               ip_rt_put(rt);
                return ret;
+       }
 
        if (!(*out_ttl))
                *out_ttl = ip4_dst_hoplimit(&rt->dst);
@@ -149,8 +153,10 @@ static int mlx5e_route_lookup_ipv6(struct mlx5e_priv *priv,
                *out_ttl = ip6_dst_hoplimit(dst);
 
        ret = get_route_and_out_devs(priv, dst->dev, route_dev, out_dev);
-       if (ret < 0)
+       if (ret < 0) {
+               dst_release(dst);
                return ret;
+       }
 #else
        return -EOPNOTSUPP;
 #endif
index 87be9674790292beceddd8908e0d52d07a71c4e1..7c8796d9743fa5a6c66f4aa3e0017b800a121a9b 100644 (file)
 #else
 /* TLS offload requires additional stop_room for:
  *  - a resync SKB.
- * kTLS offload requires additional stop_room for:
- * - static params WQE,
- * - progress params WQE, and
- * - resync DUMP per frag.
+ * kTLS offload requires fixed additional stop_room for:
+ * - a static params WQE, and a progress params WQE.
+ * The additional MTU-depending room for the resync DUMP WQEs
+ * will be calculated and added in runtime.
  */
 #define MLX5E_SQ_TLS_ROOM  \
        (MLX5_SEND_WQE_MAX_WQEBBS + \
-        MLX5E_KTLS_STATIC_WQEBBS + MLX5E_KTLS_PROGRESS_WQEBBS + \
-        MAX_SKB_FRAGS * MLX5E_KTLS_MAX_DUMP_WQEBBS)
+        MLX5E_KTLS_STATIC_WQEBBS + MLX5E_KTLS_PROGRESS_WQEBBS)
 #endif
 
 #define INL_HDR_START_SZ (sizeof(((struct mlx5_wqe_eth_seg *)NULL)->inline_hdr.start))
@@ -92,7 +91,7 @@ mlx5e_fill_sq_frag_edge(struct mlx5e_txqsq *sq, struct mlx5_wq_cyc *wq,
 
        /* fill sq frag edge with nops to avoid wqe wrapping two pages */
        for (; wi < edge_wi; wi++) {
-               wi->skb        = NULL;
+               memset(wi, 0, sizeof(*wi));
                wi->num_wqebbs = 1;
                mlx5e_post_nop(wq, sq->sqn, &sq->pc);
        }
index d2ff74d52720d2ba369c143f086922185117086e..46725cd743a369b6531b2dc3fd8051e2129f266e 100644 (file)
@@ -38,7 +38,7 @@ static int mlx5e_ktls_add(struct net_device *netdev, struct sock *sk,
                return -ENOMEM;
 
        tx_priv->expected_seq = start_offload_tcp_sn;
-       tx_priv->crypto_info  = crypto_info;
+       tx_priv->crypto_info  = *(struct tls12_crypto_info_aes_gcm_128 *)crypto_info;
        mlx5e_set_ktls_tx_priv_ctx(tls_ctx, tx_priv);
 
        /* tc and underlay_qpn values are not in use for tls tis */
index b7298f9ee3d3f7d7a2adcb5cd2895d5ab2a0d78f..a3efa29a4629d796876452368502c3d10a9b12b5 100644 (file)
         MLX5_ST_SZ_BYTES(tls_progress_params))
 #define MLX5E_KTLS_PROGRESS_WQEBBS \
        (DIV_ROUND_UP(MLX5E_KTLS_PROGRESS_WQE_SZ, MLX5_SEND_WQE_BB))
-#define MLX5E_KTLS_MAX_DUMP_WQEBBS 2
+
+struct mlx5e_dump_wqe {
+       struct mlx5_wqe_ctrl_seg ctrl;
+       struct mlx5_wqe_data_seg data;
+};
+
+#define MLX5E_KTLS_DUMP_WQEBBS \
+       (DIV_ROUND_UP(sizeof(struct mlx5e_dump_wqe), MLX5_SEND_WQE_BB))
 
 enum {
        MLX5E_TLS_PROGRESS_PARAMS_AUTH_STATE_NO_OFFLOAD     = 0,
@@ -37,7 +44,7 @@ enum {
 
 struct mlx5e_ktls_offload_context_tx {
        struct tls_offload_context_tx *tx_ctx;
-       struct tls_crypto_info *crypto_info;
+       struct tls12_crypto_info_aes_gcm_128 crypto_info;
        u32 expected_seq;
        u32 tisn;
        u32 key_id;
@@ -86,14 +93,28 @@ struct sk_buff *mlx5e_ktls_handle_tx_skb(struct net_device *netdev,
                                         struct mlx5e_tx_wqe **wqe, u16 *pi);
 void mlx5e_ktls_tx_handle_resync_dump_comp(struct mlx5e_txqsq *sq,
                                           struct mlx5e_tx_wqe_info *wi,
-                                          struct mlx5e_sq_dma *dma);
-
+                                          u32 *dma_fifo_cc);
+static inline u8
+mlx5e_ktls_dumps_num_wqebbs(struct mlx5e_txqsq *sq, unsigned int nfrags,
+                           unsigned int sync_len)
+{
+       /* Given the MTU and sync_len, calculates an upper bound for the
+        * number of WQEBBs needed for the TX resync DUMP WQEs of a record.
+        */
+       return MLX5E_KTLS_DUMP_WQEBBS *
+               (nfrags + DIV_ROUND_UP(sync_len, sq->hw_mtu));
+}
 #else
 
 static inline void mlx5e_ktls_build_netdev(struct mlx5e_priv *priv)
 {
 }
 
+static inline void
+mlx5e_ktls_tx_handle_resync_dump_comp(struct mlx5e_txqsq *sq,
+                                     struct mlx5e_tx_wqe_info *wi,
+                                     u32 *dma_fifo_cc) {}
+
 #endif
 
 #endif /* __MLX5E_TLS_H__ */
index d195366461c9f21df74ad755d8be36efd7708f2c..778dab1af8fc659cae40ead517bc94dc22f68a4a 100644 (file)
@@ -24,17 +24,12 @@ enum {
 static void
 fill_static_params_ctx(void *ctx, struct mlx5e_ktls_offload_context_tx *priv_tx)
 {
-       struct tls_crypto_info *crypto_info = priv_tx->crypto_info;
-       struct tls12_crypto_info_aes_gcm_128 *info;
+       struct tls12_crypto_info_aes_gcm_128 *info = &priv_tx->crypto_info;
        char *initial_rn, *gcm_iv;
        u16 salt_sz, rec_seq_sz;
        char *salt, *rec_seq;
        u8 tls_version;
 
-       if (WARN_ON(crypto_info->cipher_type != TLS_CIPHER_AES_GCM_128))
-               return;
-
-       info = (struct tls12_crypto_info_aes_gcm_128 *)crypto_info;
        EXTRACT_INFO_FIELDS;
 
        gcm_iv      = MLX5_ADDR_OF(tls_static_params, ctx, gcm_iv);
@@ -108,16 +103,15 @@ build_progress_params(struct mlx5e_tx_wqe *wqe, u16 pc, u32 sqn,
 }
 
 static void tx_fill_wi(struct mlx5e_txqsq *sq,
-                      u16 pi, u8 num_wqebbs,
-                      skb_frag_t *resync_dump_frag,
-                      u32 num_bytes)
+                      u16 pi, u8 num_wqebbs, u32 num_bytes,
+                      struct page *page)
 {
        struct mlx5e_tx_wqe_info *wi = &sq->db.wqe_info[pi];
 
-       wi->skb              = NULL;
-       wi->num_wqebbs       = num_wqebbs;
-       wi->resync_dump_frag = resync_dump_frag;
-       wi->num_bytes        = num_bytes;
+       memset(wi, 0, sizeof(*wi));
+       wi->num_wqebbs = num_wqebbs;
+       wi->num_bytes  = num_bytes;
+       wi->resync_dump_frag_page = page;
 }
 
 void mlx5e_ktls_tx_offload_set_pending(struct mlx5e_ktls_offload_context_tx *priv_tx)
@@ -145,7 +139,7 @@ post_static_params(struct mlx5e_txqsq *sq,
 
        umr_wqe = mlx5e_sq_fetch_wqe(sq, MLX5E_KTLS_STATIC_UMR_WQE_SZ, &pi);
        build_static_params(umr_wqe, sq->pc, sq->sqn, priv_tx, fence);
-       tx_fill_wi(sq, pi, MLX5E_KTLS_STATIC_WQEBBS, NULL, 0);
+       tx_fill_wi(sq, pi, MLX5E_KTLS_STATIC_WQEBBS, 0, NULL);
        sq->pc += MLX5E_KTLS_STATIC_WQEBBS;
 }
 
@@ -159,7 +153,7 @@ post_progress_params(struct mlx5e_txqsq *sq,
 
        wqe = mlx5e_sq_fetch_wqe(sq, MLX5E_KTLS_PROGRESS_WQE_SZ, &pi);
        build_progress_params(wqe, sq->pc, sq->sqn, priv_tx, fence);
-       tx_fill_wi(sq, pi, MLX5E_KTLS_PROGRESS_WQEBBS, NULL, 0);
+       tx_fill_wi(sq, pi, MLX5E_KTLS_PROGRESS_WQEBBS, 0, NULL);
        sq->pc += MLX5E_KTLS_PROGRESS_WQEBBS;
 }
 
@@ -169,6 +163,14 @@ mlx5e_ktls_tx_post_param_wqes(struct mlx5e_txqsq *sq,
                              bool skip_static_post, bool fence_first_post)
 {
        bool progress_fence = skip_static_post || !fence_first_post;
+       struct mlx5_wq_cyc *wq = &sq->wq;
+       u16 contig_wqebbs_room, pi;
+
+       pi = mlx5_wq_cyc_ctr2ix(wq, sq->pc);
+       contig_wqebbs_room = mlx5_wq_cyc_get_contig_wqebbs(wq, pi);
+       if (unlikely(contig_wqebbs_room <
+                    MLX5E_KTLS_STATIC_WQEBBS + MLX5E_KTLS_PROGRESS_WQEBBS))
+               mlx5e_fill_sq_frag_edge(sq, wq, pi, contig_wqebbs_room);
 
        if (!skip_static_post)
                post_static_params(sq, priv_tx, fence_first_post);
@@ -180,29 +182,36 @@ struct tx_sync_info {
        u64 rcd_sn;
        s32 sync_len;
        int nr_frags;
-       skb_frag_t *frags[MAX_SKB_FRAGS];
+       skb_frag_t frags[MAX_SKB_FRAGS];
+};
+
+enum mlx5e_ktls_sync_retval {
+       MLX5E_KTLS_SYNC_DONE,
+       MLX5E_KTLS_SYNC_FAIL,
+       MLX5E_KTLS_SYNC_SKIP_NO_DATA,
 };
 
-static bool tx_sync_info_get(struct mlx5e_ktls_offload_context_tx *priv_tx,
-                            u32 tcp_seq, struct tx_sync_info *info)
+static enum mlx5e_ktls_sync_retval
+tx_sync_info_get(struct mlx5e_ktls_offload_context_tx *priv_tx,
+                u32 tcp_seq, struct tx_sync_info *info)
 {
        struct tls_offload_context_tx *tx_ctx = priv_tx->tx_ctx;
+       enum mlx5e_ktls_sync_retval ret = MLX5E_KTLS_SYNC_DONE;
        struct tls_record_info *record;
        int remaining, i = 0;
        unsigned long flags;
-       bool ret = true;
 
        spin_lock_irqsave(&tx_ctx->lock, flags);
        record = tls_get_record(tx_ctx, tcp_seq, &info->rcd_sn);
 
        if (unlikely(!record)) {
-               ret = false;
+               ret = MLX5E_KTLS_SYNC_FAIL;
                goto out;
        }
 
        if (unlikely(tcp_seq < tls_record_start_seq(record))) {
-               if (!tls_record_is_start_marker(record))
-                       ret = false;
+               ret = tls_record_is_start_marker(record) ?
+                       MLX5E_KTLS_SYNC_SKIP_NO_DATA : MLX5E_KTLS_SYNC_FAIL;
                goto out;
        }
 
@@ -211,13 +220,13 @@ static bool tx_sync_info_get(struct mlx5e_ktls_offload_context_tx *priv_tx,
        while (remaining > 0) {
                skb_frag_t *frag = &record->frags[i];
 
-               __skb_frag_ref(frag);
+               get_page(skb_frag_page(frag));
                remaining -= skb_frag_size(frag);
-               info->frags[i++] = frag;
+               info->frags[i++] = *frag;
        }
        /* reduce the part which will be sent with the original SKB */
        if (remaining < 0)
-               skb_frag_size_add(info->frags[i - 1], remaining);
+               skb_frag_size_add(&info->frags[i - 1], remaining);
        info->nr_frags = i;
 out:
        spin_unlock_irqrestore(&tx_ctx->lock, flags);
@@ -229,17 +238,12 @@ tx_post_resync_params(struct mlx5e_txqsq *sq,
                      struct mlx5e_ktls_offload_context_tx *priv_tx,
                      u64 rcd_sn)
 {
-       struct tls_crypto_info *crypto_info = priv_tx->crypto_info;
-       struct tls12_crypto_info_aes_gcm_128 *info;
+       struct tls12_crypto_info_aes_gcm_128 *info = &priv_tx->crypto_info;
        __be64 rn_be = cpu_to_be64(rcd_sn);
        bool skip_static_post;
        u16 rec_seq_sz;
        char *rec_seq;
 
-       if (WARN_ON(crypto_info->cipher_type != TLS_CIPHER_AES_GCM_128))
-               return;
-
-       info = (struct tls12_crypto_info_aes_gcm_128 *)crypto_info;
        rec_seq = info->rec_seq;
        rec_seq_sz = sizeof(info->rec_seq);
 
@@ -250,11 +254,6 @@ tx_post_resync_params(struct mlx5e_txqsq *sq,
        mlx5e_ktls_tx_post_param_wqes(sq, priv_tx, skip_static_post, true);
 }
 
-struct mlx5e_dump_wqe {
-       struct mlx5_wqe_ctrl_seg ctrl;
-       struct mlx5_wqe_data_seg data;
-};
-
 static int
 tx_post_resync_dump(struct mlx5e_txqsq *sq, skb_frag_t *frag, u32 tisn, bool first)
 {
@@ -262,7 +261,6 @@ tx_post_resync_dump(struct mlx5e_txqsq *sq, skb_frag_t *frag, u32 tisn, bool fir
        struct mlx5_wqe_data_seg *dseg;
        struct mlx5e_dump_wqe *wqe;
        dma_addr_t dma_addr = 0;
-       u8  num_wqebbs;
        u16 ds_cnt;
        int fsz;
        u16 pi;
@@ -270,7 +268,6 @@ tx_post_resync_dump(struct mlx5e_txqsq *sq, skb_frag_t *frag, u32 tisn, bool fir
        wqe = mlx5e_sq_fetch_wqe(sq, sizeof(*wqe), &pi);
 
        ds_cnt = sizeof(*wqe) / MLX5_SEND_WQE_DS;
-       num_wqebbs = DIV_ROUND_UP(ds_cnt, MLX5_SEND_WQEBB_NUM_DS);
 
        cseg = &wqe->ctrl;
        dseg = &wqe->data;
@@ -291,24 +288,27 @@ tx_post_resync_dump(struct mlx5e_txqsq *sq, skb_frag_t *frag, u32 tisn, bool fir
        dseg->byte_count = cpu_to_be32(fsz);
        mlx5e_dma_push(sq, dma_addr, fsz, MLX5E_DMA_MAP_PAGE);
 
-       tx_fill_wi(sq, pi, num_wqebbs, frag, fsz);
-       sq->pc += num_wqebbs;
-
-       WARN(num_wqebbs > MLX5E_KTLS_MAX_DUMP_WQEBBS,
-            "unexpected DUMP num_wqebbs, %d > %d",
-            num_wqebbs, MLX5E_KTLS_MAX_DUMP_WQEBBS);
+       tx_fill_wi(sq, pi, MLX5E_KTLS_DUMP_WQEBBS, fsz, skb_frag_page(frag));
+       sq->pc += MLX5E_KTLS_DUMP_WQEBBS;
 
        return 0;
 }
 
 void mlx5e_ktls_tx_handle_resync_dump_comp(struct mlx5e_txqsq *sq,
                                           struct mlx5e_tx_wqe_info *wi,
-                                          struct mlx5e_sq_dma *dma)
+                                          u32 *dma_fifo_cc)
 {
-       struct mlx5e_sq_stats *stats = sq->stats;
+       struct mlx5e_sq_stats *stats;
+       struct mlx5e_sq_dma *dma;
+
+       if (!wi->resync_dump_frag_page)
+               return;
+
+       dma = mlx5e_dma_get(sq, (*dma_fifo_cc)++);
+       stats = sq->stats;
 
        mlx5e_tx_dma_unmap(sq->pdev, dma);
-       __skb_frag_unref(wi->resync_dump_frag);
+       put_page(wi->resync_dump_frag_page);
        stats->tls_dump_packets++;
        stats->tls_dump_bytes += wi->num_bytes;
 }
@@ -318,25 +318,31 @@ static void tx_post_fence_nop(struct mlx5e_txqsq *sq)
        struct mlx5_wq_cyc *wq = &sq->wq;
        u16 pi = mlx5_wq_cyc_ctr2ix(wq, sq->pc);
 
-       tx_fill_wi(sq, pi, 1, NULL, 0);
+       tx_fill_wi(sq, pi, 1, 0, NULL);
 
        mlx5e_post_nop_fence(wq, sq->sqn, &sq->pc);
 }
 
-static struct sk_buff *
+static enum mlx5e_ktls_sync_retval
 mlx5e_ktls_tx_handle_ooo(struct mlx5e_ktls_offload_context_tx *priv_tx,
                         struct mlx5e_txqsq *sq,
-                        struct sk_buff *skb,
+                        int datalen,
                         u32 seq)
 {
        struct mlx5e_sq_stats *stats = sq->stats;
        struct mlx5_wq_cyc *wq = &sq->wq;
+       enum mlx5e_ktls_sync_retval ret;
        struct tx_sync_info info = {};
        u16 contig_wqebbs_room, pi;
        u8 num_wqebbs;
-       int i;
-
-       if (!tx_sync_info_get(priv_tx, seq, &info)) {
+       int i = 0;
+
+       ret = tx_sync_info_get(priv_tx, seq, &info);
+       if (unlikely(ret != MLX5E_KTLS_SYNC_DONE)) {
+               if (ret == MLX5E_KTLS_SYNC_SKIP_NO_DATA) {
+                       stats->tls_skip_no_sync_data++;
+                       return MLX5E_KTLS_SYNC_SKIP_NO_DATA;
+               }
                /* We might get here if a retransmission reaches the driver
                 * after the relevant record is acked.
                 * It should be safe to drop the packet in this case
@@ -346,13 +352,8 @@ mlx5e_ktls_tx_handle_ooo(struct mlx5e_ktls_offload_context_tx *priv_tx,
        }
 
        if (unlikely(info.sync_len < 0)) {
-               u32 payload;
-               int headln;
-
-               headln = skb_transport_offset(skb) + tcp_hdrlen(skb);
-               payload = skb->len - headln;
-               if (likely(payload <= -info.sync_len))
-                       return skb;
+               if (likely(datalen <= -info.sync_len))
+                       return MLX5E_KTLS_SYNC_DONE;
 
                stats->tls_drop_bypass_req++;
                goto err_out;
@@ -360,30 +361,62 @@ mlx5e_ktls_tx_handle_ooo(struct mlx5e_ktls_offload_context_tx *priv_tx,
 
        stats->tls_ooo++;
 
-       num_wqebbs = MLX5E_KTLS_STATIC_WQEBBS + MLX5E_KTLS_PROGRESS_WQEBBS +
-               (info.nr_frags ? info.nr_frags * MLX5E_KTLS_MAX_DUMP_WQEBBS : 1);
+       tx_post_resync_params(sq, priv_tx, info.rcd_sn);
+
+       /* If no dump WQE was sent, we need to have a fence NOP WQE before the
+        * actual data xmit.
+        */
+       if (!info.nr_frags) {
+               tx_post_fence_nop(sq);
+               return MLX5E_KTLS_SYNC_DONE;
+       }
+
+       num_wqebbs = mlx5e_ktls_dumps_num_wqebbs(sq, info.nr_frags, info.sync_len);
        pi = mlx5_wq_cyc_ctr2ix(wq, sq->pc);
        contig_wqebbs_room = mlx5_wq_cyc_get_contig_wqebbs(wq, pi);
+
        if (unlikely(contig_wqebbs_room < num_wqebbs))
                mlx5e_fill_sq_frag_edge(sq, wq, pi, contig_wqebbs_room);
 
        tx_post_resync_params(sq, priv_tx, info.rcd_sn);
 
-       for (i = 0; i < info.nr_frags; i++)
-               if (tx_post_resync_dump(sq, info.frags[i], priv_tx->tisn, !i))
-                       goto err_out;
+       for (; i < info.nr_frags; i++) {
+               unsigned int orig_fsz, frag_offset = 0, n = 0;
+               skb_frag_t *f = &info.frags[i];
 
-       /* If no dump WQE was sent, we need to have a fence NOP WQE before the
-        * actual data xmit.
-        */
-       if (!info.nr_frags)
-               tx_post_fence_nop(sq);
+               orig_fsz = skb_frag_size(f);
 
-       return skb;
+               do {
+                       bool fence = !(i || frag_offset);
+                       unsigned int fsz;
+
+                       n++;
+                       fsz = min_t(unsigned int, sq->hw_mtu, orig_fsz - frag_offset);
+                       skb_frag_size_set(f, fsz);
+                       if (tx_post_resync_dump(sq, f, priv_tx->tisn, fence)) {
+                               page_ref_add(skb_frag_page(f), n - 1);
+                               goto err_out;
+                       }
+
+                       skb_frag_off_add(f, fsz);
+                       frag_offset += fsz;
+               } while (frag_offset < orig_fsz);
+
+               page_ref_add(skb_frag_page(f), n - 1);
+       }
+
+       return MLX5E_KTLS_SYNC_DONE;
 
 err_out:
-       dev_kfree_skb_any(skb);
-       return NULL;
+       for (; i < info.nr_frags; i++)
+               /* The put_page() here undoes the page ref obtained in tx_sync_info_get().
+                * Page refs obtained for the DUMP WQEs above (by page_ref_add) will be
+                * released only upon their completions (or in mlx5e_free_txqsq_descs,
+                * if channel closes).
+                */
+               put_page(skb_frag_page(&info.frags[i]));
+
+       return MLX5E_KTLS_SYNC_FAIL;
 }
 
 struct sk_buff *mlx5e_ktls_handle_tx_skb(struct net_device *netdev,
@@ -419,10 +452,15 @@ struct sk_buff *mlx5e_ktls_handle_tx_skb(struct net_device *netdev,
 
        seq = ntohl(tcp_hdr(skb)->seq);
        if (unlikely(priv_tx->expected_seq != seq)) {
-               skb = mlx5e_ktls_tx_handle_ooo(priv_tx, sq, skb, seq);
-               if (unlikely(!skb))
+               enum mlx5e_ktls_sync_retval ret =
+                       mlx5e_ktls_tx_handle_ooo(priv_tx, sq, datalen, seq);
+
+               if (likely(ret == MLX5E_KTLS_SYNC_DONE))
+                       *wqe = mlx5e_sq_fetch_wqe(sq, sizeof(**wqe), pi);
+               else if (ret == MLX5E_KTLS_SYNC_FAIL)
+                       goto err_out;
+               else /* ret == MLX5E_KTLS_SYNC_SKIP_NO_DATA */
                        goto out;
-               *wqe = mlx5e_sq_fetch_wqe(sq, sizeof(**wqe), pi);
        }
 
        priv_tx->expected_seq = seq + datalen;
index c5a9c20d7f006f554afea951f14da6b06ed8ca57..327c93a7bd55a843dfb16bf27ccdacf61e69efc0 100644 (file)
@@ -1021,7 +1021,7 @@ static bool ext_link_mode_requested(const unsigned long *adver)
 {
 #define MLX5E_MIN_PTYS_EXT_LINK_MODE_BIT ETHTOOL_LINK_MODE_50000baseKR_Full_BIT
        int size = __ETHTOOL_LINK_MODE_MASK_NBITS - MLX5E_MIN_PTYS_EXT_LINK_MODE_BIT;
-       __ETHTOOL_DECLARE_LINK_MODE_MASK(modes);
+       __ETHTOOL_DECLARE_LINK_MODE_MASK(modes) = {0,};
 
        bitmap_set(modes, MLX5E_MIN_PTYS_EXT_LINK_MODE_BIT, size);
        return bitmap_intersects(modes, adver, __ETHTOOL_LINK_MODE_MASK_NBITS);
index 7569287f8f3c2129a92f6f2f0552051dd3762571..772bfdbdeb9c601f93354a654f02163c6db3fc17 100644 (file)
@@ -1128,6 +1128,7 @@ static int mlx5e_alloc_txqsq(struct mlx5e_channel *c,
        sq->txq_ix    = txq_ix;
        sq->uar_map   = mdev->mlx5e_res.bfreg.map;
        sq->min_inline_mode = params->tx_min_inline_mode;
+       sq->hw_mtu    = MLX5E_SW2HW_MTU(params, params->sw_mtu);
        sq->stats     = &c->priv->channel_stats[c->ix].sq[tc];
        sq->stop_room = MLX5E_SQ_STOP_ROOM;
        INIT_WORK(&sq->recover_work, mlx5e_tx_err_cqe_work);
@@ -1135,10 +1136,14 @@ static int mlx5e_alloc_txqsq(struct mlx5e_channel *c,
                set_bit(MLX5E_SQ_STATE_VLAN_NEED_L2_INLINE, &sq->state);
        if (MLX5_IPSEC_DEV(c->priv->mdev))
                set_bit(MLX5E_SQ_STATE_IPSEC, &sq->state);
+#ifdef CONFIG_MLX5_EN_TLS
        if (mlx5_accel_is_tls_device(c->priv->mdev)) {
                set_bit(MLX5E_SQ_STATE_TLS, &sq->state);
-               sq->stop_room += MLX5E_SQ_TLS_ROOM;
+               sq->stop_room += MLX5E_SQ_TLS_ROOM +
+                       mlx5e_ktls_dumps_num_wqebbs(sq, MAX_SKB_FRAGS,
+                                                   TLS_MAX_PAYLOAD_SIZE);
        }
+#endif
 
        param->wq.db_numa_node = cpu_to_node(c->cpu);
        err = mlx5_wq_cyc_create(mdev, &param->wq, sqc_wq, wq, &sq->wq_ctrl);
@@ -1349,9 +1354,13 @@ static void mlx5e_deactivate_txqsq(struct mlx5e_txqsq *sq)
        /* last doorbell out, godspeed .. */
        if (mlx5e_wqc_has_room_for(wq, sq->cc, sq->pc, 1)) {
                u16 pi = mlx5_wq_cyc_ctr2ix(wq, sq->pc);
+               struct mlx5e_tx_wqe_info *wi;
                struct mlx5e_tx_wqe *nop;
 
-               sq->db.wqe_info[pi].skb = NULL;
+               wi = &sq->db.wqe_info[pi];
+
+               memset(wi, 0, sizeof(*wi));
+               wi->num_wqebbs = 1;
                nop = mlx5e_post_nop(wq, sq->sqn, &sq->pc);
                mlx5e_notify_hw(wq, sq->pc, sq->uar_map, &nop->ctrl);
        }
index 95892a3b63a13578e5532f63c96cadf0edaa434e..cd9bb7c7b3413651a9835925d69305299d007dcf 100644 (file)
@@ -611,8 +611,8 @@ static void mlx5e_rep_update_flows(struct mlx5e_priv *priv,
 
        mutex_lock(&esw->offloads.encap_tbl_lock);
        encap_connected = !!(e->flags & MLX5_ENCAP_ENTRY_VALID);
-       if (e->compl_result || (encap_connected == neigh_connected &&
-                               ether_addr_equal(e->h_dest, ha)))
+       if (e->compl_result < 0 || (encap_connected == neigh_connected &&
+                                   ether_addr_equal(e->h_dest, ha)))
                goto unlock;
 
        mlx5e_take_all_encap_flows(e, &flow_list);
index d6a547238de03fd9778d7f786346c00647963c68..82cffb3a99640f25fa6f6c0a8f52151194874058 100644 (file)
@@ -1386,8 +1386,11 @@ int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget)
        if (unlikely(!test_bit(MLX5E_RQ_STATE_ENABLED, &rq->state)))
                return 0;
 
-       if (rq->cqd.left)
+       if (rq->cqd.left) {
                work_done += mlx5e_decompress_cqes_cont(rq, cqwq, 0, budget);
+               if (rq->cqd.left || work_done >= budget)
+                       goto out;
+       }
 
        cqe = mlx5_cqwq_get_cqe(cqwq);
        if (!cqe) {
index 840ec945ccbab466863fb6f43a29bbfd23d08c4a..bbff8d8ded767ce411dca360fe43ef5a3942ef26 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/udp.h>
 #include <net/udp.h>
 #include "en.h"
+#include "en/port.h"
 
 enum {
        MLX5E_ST_LINK_STATE,
@@ -80,22 +81,12 @@ static int mlx5e_test_link_state(struct mlx5e_priv *priv)
 
 static int mlx5e_test_link_speed(struct mlx5e_priv *priv)
 {
-       u32 out[MLX5_ST_SZ_DW(ptys_reg)];
-       u32 eth_proto_oper;
-       int i;
+       u32 speed;
 
        if (!netif_carrier_ok(priv->netdev))
                return 1;
 
-       if (mlx5_query_port_ptys(priv->mdev, out, sizeof(out), MLX5_PTYS_EN, 1))
-               return 1;
-
-       eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
-       for (i = 0; i < MLX5E_LINK_MODES_NUMBER; i++) {
-               if (eth_proto_oper & MLX5E_PROT_MASK(i))
-                       return 0;
-       }
-       return 1;
+       return mlx5e_port_linkspeed(priv->mdev, &speed);
 }
 
 struct mlx5ehdr {
index ac6fdcda7019b28c92c11bc1257705e23698e988..7e6ebd0505cc044963493e58563f45661b652441 100644 (file)
@@ -52,11 +52,12 @@ static const struct counter_desc sw_stats_desc[] = {
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_encrypted_bytes) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_ctx) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_ooo) },
+       { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_dump_packets) },
+       { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_dump_bytes) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_resync_bytes) },
+       { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_skip_no_sync_data) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_drop_no_sync_data) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_drop_bypass_req) },
-       { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_dump_packets) },
-       { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_dump_bytes) },
 #endif
 
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_lro_packets) },
@@ -288,11 +289,12 @@ static void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv)
                        s->tx_tls_encrypted_bytes   += sq_stats->tls_encrypted_bytes;
                        s->tx_tls_ctx               += sq_stats->tls_ctx;
                        s->tx_tls_ooo               += sq_stats->tls_ooo;
+                       s->tx_tls_dump_bytes        += sq_stats->tls_dump_bytes;
+                       s->tx_tls_dump_packets      += sq_stats->tls_dump_packets;
                        s->tx_tls_resync_bytes      += sq_stats->tls_resync_bytes;
+                       s->tx_tls_skip_no_sync_data += sq_stats->tls_skip_no_sync_data;
                        s->tx_tls_drop_no_sync_data += sq_stats->tls_drop_no_sync_data;
                        s->tx_tls_drop_bypass_req   += sq_stats->tls_drop_bypass_req;
-                       s->tx_tls_dump_bytes        += sq_stats->tls_dump_bytes;
-                       s->tx_tls_dump_packets      += sq_stats->tls_dump_packets;
 #endif
                        s->tx_cqes              += sq_stats->cqes;
                }
@@ -1472,10 +1474,12 @@ static const struct counter_desc sq_stats_desc[] = {
        { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_encrypted_bytes) },
        { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_ctx) },
        { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_ooo) },
-       { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_drop_no_sync_data) },
-       { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_drop_bypass_req) },
        { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_dump_packets) },
        { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_dump_bytes) },
+       { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_resync_bytes) },
+       { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_skip_no_sync_data) },
+       { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_drop_no_sync_data) },
+       { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_drop_bypass_req) },
 #endif
        { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, csum_none) },
        { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, stopped) },
index 79f261bf86ac8e54932b7a0ef2c925fd2fd54d3c..869f3502f6312845e35d888f972a5a78a8a3b84e 100644 (file)
@@ -129,11 +129,12 @@ struct mlx5e_sw_stats {
        u64 tx_tls_encrypted_bytes;
        u64 tx_tls_ctx;
        u64 tx_tls_ooo;
+       u64 tx_tls_dump_packets;
+       u64 tx_tls_dump_bytes;
        u64 tx_tls_resync_bytes;
+       u64 tx_tls_skip_no_sync_data;
        u64 tx_tls_drop_no_sync_data;
        u64 tx_tls_drop_bypass_req;
-       u64 tx_tls_dump_packets;
-       u64 tx_tls_dump_bytes;
 #endif
 
        u64 rx_xsk_packets;
@@ -273,11 +274,12 @@ struct mlx5e_sq_stats {
        u64 tls_encrypted_bytes;
        u64 tls_ctx;
        u64 tls_ooo;
+       u64 tls_dump_packets;
+       u64 tls_dump_bytes;
        u64 tls_resync_bytes;
+       u64 tls_skip_no_sync_data;
        u64 tls_drop_no_sync_data;
        u64 tls_drop_bypass_req;
-       u64 tls_dump_packets;
-       u64 tls_dump_bytes;
 #endif
        /* less likely accessed in data path */
        u64 csum_none;
index 3e78a727f3e68634e2fb5f7e65838dce963a90bc..fda0b37075e8c444bdf2adba3a0e5dc47ca47adf 100644 (file)
@@ -1278,8 +1278,10 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
        mlx5_eswitch_del_vlan_action(esw, attr);
 
        for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++)
-               if (attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP)
+               if (attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP) {
                        mlx5e_detach_encap(priv, flow, out_index);
+                       kfree(attr->parse_attr->tun_info[out_index]);
+               }
        kvfree(attr->parse_attr);
 
        if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
@@ -1559,6 +1561,7 @@ static void mlx5e_encap_dealloc(struct mlx5e_priv *priv, struct mlx5e_encap_entr
                        mlx5_packet_reformat_dealloc(priv->mdev, e->pkt_reformat);
        }
 
+       kfree(e->tun_info);
        kfree(e->encap_header);
        kfree_rcu(e, rcu);
 }
@@ -2972,6 +2975,13 @@ mlx5e_encap_get(struct mlx5e_priv *priv, struct encap_key *key,
        return NULL;
 }
 
+static struct ip_tunnel_info *dup_tun_info(const struct ip_tunnel_info *tun_info)
+{
+       size_t tun_size = sizeof(*tun_info) + tun_info->options_len;
+
+       return kmemdup(tun_info, tun_size, GFP_KERNEL);
+}
+
 static int mlx5e_attach_encap(struct mlx5e_priv *priv,
                              struct mlx5e_tc_flow *flow,
                              struct net_device *mirred_dev,
@@ -3028,13 +3038,15 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv,
        refcount_set(&e->refcnt, 1);
        init_completion(&e->res_ready);
 
+       tun_info = dup_tun_info(tun_info);
+       if (!tun_info) {
+               err = -ENOMEM;
+               goto out_err_init;
+       }
        e->tun_info = tun_info;
        err = mlx5e_tc_tun_init_encap_attr(mirred_dev, priv, e, extack);
-       if (err) {
-               kfree(e);
-               e = NULL;
-               goto out_err;
-       }
+       if (err)
+               goto out_err_init;
 
        INIT_LIST_HEAD(&e->flows);
        hash_add_rcu(esw->offloads.encap_tbl, &e->encap_hlist, hash_key);
@@ -3075,6 +3087,12 @@ out_err:
        if (e)
                mlx5e_encap_put(priv, e);
        return err;
+
+out_err_init:
+       mutex_unlock(&esw->offloads.encap_tbl_lock);
+       kfree(tun_info);
+       kfree(e);
+       return err;
 }
 
 static int parse_tc_vlan_action(struct mlx5e_priv *priv,
@@ -3160,7 +3178,7 @@ static int add_vlan_pop_action(struct mlx5e_priv *priv,
                               struct mlx5_esw_flow_attr *attr,
                               u32 *action)
 {
-       int nest_level = vlan_get_encap_level(attr->parse_attr->filter_dev);
+       int nest_level = attr->parse_attr->filter_dev->lower_level;
        struct flow_action_entry vlan_act = {
                .id = FLOW_ACTION_VLAN_POP,
        };
@@ -3295,7 +3313,9 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
                        } else if (encap) {
                                parse_attr->mirred_ifindex[attr->out_count] =
                                        out_dev->ifindex;
-                               parse_attr->tun_info[attr->out_count] = info;
+                               parse_attr->tun_info[attr->out_count] = dup_tun_info(info);
+                               if (!parse_attr->tun_info[attr->out_count])
+                                       return -ENOMEM;
                                encap = false;
                                attr->dests[attr->out_count].flags |=
                                        MLX5_ESW_DEST_ENCAP;
index d3a67a9b4eba76076ea899a82649f027e0603a92..67dc4f0921b649f7f38c750c4069d042261d1777 100644 (file)
@@ -403,7 +403,10 @@ netdev_tx_t mlx5e_xmit(struct sk_buff *skb, struct net_device *dev)
 static void mlx5e_dump_error_cqe(struct mlx5e_txqsq *sq,
                                 struct mlx5_err_cqe *err_cqe)
 {
-       u32 ci = mlx5_cqwq_get_ci(&sq->cq.wq);
+       struct mlx5_cqwq *wq = &sq->cq.wq;
+       u32 ci;
+
+       ci = mlx5_cqwq_ctr2ix(wq, wq->cc - 1);
 
        netdev_err(sq->channel->netdev,
                   "Error cqe on cqn 0x%x, ci 0x%x, sqn 0x%x, opcode 0x%x, syndrome 0x%x, vendor syndrome 0x%x\n",
@@ -479,14 +482,7 @@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget)
                        skb = wi->skb;
 
                        if (unlikely(!skb)) {
-#ifdef CONFIG_MLX5_EN_TLS
-                               if (wi->resync_dump_frag) {
-                                       struct mlx5e_sq_dma *dma =
-                                               mlx5e_dma_get(sq, dma_fifo_cc++);
-
-                                       mlx5e_ktls_tx_handle_resync_dump_comp(sq, wi, dma);
-                               }
-#endif
+                               mlx5e_ktls_tx_handle_resync_dump_comp(sq, wi, &dma_fifo_cc);
                                sqcc += wi->num_wqebbs;
                                continue;
                        }
@@ -542,29 +538,38 @@ void mlx5e_free_txqsq_descs(struct mlx5e_txqsq *sq)
 {
        struct mlx5e_tx_wqe_info *wi;
        struct sk_buff *skb;
+       u32 dma_fifo_cc;
+       u16 sqcc;
        u16 ci;
        int i;
 
-       while (sq->cc != sq->pc) {
-               ci = mlx5_wq_cyc_ctr2ix(&sq->wq, sq->cc);
+       sqcc = sq->cc;
+       dma_fifo_cc = sq->dma_fifo_cc;
+
+       while (sqcc != sq->pc) {
+               ci = mlx5_wq_cyc_ctr2ix(&sq->wq, sqcc);
                wi = &sq->db.wqe_info[ci];
                skb = wi->skb;
 
-               if (!skb) { /* nop */
-                       sq->cc++;
+               if (!skb) {
+                       mlx5e_ktls_tx_handle_resync_dump_comp(sq, wi, &dma_fifo_cc);
+                       sqcc += wi->num_wqebbs;
                        continue;
                }
 
                for (i = 0; i < wi->num_dma; i++) {
                        struct mlx5e_sq_dma *dma =
-                               mlx5e_dma_get(sq, sq->dma_fifo_cc++);
+                               mlx5e_dma_get(sq, dma_fifo_cc++);
 
                        mlx5e_tx_dma_unmap(sq->pdev, dma);
                }
 
                dev_kfree_skb_any(skb);
-               sq->cc += wi->num_wqebbs;
+               sqcc += wi->num_wqebbs;
        }
+
+       sq->dma_fifo_cc = dma_fifo_cc;
+       sq->cc = sqcc;
 }
 
 #ifdef CONFIG_MLX5_CORE_IPOIB
index 00d71db15f2217f437b4d8438d1a8087d35ab080..9004a07e457a48ca63cbdde6f5b280181e108c09 100644 (file)
@@ -285,7 +285,6 @@ mlx5_eswitch_add_fwd_rule(struct mlx5_eswitch *esw,
 
        mlx5_eswitch_set_rule_source_port(esw, spec, attr);
 
-       spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS;
        if (attr->outer_match_level != MLX5_MATCH_NONE)
                spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
 
@@ -1080,7 +1079,7 @@ static int esw_create_offloads_fdb_tables(struct mlx5_eswitch *esw, int nvports)
                            MLX5_CAP_GEN(dev, max_flow_counter_15_0);
        fdb_max = 1 << MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size);
 
-       esw_debug(dev, "Create offloads FDB table, min (max esw size(2^%d), max counters(%d), groups(%d), max flow table size(2^%d))\n",
+       esw_debug(dev, "Create offloads FDB table, min (max esw size(2^%d), max counters(%d), groups(%d), max flow table size(%d))\n",
                  MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size),
                  max_flow_counter, ESW_OFFLOADS_NUM_GROUPS,
                  fdb_max);
index 1d55a324a17e3d00b779d8fce3ad77b914471bdb..366bda1bb1c32edfaad041d0b158f160cdb591ed 100644 (file)
@@ -177,22 +177,33 @@ mlx5_eswitch_termtbl_actions_move(struct mlx5_flow_act *src,
        memset(&src->vlan[1], 0, sizeof(src->vlan[1]));
 }
 
+static bool mlx5_eswitch_offload_is_uplink_port(const struct mlx5_eswitch *esw,
+                                               const struct mlx5_flow_spec *spec)
+{
+       u32 port_mask, port_value;
+
+       if (MLX5_CAP_ESW_FLOWTABLE(esw->dev, flow_source))
+               return spec->flow_context.flow_source ==
+                                       MLX5_FLOW_CONTEXT_FLOW_SOURCE_UPLINK;
+
+       port_mask = MLX5_GET(fte_match_param, spec->match_criteria,
+                            misc_parameters.source_port);
+       port_value = MLX5_GET(fte_match_param, spec->match_value,
+                             misc_parameters.source_port);
+       return (port_mask & port_value & 0xffff) == MLX5_VPORT_UPLINK;
+}
+
 bool
 mlx5_eswitch_termtbl_required(struct mlx5_eswitch *esw,
                              struct mlx5_flow_act *flow_act,
                              struct mlx5_flow_spec *spec)
 {
-       u32 port_mask = MLX5_GET(fte_match_param, spec->match_criteria,
-                                misc_parameters.source_port);
-       u32 port_value = MLX5_GET(fte_match_param, spec->match_value,
-                                 misc_parameters.source_port);
-
        if (!MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, termination_table))
                return false;
 
        /* push vlan on RX */
        return (flow_act->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH) &&
-               ((port_mask & port_value) == MLX5_VPORT_UPLINK);
+               mlx5_eswitch_offload_is_uplink_port(esw, spec);
 }
 
 struct mlx5_flow_handle *
index 4c50efe4e7f11878895a98db4305b52d21bcbb15..61021133029e6a62452bbbad84d7894ef6df00bd 100644 (file)
@@ -464,8 +464,10 @@ static int mlx5_fpga_conn_create_cq(struct mlx5_fpga_conn *conn, int cq_size)
        }
 
        err = mlx5_vector2eqn(mdev, smp_processor_id(), &eqn, &irqn);
-       if (err)
+       if (err) {
+               kvfree(in);
                goto err_cqwq;
+       }
 
        cqc = MLX5_ADDR_OF(create_cq_in, in, cq_context);
        MLX5_SET(cqc, cqc, log_cq_size, ilog2(cq_size));
index 579c306caa7b10345c5a0f9ae7c9892d489f1de9..3c816e81f8d9bab405cbeeb3901d40341cbdd60d 100644 (file)
@@ -507,7 +507,8 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev,
                                MLX5_SET(dest_format_struct, in_dests,
                                         destination_eswitch_owner_vhca_id,
                                         dst->dest_attr.vport.vhca_id);
-                               if (extended_dest) {
+                               if (extended_dest &&
+                                   dst->dest_attr.vport.pkt_reformat) {
                                        MLX5_SET(dest_format_struct, in_dests,
                                                 packet_reformat,
                                                 !!(dst->dest_attr.vport.flags &
index d685122d9ff761794a7f89d860a90e25801f29fc..c07f3154437c6062679fd241522eb91f4afed771 100644 (file)
@@ -572,7 +572,7 @@ mlx5_fw_fatal_reporter_dump(struct devlink_health_reporter *reporter,
                return -ENOMEM;
        err = mlx5_crdump_collect(dev, cr_data);
        if (err)
-               return err;
+               goto free_data;
 
        if (priv_ctx) {
                struct mlx5_fw_reporter_ctx *fw_reporter_ctx = priv_ctx;
index b74b7d0f659052e7148a20ccef762b9de06a4523..004c56c2fc0cba29cc53de5200939a9003969f05 100644 (file)
@@ -1577,6 +1577,7 @@ int mlx5dr_action_destroy(struct mlx5dr_action *action)
                break;
        case DR_ACTION_TYP_MODIFY_HDR:
                mlx5dr_icm_free_chunk(action->rewrite.chunk);
+               kfree(action->rewrite.data);
                refcount_dec(&action->rewrite.dmn->refcount);
                break;
        default:
index e8b656075c6ff3d90a3d857fbb4bbab752183c33..5dcb8baf491a5dce2937626f55453690b655765b 100644 (file)
@@ -1096,6 +1096,8 @@ dr_rule_create_rule_nic(struct mlx5dr_rule *rule,
        if (htbl)
                mlx5dr_htbl_put(htbl);
 
+       kfree(hw_ste_arr);
+
        return 0;
 
 free_ste:
index 14dcc786926ddc22ea93c6820cc117df40dd6316..4421ab22182fe7c5d254dba03e5b3ab415ea392a 100644 (file)
@@ -1186,7 +1186,7 @@ __mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
        if (err)
                goto err_thermal_init;
 
-       if (mlxsw_driver->params_register && !reload)
+       if (mlxsw_driver->params_register)
                devlink_params_publish(devlink);
 
        return 0;
@@ -1259,7 +1259,7 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core,
                        return;
        }
 
-       if (mlxsw_core->driver->params_unregister && !reload)
+       if (mlxsw_core->driver->params_unregister)
                devlink_params_unpublish(devlink);
        mlxsw_thermal_fini(mlxsw_core->thermal);
        mlxsw_hwmon_fini(mlxsw_core->hwmon);
index 4d1bce4389c792a163b87938e4b8142a83808c2e..672ea1342addaebb55b2463756cadcf0a52b33c2 100644 (file)
@@ -261,8 +261,15 @@ static int ocelot_vlan_vid_add(struct net_device *dev, u16 vid, bool pvid,
                port->pvid = vid;
 
        /* Untagged egress vlan clasification */
-       if (untagged)
+       if (untagged && port->vid != vid) {
+               if (port->vid) {
+                       dev_err(ocelot->dev,
+                               "Port already has a native VLAN: %d\n",
+                               port->vid);
+                       return -EBUSY;
+               }
                port->vid = vid;
+       }
 
        ocelot_vlan_port_apply(ocelot, port);
 
@@ -934,7 +941,7 @@ end:
 static int ocelot_vlan_rx_add_vid(struct net_device *dev, __be16 proto,
                                  u16 vid)
 {
-       return ocelot_vlan_vid_add(dev, vid, false, true);
+       return ocelot_vlan_vid_add(dev, vid, false, false);
 }
 
 static int ocelot_vlan_rx_kill_vid(struct net_device *dev, __be16 proto,
@@ -1673,9 +1680,6 @@ static int ocelot_netdevice_port_event(struct net_device *dev,
        struct ocelot_port *ocelot_port = netdev_priv(dev);
        int err = 0;
 
-       if (!ocelot_netdevice_dev_check(dev))
-               return 0;
-
        switch (event) {
        case NETDEV_CHANGEUPPER:
                if (netif_is_bridge_master(info->upper_dev)) {
@@ -1712,12 +1716,16 @@ static int ocelot_netdevice_event(struct notifier_block *unused,
        struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        int ret = 0;
 
+       if (!ocelot_netdevice_dev_check(dev))
+               return 0;
+
        if (event == NETDEV_PRECHANGEUPPER &&
            netif_is_lag_master(info->upper_dev)) {
                struct netdev_lag_upper_info *lag_upper_info = info->upper_info;
                struct netlink_ext_ack *extack;
 
-               if (lag_upper_info->tx_type != NETDEV_LAG_TX_TYPE_HASH) {
+               if (lag_upper_info &&
+                   lag_upper_info->tx_type != NETDEV_LAG_TX_TYPE_HASH) {
                        extack = netdev_notifier_info_to_extack(&info->info);
                        NL_SET_ERR_MSG_MOD(extack, "LAG device using unsupported Tx type");
 
index e40773c01a44b57dffd13682b13f3385caadf689..06ac806052bc1c61909da41af57829afb2b5ffae 100644 (file)
@@ -523,7 +523,7 @@ void __ocelot_write_ix(struct ocelot *ocelot, u32 val, u32 reg, u32 offset);
 #define ocelot_write_rix(ocelot, val, reg, ri) __ocelot_write_ix(ocelot, val, reg, reg##_RSZ * (ri))
 #define ocelot_write(ocelot, val, reg) __ocelot_write_ix(ocelot, val, reg, 0)
 
-void __ocelot_rmw_ix(struct ocelot *ocelot, u32 val, u32 reg, u32 mask,
+void __ocelot_rmw_ix(struct ocelot *ocelot, u32 val, u32 mask, u32 reg,
                     u32 offset);
 #define ocelot_rmw_ix(ocelot, val, m, reg, gi, ri) __ocelot_rmw_ix(ocelot, val, m, reg, reg##_GSZ * (gi) + reg##_RSZ * (ri))
 #define ocelot_rmw_gix(ocelot, val, m, reg, gi) __ocelot_rmw_ix(ocelot, val, m, reg, reg##_GSZ * (gi))
index 1eef446036d6a2be6bd4acb306c782f7b169f2f1..79d72c88bbef2a16a584bef5359e958fc001344d 100644 (file)
@@ -299,22 +299,6 @@ static void nfp_repr_clean(struct nfp_repr *repr)
        nfp_port_free(repr->port);
 }
 
-static struct lock_class_key nfp_repr_netdev_xmit_lock_key;
-static struct lock_class_key nfp_repr_netdev_addr_lock_key;
-
-static void nfp_repr_set_lockdep_class_one(struct net_device *dev,
-                                          struct netdev_queue *txq,
-                                          void *_unused)
-{
-       lockdep_set_class(&txq->_xmit_lock, &nfp_repr_netdev_xmit_lock_key);
-}
-
-static void nfp_repr_set_lockdep_class(struct net_device *dev)
-{
-       lockdep_set_class(&dev->addr_list_lock, &nfp_repr_netdev_addr_lock_key);
-       netdev_for_each_tx_queue(dev, nfp_repr_set_lockdep_class_one, NULL);
-}
-
 int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
                  u32 cmsg_port_id, struct nfp_port *port,
                  struct net_device *pf_netdev)
@@ -324,8 +308,6 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
        u32 repr_cap = nn->tlv_caps.repr_cap;
        int err;
 
-       nfp_repr_set_lockdep_class(netdev);
-
        repr->port = port;
        repr->dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, GFP_KERNEL);
        if (!repr->dst)
index 72107a0627a9957de0ce4c01e6b561f37599b510..20faa8d24c9ffea255d25bf5103b16f94613d301 100644 (file)
@@ -1,6 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0
 /* Copyright(c) 2017 - 2019 Pensando Systems, Inc */
 
+#include <linux/printk.h>
+#include <linux/dynamic_debug.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/rtnetlink.h>
index 15e432386b35a2ad0733c0df28e4002588bb66ea..aab3114134128f578fc2eb4acf849bcabe282df2 100644 (file)
@@ -1,6 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0
 /* Copyright(c) 2017 - 2019 Pensando Systems, Inc */
 
+#include <linux/printk.h>
+#include <linux/dynamic_debug.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/utsname.h>
index 2ce70097d018b8e7e846e71d4a9b79204838c0cf..38f7f40b3a4d0dd5773a24185e6602d7479fc8b7 100644 (file)
 #define QED_ROCE_QPS                   (8192)
 #define QED_ROCE_DPIS                  (8)
 #define QED_RDMA_SRQS                   QED_ROCE_QPS
-#define QED_NVM_CFG_SET_FLAGS          0xE
-#define QED_NVM_CFG_SET_PF_FLAGS       0x1E
 #define QED_NVM_CFG_GET_FLAGS          0xA
 #define QED_NVM_CFG_GET_PF_FLAGS       0x1A
+#define QED_NVM_CFG_MAX_ATTRS          50
 
 static char version[] =
        "QLogic FastLinQ 4xxxx Core Module qed " DRV_MODULE_VERSION "\n";
@@ -2255,6 +2254,7 @@ static int qed_nvm_flash_cfg_write(struct qed_dev *cdev, const u8 **data)
 {
        struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
        u8 entity_id, len, buf[32];
+       bool need_nvm_init = true;
        struct qed_ptt *ptt;
        u16 cfg_id, count;
        int rc = 0, i;
@@ -2271,8 +2271,10 @@ static int qed_nvm_flash_cfg_write(struct qed_dev *cdev, const u8 **data)
 
        DP_VERBOSE(cdev, NETIF_MSG_DRV,
                   "Read config ids: num_attrs = %0d\n", count);
-       /* NVM CFG ID attributes */
-       for (i = 0; i < count; i++) {
+       /* NVM CFG ID attributes. Start loop index from 1 to avoid additional
+        * arithmetic operations in the implementation.
+        */
+       for (i = 1; i <= count; i++) {
                cfg_id = *((u16 *)*data);
                *data += 2;
                entity_id = **data;
@@ -2282,8 +2284,21 @@ static int qed_nvm_flash_cfg_write(struct qed_dev *cdev, const u8 **data)
                memcpy(buf, *data, len);
                *data += len;
 
-               flags = entity_id ? QED_NVM_CFG_SET_PF_FLAGS :
-                       QED_NVM_CFG_SET_FLAGS;
+               flags = 0;
+               if (need_nvm_init) {
+                       flags |= QED_NVM_CFG_OPTION_INIT;
+                       need_nvm_init = false;
+               }
+
+               /* Commit to flash and free the resources */
+               if (!(i % QED_NVM_CFG_MAX_ATTRS) || i == count) {
+                       flags |= QED_NVM_CFG_OPTION_COMMIT |
+                                QED_NVM_CFG_OPTION_FREE;
+                       need_nvm_init = true;
+               }
+
+               if (entity_id)
+                       flags |= QED_NVM_CFG_OPTION_ENTITY_SEL;
 
                DP_VERBOSE(cdev, NETIF_MSG_DRV,
                           "cfg_id = %d entity = %d len = %d\n", cfg_id,
index 78f77b712b1012509528e3a9f2889d6ea057b596..dcb5c917f3733fd60642bbff0dc45104bd91902c 100644 (file)
@@ -2005,7 +2005,7 @@ static void qed_iov_vf_mbx_stop_vport(struct qed_hwfn *p_hwfn,
            (qed_iov_validate_active_txq(p_hwfn, vf))) {
                vf->b_malicious = true;
                DP_NOTICE(p_hwfn,
-                         "VF [%02x] - considered malicious; Unable to stop RX/TX queuess\n",
+                         "VF [%02x] - considered malicious; Unable to stop RX/TX queues\n",
                          vf->abs_vf_id);
                status = PFVF_STATUS_MALICIOUS;
                goto out;
index 8d1c208f778f37287792b1a87aa1796506c5139a..a220cc7c947a1ef4a4552007bae04ceb8bd3eceb 100644 (file)
@@ -1208,8 +1208,16 @@ enum qede_remove_mode {
 static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode)
 {
        struct net_device *ndev = pci_get_drvdata(pdev);
-       struct qede_dev *edev = netdev_priv(ndev);
-       struct qed_dev *cdev = edev->cdev;
+       struct qede_dev *edev;
+       struct qed_dev *cdev;
+
+       if (!ndev) {
+               dev_info(&pdev->dev, "Device has already been removed\n");
+               return;
+       }
+
+       edev = netdev_priv(ndev);
+       cdev = edev->cdev;
 
        DP_INFO(edev, "Starting qede_remove\n");
 
index 9c54b715228e020bac2ab04906e7e914ba56d821..06de59521fc4a5e0d8861672525ab39406f98f18 100644 (file)
@@ -57,10 +57,10 @@ static int rmnet_unregister_real_device(struct net_device *real_dev,
        if (port->nr_rmnet_devs)
                return -EINVAL;
 
-       kfree(port);
-
        netdev_rx_handler_unregister(real_dev);
 
+       kfree(port);
+
        /* release reference on real_dev */
        dev_put(real_dev);
 
index 350b0d949611efa439c36ad4d0458cfd2d9d5c74..c4e961ea44d5d57e6943b6534b1bfbd0c167a13d 100644 (file)
@@ -916,6 +916,9 @@ static void r8168g_mdio_write(struct rtl8169_private *tp, int reg, int value)
 
 static int r8168g_mdio_read(struct rtl8169_private *tp, int reg)
 {
+       if (reg == 0x1f)
+               return tp->ocp_base == OCP_STD_PHY_BASE ? 0 : tp->ocp_base >> 4;
+
        if (tp->ocp_base != OCP_STD_PHY_BASE)
                reg -= 0x10;
 
@@ -1029,6 +1032,10 @@ static int r8168dp_2_mdio_read(struct rtl8169_private *tp, int reg)
 {
        int value;
 
+       /* Work around issue with chip reporting wrong PHY ID */
+       if (reg == MII_PHYSID2)
+               return 0xc912;
+
        r8168dp_2_mdio_start(tp);
 
        value = r8169_mdio_read(tp, reg);
index 5a7b0aca1d31af097ece2070ad0f657be3ea49bf..66e60c7e98504f3ad555fb945f58c06a91ba3a32 100644 (file)
@@ -432,7 +432,7 @@ static void dwmac4_set_filter(struct mac_device_info *hw,
                         * bits used depends on the hardware configuration
                         * selected at core configuration time.
                         */
-                       int bit_nr = bitrev32(~crc32_le(~0, ha->addr,
+                       u32 bit_nr = bitrev32(~crc32_le(~0, ha->addr,
                                        ETH_ALEN)) >> (32 - mcbitslog2);
                        /* The most significant bit determines the register to
                         * use (H/L) while the other 5 bits determine the bit
index 5031398e612c241b12b99fc64c1205722ea6ea42..070bd7d1ae4cab99a8f351d4151c7ec7bdaec430 100644 (file)
@@ -224,6 +224,7 @@ static void dwxgmac2_config_cbs(struct mac_device_info *hw,
        writel(low_credit, ioaddr + XGMAC_MTL_TCx_LOCREDIT(queue));
 
        value = readl(ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(queue));
+       value &= ~XGMAC_TSA;
        value |= XGMAC_CC | XGMAC_CBS;
        writel(value, ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(queue));
 }
@@ -463,7 +464,7 @@ static void dwxgmac2_set_filter(struct mac_device_info *hw,
                value |= XGMAC_FILTER_HMC;
 
                netdev_for_each_mc_addr(ha, dev) {
-                       int nr = (bitrev32(~crc32_le(~0, ha->addr, 6)) >>
+                       u32 nr = (bitrev32(~crc32_le(~0, ha->addr, 6)) >>
                                        (32 - mcbitslog2));
                        mc_filter[nr >> 5] |= (1 << (nr & 0x1F));
                }
index ae48154f933cb1bd3e192874d77f76866478e566..bd5838ce1e8a9d8343e735cb30502010b780ce7c 100644 (file)
@@ -288,7 +288,8 @@ static int dwxgmac2_get_rx_hash(struct dma_desc *p, u32 *hash,
 
 static int dwxgmac2_get_rx_header_len(struct dma_desc *p, unsigned int *len)
 {
-       *len = le32_to_cpu(p->des2) & XGMAC_RDES2_HL;
+       if (le32_to_cpu(p->des3) & XGMAC_RDES3_L34T)
+               *len = le32_to_cpu(p->des2) & XGMAC_RDES2_HL;
        return 0;
 }
 
index 965cbe3e6f51f262344e4bd9f62d22d75718d295..f70ca5300b82c8b64ad1e855f1eee33ce78b626d 100644 (file)
@@ -369,7 +369,7 @@ static void dwxgmac2_get_hw_feature(void __iomem *ioaddr,
        dma_cap->eee = (hw_cap & XGMAC_HWFEAT_EEESEL) >> 13;
        dma_cap->atime_stamp = (hw_cap & XGMAC_HWFEAT_TSSEL) >> 12;
        dma_cap->av = (hw_cap & XGMAC_HWFEAT_AVSEL) >> 11;
-       dma_cap->av &= !(hw_cap & XGMAC_HWFEAT_RAVSEL) >> 10;
+       dma_cap->av &= !((hw_cap & XGMAC_HWFEAT_RAVSEL) >> 10);
        dma_cap->arpoffsel = (hw_cap & XGMAC_HWFEAT_ARPOFFSEL) >> 9;
        dma_cap->rmon = (hw_cap & XGMAC_HWFEAT_MMCSEL) >> 8;
        dma_cap->pmt_magic_frame = (hw_cap & XGMAC_HWFEAT_MGKSEL) >> 7;
@@ -470,6 +470,7 @@ static void dwxgmac2_enable_tso(void __iomem *ioaddr, bool en, u32 chan)
 static void dwxgmac2_qmode(void __iomem *ioaddr, u32 channel, u8 qmode)
 {
        u32 value = readl(ioaddr + XGMAC_MTL_TXQ_OPMODE(channel));
+       u32 flow = readl(ioaddr + XGMAC_RX_FLOW_CTRL);
 
        value &= ~XGMAC_TXQEN;
        if (qmode != MTL_QUEUE_AVB) {
@@ -477,6 +478,7 @@ static void dwxgmac2_qmode(void __iomem *ioaddr, u32 channel, u8 qmode)
                writel(0, ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(channel));
        } else {
                value |= 0x1 << XGMAC_TXQEN_SHIFT;
+               writel(flow & (~XGMAC_RFE), ioaddr + XGMAC_RX_FLOW_CTRL);
        }
 
        writel(value, ioaddr +  XGMAC_MTL_TXQ_OPMODE(channel));
index a223584f5f9a67da9ea7492a63c3f57cef08fd40..252cf48c581665ff99276672d840e01e42ff5e77 100644 (file)
 #define MMC_XGMAC_RX_PKT_SMD_ERR       0x22c
 #define MMC_XGMAC_RX_PKT_ASSEMBLY_OK   0x230
 #define MMC_XGMAC_RX_FPE_FRAG          0x234
+#define MMC_XGMAC_RX_IPC_INTR_MASK     0x25c
 
 static void dwmac_mmc_ctrl(void __iomem *mmcaddr, unsigned int mode)
 {
@@ -333,8 +334,9 @@ static void dwxgmac_mmc_ctrl(void __iomem *mmcaddr, unsigned int mode)
 
 static void dwxgmac_mmc_intr_all_mask(void __iomem *mmcaddr)
 {
-       writel(MMC_DEFAULT_MASK, mmcaddr + MMC_RX_INTR_MASK);
-       writel(MMC_DEFAULT_MASK, mmcaddr + MMC_TX_INTR_MASK);
+       writel(0x0, mmcaddr + MMC_RX_INTR_MASK);
+       writel(0x0, mmcaddr + MMC_TX_INTR_MASK);
+       writel(MMC_DEFAULT_MASK, mmcaddr + MMC_XGMAC_RX_IPC_INTR_MASK);
 }
 
 static void dwxgmac_read_mmc_reg(void __iomem *addr, u32 reg, u32 *dest)
index 3dfd04e0506a37cb0c857d92c9980ff3f319017f..f826365c979d5092232cd7fe26f11b57faf1c64e 100644 (file)
@@ -2995,6 +2995,8 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
        } else {
                stmmac_set_desc_addr(priv, first, des);
                tmp_pay_len = pay_len;
+               des += proto_hdr_len;
+               pay_len = 0;
        }
 
        stmmac_tso_allocator(priv, des, tmp_pay_len, (nfrags == 0), queue);
@@ -3022,6 +3024,19 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
        /* Only the last descriptor gets to point to the skb. */
        tx_q->tx_skbuff[tx_q->cur_tx] = skb;
 
+       /* Manage tx mitigation */
+       tx_q->tx_count_frames += nfrags + 1;
+       if (likely(priv->tx_coal_frames > tx_q->tx_count_frames) &&
+           !((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
+             priv->hwts_tx_en)) {
+               stmmac_tx_timer_arm(priv, queue);
+       } else {
+               desc = &tx_q->dma_tx[tx_q->cur_tx];
+               tx_q->tx_count_frames = 0;
+               stmmac_set_tx_ic(priv, desc);
+               priv->xstats.tx_set_ic_bit++;
+       }
+
        /* We've used all descriptors we need for this skb, however,
         * advance cur_tx so that it references a fresh descriptor.
         * ndo_start_xmit will fill this descriptor the next time it's
@@ -3039,19 +3054,6 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
        priv->xstats.tx_tso_frames++;
        priv->xstats.tx_tso_nfrags += nfrags;
 
-       /* Manage tx mitigation */
-       tx_q->tx_count_frames += nfrags + 1;
-       if (likely(priv->tx_coal_frames > tx_q->tx_count_frames) &&
-           !(priv->synopsys_id >= DWMAC_CORE_4_00 &&
-           (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
-           priv->hwts_tx_en)) {
-               stmmac_tx_timer_arm(priv, queue);
-       } else {
-               tx_q->tx_count_frames = 0;
-               stmmac_set_tx_ic(priv, desc);
-               priv->xstats.tx_set_ic_bit++;
-       }
-
        if (priv->sarc_type)
                stmmac_set_desc_sarc(priv, first, priv->sarc_type);
 
@@ -3223,6 +3225,27 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
        /* Only the last descriptor gets to point to the skb. */
        tx_q->tx_skbuff[entry] = skb;
 
+       /* According to the coalesce parameter the IC bit for the latest
+        * segment is reset and the timer re-started to clean the tx status.
+        * This approach takes care about the fragments: desc is the first
+        * element in case of no SG.
+        */
+       tx_q->tx_count_frames += nfrags + 1;
+       if (likely(priv->tx_coal_frames > tx_q->tx_count_frames) &&
+           !((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
+             priv->hwts_tx_en)) {
+               stmmac_tx_timer_arm(priv, queue);
+       } else {
+               if (likely(priv->extend_desc))
+                       desc = &tx_q->dma_etx[entry].basic;
+               else
+                       desc = &tx_q->dma_tx[entry];
+
+               tx_q->tx_count_frames = 0;
+               stmmac_set_tx_ic(priv, desc);
+               priv->xstats.tx_set_ic_bit++;
+       }
+
        /* We've used all descriptors we need for this skb, however,
         * advance cur_tx so that it references a fresh descriptor.
         * ndo_start_xmit will fill this descriptor the next time it's
@@ -3258,23 +3281,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
        dev->stats.tx_bytes += skb->len;
 
-       /* According to the coalesce parameter the IC bit for the latest
-        * segment is reset and the timer re-started to clean the tx status.
-        * This approach takes care about the fragments: desc is the first
-        * element in case of no SG.
-        */
-       tx_q->tx_count_frames += nfrags + 1;
-       if (likely(priv->tx_coal_frames > tx_q->tx_count_frames) &&
-           !(priv->synopsys_id >= DWMAC_CORE_4_00 &&
-           (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
-           priv->hwts_tx_en)) {
-               stmmac_tx_timer_arm(priv, queue);
-       } else {
-               tx_q->tx_count_frames = 0;
-               stmmac_set_tx_ic(priv, desc);
-               priv->xstats.tx_set_ic_bit++;
-       }
-
        if (priv->sarc_type)
                stmmac_set_desc_sarc(priv, first, priv->sarc_type);
 
@@ -3505,8 +3511,6 @@ read_again:
                if (unlikely(status & dma_own))
                        break;
 
-               count++;
-
                rx_q->cur_rx = STMMAC_GET_ENTRY(rx_q->cur_rx, DMA_RX_SIZE);
                next_entry = rx_q->cur_rx;
 
@@ -3533,6 +3537,7 @@ read_again:
                        goto read_again;
                if (unlikely(error)) {
                        dev_kfree_skb(skb);
+                       count++;
                        continue;
                }
 
@@ -3572,6 +3577,7 @@ read_again:
                        skb = napi_alloc_skb(&ch->rx_napi, len);
                        if (!skb) {
                                priv->dev->stats.rx_dropped++;
+                               count++;
                                continue;
                        }
 
@@ -3637,6 +3643,7 @@ read_again:
 
                priv->dev->stats.rx_packets++;
                priv->dev->stats.rx_bytes += len;
+               count++;
        }
 
        if (status & rx_not_ls) {
index e4ac3c4014328c50402f10bdf59c96a05e86f351..ac3f658105c01a39cb9d3a2ba970257bba52c653 100644 (file)
@@ -6,7 +6,9 @@
  * Author: Jose Abreu <joabreu@synopsys.com>
  */
 
+#include <linux/bitrev.h>
 #include <linux/completion.h>
+#include <linux/crc32.h>
 #include <linux/ethtool.h>
 #include <linux/ip.h>
 #include <linux/phy.h>
@@ -485,12 +487,48 @@ static int stmmac_filter_check(struct stmmac_priv *priv)
        return -EOPNOTSUPP;
 }
 
+static bool stmmac_hash_check(struct stmmac_priv *priv, unsigned char *addr)
+{
+       int mc_offset = 32 - priv->hw->mcast_bits_log2;
+       struct netdev_hw_addr *ha;
+       u32 hash, hash_nr;
+
+       /* First compute the hash for desired addr */
+       hash = bitrev32(~crc32_le(~0, addr, 6)) >> mc_offset;
+       hash_nr = hash >> 5;
+       hash = 1 << (hash & 0x1f);
+
+       /* Now, check if it collides with any existing one */
+       netdev_for_each_mc_addr(ha, priv->dev) {
+               u32 nr = bitrev32(~crc32_le(~0, ha->addr, ETH_ALEN)) >> mc_offset;
+               if (((nr >> 5) == hash_nr) && ((1 << (nr & 0x1f)) == hash))
+                       return false;
+       }
+
+       /* No collisions, address is good to go */
+       return true;
+}
+
+static bool stmmac_perfect_check(struct stmmac_priv *priv, unsigned char *addr)
+{
+       struct netdev_hw_addr *ha;
+
+       /* Check if it collides with any existing one */
+       netdev_for_each_uc_addr(ha, priv->dev) {
+               if (!memcmp(ha->addr, addr, ETH_ALEN))
+                       return false;
+       }
+
+       /* No collisions, address is good to go */
+       return true;
+}
+
 static int stmmac_test_hfilt(struct stmmac_priv *priv)
 {
-       unsigned char gd_addr[ETH_ALEN] = {0x01, 0xee, 0xdd, 0xcc, 0xbb, 0xaa};
-       unsigned char bd_addr[ETH_ALEN] = {0x01, 0x01, 0x02, 0x03, 0x04, 0x05};
+       unsigned char gd_addr[ETH_ALEN] = {0xf1, 0xee, 0xdd, 0xcc, 0xbb, 0xaa};
+       unsigned char bd_addr[ETH_ALEN] = {0xf1, 0xff, 0xff, 0xff, 0xff, 0xff};
        struct stmmac_packet_attrs attr = { };
-       int ret;
+       int ret, tries = 256;
 
        ret = stmmac_filter_check(priv);
        if (ret)
@@ -499,6 +537,16 @@ static int stmmac_test_hfilt(struct stmmac_priv *priv)
        if (netdev_mc_count(priv->dev) >= priv->hw->multicast_filter_bins)
                return -EOPNOTSUPP;
 
+       while (--tries) {
+               /* We only need to check the bd_addr for collisions */
+               bd_addr[ETH_ALEN - 1] = tries;
+               if (stmmac_hash_check(priv, bd_addr))
+                       break;
+       }
+
+       if (!tries)
+               return -EOPNOTSUPP;
+
        ret = dev_mc_add(priv->dev, gd_addr);
        if (ret)
                return ret;
@@ -523,13 +571,25 @@ cleanup:
 
 static int stmmac_test_pfilt(struct stmmac_priv *priv)
 {
-       unsigned char gd_addr[ETH_ALEN] = {0x00, 0x01, 0x44, 0x55, 0x66, 0x77};
-       unsigned char bd_addr[ETH_ALEN] = {0x08, 0x00, 0x22, 0x33, 0x44, 0x55};
+       unsigned char gd_addr[ETH_ALEN] = {0xf0, 0x01, 0x44, 0x55, 0x66, 0x77};
+       unsigned char bd_addr[ETH_ALEN] = {0xf0, 0xff, 0xff, 0xff, 0xff, 0xff};
        struct stmmac_packet_attrs attr = { };
-       int ret;
+       int ret, tries = 256;
 
        if (stmmac_filter_check(priv))
                return -EOPNOTSUPP;
+       if (netdev_uc_count(priv->dev) >= priv->hw->unicast_filter_entries)
+               return -EOPNOTSUPP;
+
+       while (--tries) {
+               /* We only need to check the bd_addr for collisions */
+               bd_addr[ETH_ALEN - 1] = tries;
+               if (stmmac_perfect_check(priv, bd_addr))
+                       break;
+       }
+
+       if (!tries)
+               return -EOPNOTSUPP;
 
        ret = dev_uc_add(priv->dev, gd_addr);
        if (ret)
@@ -553,39 +613,31 @@ cleanup:
        return ret;
 }
 
-static int stmmac_dummy_sync(struct net_device *netdev, const u8 *addr)
-{
-       return 0;
-}
-
-static void stmmac_test_set_rx_mode(struct net_device *netdev)
-{
-       /* As we are in test mode of ethtool we already own the rtnl lock
-        * so no address will change from user. We can just call the
-        * ndo_set_rx_mode() callback directly */
-       if (netdev->netdev_ops->ndo_set_rx_mode)
-               netdev->netdev_ops->ndo_set_rx_mode(netdev);
-}
-
 static int stmmac_test_mcfilt(struct stmmac_priv *priv)
 {
-       unsigned char uc_addr[ETH_ALEN] = {0x00, 0x01, 0x44, 0x55, 0x66, 0x77};
-       unsigned char mc_addr[ETH_ALEN] = {0x01, 0x01, 0x44, 0x55, 0x66, 0x77};
+       unsigned char uc_addr[ETH_ALEN] = {0xf0, 0xff, 0xff, 0xff, 0xff, 0xff};
+       unsigned char mc_addr[ETH_ALEN] = {0xf1, 0xff, 0xff, 0xff, 0xff, 0xff};
        struct stmmac_packet_attrs attr = { };
-       int ret;
+       int ret, tries = 256;
 
        if (stmmac_filter_check(priv))
                return -EOPNOTSUPP;
-       if (!priv->hw->multicast_filter_bins)
+       if (netdev_uc_count(priv->dev) >= priv->hw->unicast_filter_entries)
                return -EOPNOTSUPP;
 
-       /* Remove all MC addresses */
-       __dev_mc_unsync(priv->dev, NULL);
-       stmmac_test_set_rx_mode(priv->dev);
+       while (--tries) {
+               /* We only need to check the mc_addr for collisions */
+               mc_addr[ETH_ALEN - 1] = tries;
+               if (stmmac_hash_check(priv, mc_addr))
+                       break;
+       }
+
+       if (!tries)
+               return -EOPNOTSUPP;
 
        ret = dev_uc_add(priv->dev, uc_addr);
        if (ret)
-               goto cleanup;
+               return ret;
 
        attr.dst = uc_addr;
 
@@ -602,30 +654,34 @@ static int stmmac_test_mcfilt(struct stmmac_priv *priv)
 
 cleanup:
        dev_uc_del(priv->dev, uc_addr);
-       __dev_mc_sync(priv->dev, stmmac_dummy_sync, NULL);
-       stmmac_test_set_rx_mode(priv->dev);
        return ret;
 }
 
 static int stmmac_test_ucfilt(struct stmmac_priv *priv)
 {
-       unsigned char uc_addr[ETH_ALEN] = {0x00, 0x01, 0x44, 0x55, 0x66, 0x77};
-       unsigned char mc_addr[ETH_ALEN] = {0x01, 0x01, 0x44, 0x55, 0x66, 0x77};
+       unsigned char uc_addr[ETH_ALEN] = {0xf0, 0xff, 0xff, 0xff, 0xff, 0xff};
+       unsigned char mc_addr[ETH_ALEN] = {0xf1, 0xff, 0xff, 0xff, 0xff, 0xff};
        struct stmmac_packet_attrs attr = { };
-       int ret;
+       int ret, tries = 256;
 
        if (stmmac_filter_check(priv))
                return -EOPNOTSUPP;
-       if (!priv->hw->multicast_filter_bins)
+       if (netdev_mc_count(priv->dev) >= priv->hw->multicast_filter_bins)
                return -EOPNOTSUPP;
 
-       /* Remove all UC addresses */
-       __dev_uc_unsync(priv->dev, NULL);
-       stmmac_test_set_rx_mode(priv->dev);
+       while (--tries) {
+               /* We only need to check the uc_addr for collisions */
+               uc_addr[ETH_ALEN - 1] = tries;
+               if (stmmac_perfect_check(priv, uc_addr))
+                       break;
+       }
+
+       if (!tries)
+               return -EOPNOTSUPP;
 
        ret = dev_mc_add(priv->dev, mc_addr);
        if (ret)
-               goto cleanup;
+               return ret;
 
        attr.dst = mc_addr;
 
@@ -642,8 +698,6 @@ static int stmmac_test_ucfilt(struct stmmac_priv *priv)
 
 cleanup:
        dev_mc_del(priv->dev, mc_addr);
-       __dev_uc_sync(priv->dev, stmmac_dummy_sync, NULL);
-       stmmac_test_set_rx_mode(priv->dev);
        return ret;
 }
 
index bbbc1dcb6ab5ca169cca257dcabf8705e08b5af0..b517c1af9de052d6d5fcc2d8b249d8544d5b49b9 100644 (file)
@@ -1237,8 +1237,17 @@ static int fjes_probe(struct platform_device *plat_dev)
        adapter->open_guard = false;
 
        adapter->txrx_wq = alloc_workqueue(DRV_NAME "/txrx", WQ_MEM_RECLAIM, 0);
+       if (unlikely(!adapter->txrx_wq)) {
+               err = -ENOMEM;
+               goto err_free_netdev;
+       }
+
        adapter->control_wq = alloc_workqueue(DRV_NAME "/control",
                                              WQ_MEM_RECLAIM, 0);
+       if (unlikely(!adapter->control_wq)) {
+               err = -ENOMEM;
+               goto err_free_txrx_wq;
+       }
 
        INIT_WORK(&adapter->tx_stall_task, fjes_tx_stall_task);
        INIT_WORK(&adapter->raise_intr_rxdata_task,
@@ -1255,7 +1264,7 @@ static int fjes_probe(struct platform_device *plat_dev)
        hw->hw_res.irq = platform_get_irq(plat_dev, 0);
        err = fjes_hw_init(&adapter->hw);
        if (err)
-               goto err_free_netdev;
+               goto err_free_control_wq;
 
        /* setup MAC address (02:00:00:00:00:[epid])*/
        netdev->dev_addr[0] = 2;
@@ -1277,6 +1286,10 @@ static int fjes_probe(struct platform_device *plat_dev)
 
 err_hw_exit:
        fjes_hw_exit(&adapter->hw);
+err_free_control_wq:
+       destroy_workqueue(adapter->control_wq);
+err_free_txrx_wq:
+       destroy_workqueue(adapter->txrx_wq);
 err_free_netdev:
        free_netdev(netdev);
 err_out:
index fbec711ff514af3da11fa9473fe2ef0c1732ba5c..fbea6f232819e905f0fedd832127f4f9ab7a4aba 100644 (file)
@@ -107,27 +107,6 @@ struct bpqdev {
 
 static LIST_HEAD(bpq_devices);
 
-/*
- * bpqether network devices are paired with ethernet devices below them, so
- * form a special "super class" of normal ethernet devices; split their locks
- * off into a separate class since they always nest.
- */
-static struct lock_class_key bpq_netdev_xmit_lock_key;
-static struct lock_class_key bpq_netdev_addr_lock_key;
-
-static void bpq_set_lockdep_class_one(struct net_device *dev,
-                                     struct netdev_queue *txq,
-                                     void *_unused)
-{
-       lockdep_set_class(&txq->_xmit_lock, &bpq_netdev_xmit_lock_key);
-}
-
-static void bpq_set_lockdep_class(struct net_device *dev)
-{
-       lockdep_set_class(&dev->addr_list_lock, &bpq_netdev_addr_lock_key);
-       netdev_for_each_tx_queue(dev, bpq_set_lockdep_class_one, NULL);
-}
-
 /* ------------------------------------------------------------------------ */
 
 
@@ -498,7 +477,6 @@ static int bpq_new_device(struct net_device *edev)
        err = register_netdevice(ndev);
        if (err)
                goto error;
-       bpq_set_lockdep_class(ndev);
 
        /* List protected by RTNL */
        list_add_rcu(&bpq->bpq_list, &bpq_devices);
index 39dddcd8b3cb0129d25c98400cca6692fa8b790c..963509add611ffc1de2f2ebbbfe13f9f58cb5d08 100644 (file)
@@ -982,7 +982,7 @@ static int netvsc_attach(struct net_device *ndev,
        if (netif_running(ndev)) {
                ret = rndis_filter_open(nvdev);
                if (ret)
-                       return ret;
+                       goto err;
 
                rdev = nvdev->extension;
                if (!rdev->link_state)
@@ -990,6 +990,13 @@ static int netvsc_attach(struct net_device *ndev,
        }
 
        return 0;
+
+err:
+       netif_device_detach(ndev);
+
+       rndis_filter_device_remove(hdev, nvdev);
+
+       return ret;
 }
 
 static int netvsc_set_channels(struct net_device *net,
@@ -1807,8 +1814,10 @@ static int netvsc_set_features(struct net_device *ndev,
 
        ret = rndis_filter_set_offload_params(ndev, nvdev, &offloads);
 
-       if (ret)
+       if (ret) {
                features ^= NETIF_F_LRO;
+               ndev->features = features;
+       }
 
 syncvf:
        if (!vf_netdev)
@@ -2335,8 +2344,6 @@ static int netvsc_probe(struct hv_device *dev,
                NETIF_F_HW_VLAN_CTAG_RX;
        net->vlan_features = net->features;
 
-       netdev_lockdep_set_classes(net);
-
        /* MTU range: 68 - 1500 or 65521 */
        net->min_mtu = NETVSC_MTU_MIN;
        if (nvdev->nvsp_version >= NVSP_PROTOCOL_VERSION_2)
index 887bbba4631e7ffecd2d5158b0cc91644ba7ad8c..ba3dfac1d90433fc20650ba644990f7a339d3949 100644 (file)
@@ -131,8 +131,6 @@ static int ipvlan_init(struct net_device *dev)
        dev->gso_max_segs = phy_dev->gso_max_segs;
        dev->hard_header_len = phy_dev->hard_header_len;
 
-       netdev_lockdep_set_classes(dev);
-
        ipvlan->pcpu_stats = netdev_alloc_pcpu_stats(struct ipvl_pcpu_stats);
        if (!ipvlan->pcpu_stats)
                return -ENOMEM;
index cb7637364b40d85c9595da833873be1e99db3f7c..afd8b2a082454b57ccf51183e028e552fff1c91f 100644 (file)
@@ -267,7 +267,6 @@ struct macsec_dev {
        struct pcpu_secy_stats __percpu *stats;
        struct list_head secys;
        struct gro_cells gro_cells;
-       unsigned int nest_level;
 };
 
 /**
@@ -2750,7 +2749,6 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,
 
 #define MACSEC_FEATURES \
        (NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST)
-static struct lock_class_key macsec_netdev_addr_lock_key;
 
 static int macsec_dev_init(struct net_device *dev)
 {
@@ -2958,11 +2956,6 @@ static int macsec_get_iflink(const struct net_device *dev)
        return macsec_priv(dev)->real_dev->ifindex;
 }
 
-static int macsec_get_nest_level(struct net_device *dev)
-{
-       return macsec_priv(dev)->nest_level;
-}
-
 static const struct net_device_ops macsec_netdev_ops = {
        .ndo_init               = macsec_dev_init,
        .ndo_uninit             = macsec_dev_uninit,
@@ -2976,7 +2969,6 @@ static const struct net_device_ops macsec_netdev_ops = {
        .ndo_start_xmit         = macsec_start_xmit,
        .ndo_get_stats64        = macsec_get_stats64,
        .ndo_get_iflink         = macsec_get_iflink,
-       .ndo_get_lock_subclass  = macsec_get_nest_level,
 };
 
 static const struct device_type macsec_type = {
@@ -3001,12 +2993,10 @@ static const struct nla_policy macsec_rtnl_policy[IFLA_MACSEC_MAX + 1] = {
 static void macsec_free_netdev(struct net_device *dev)
 {
        struct macsec_dev *macsec = macsec_priv(dev);
-       struct net_device *real_dev = macsec->real_dev;
 
        free_percpu(macsec->stats);
        free_percpu(macsec->secy.tx_sc.stats);
 
-       dev_put(real_dev);
 }
 
 static void macsec_setup(struct net_device *dev)
@@ -3261,14 +3251,6 @@ static int macsec_newlink(struct net *net, struct net_device *dev,
        if (err < 0)
                return err;
 
-       dev_hold(real_dev);
-
-       macsec->nest_level = dev_get_nest_level(real_dev) + 1;
-       netdev_lockdep_set_classes(dev);
-       lockdep_set_class_and_subclass(&dev->addr_list_lock,
-                                      &macsec_netdev_addr_lock_key,
-                                      macsec_get_nest_level(dev));
-
        err = netdev_upper_dev_link(real_dev, dev, extack);
        if (err < 0)
                goto unregister;
index 940192c057b6bdef4e7a0b7d6b7fe5ff2f4f78fa..34fc59bd1e20be52a6ea186a4c24ea94e4eb3882 100644 (file)
@@ -852,8 +852,6 @@ static int macvlan_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
  * "super class" of normal network devices; split their locks off into a
  * separate class since they always nest.
  */
-static struct lock_class_key macvlan_netdev_addr_lock_key;
-
 #define ALWAYS_ON_OFFLOADS \
        (NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE | \
         NETIF_F_GSO_ROBUST | NETIF_F_GSO_ENCAP_ALL)
@@ -869,19 +867,6 @@ static struct lock_class_key macvlan_netdev_addr_lock_key;
 #define MACVLAN_STATE_MASK \
        ((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT))
 
-static int macvlan_get_nest_level(struct net_device *dev)
-{
-       return ((struct macvlan_dev *)netdev_priv(dev))->nest_level;
-}
-
-static void macvlan_set_lockdep_class(struct net_device *dev)
-{
-       netdev_lockdep_set_classes(dev);
-       lockdep_set_class_and_subclass(&dev->addr_list_lock,
-                                      &macvlan_netdev_addr_lock_key,
-                                      macvlan_get_nest_level(dev));
-}
-
 static int macvlan_init(struct net_device *dev)
 {
        struct macvlan_dev *vlan = netdev_priv(dev);
@@ -900,8 +885,6 @@ static int macvlan_init(struct net_device *dev)
        dev->gso_max_segs       = lowerdev->gso_max_segs;
        dev->hard_header_len    = lowerdev->hard_header_len;
 
-       macvlan_set_lockdep_class(dev);
-
        vlan->pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats);
        if (!vlan->pcpu_stats)
                return -ENOMEM;
@@ -1161,7 +1144,6 @@ static const struct net_device_ops macvlan_netdev_ops = {
        .ndo_fdb_add            = macvlan_fdb_add,
        .ndo_fdb_del            = macvlan_fdb_del,
        .ndo_fdb_dump           = ndo_dflt_fdb_dump,
-       .ndo_get_lock_subclass  = macvlan_get_nest_level,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = macvlan_dev_poll_controller,
        .ndo_netpoll_setup      = macvlan_dev_netpoll_setup,
@@ -1445,7 +1427,6 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
        vlan->dev      = dev;
        vlan->port     = port;
        vlan->set_features = MACVLAN_FEATURES;
-       vlan->nest_level = dev_get_nest_level(lowerdev) + 1;
 
        vlan->mode     = MACVLAN_MODE_VEPA;
        if (data && data[IFLA_MACVLAN_MODE])
index 56576d4f34a5e0d9f28734a1ab0c47be2ddd8fb2..54ca6681ba3182fa758f3eb1a6c768726ec92cb7 100644 (file)
@@ -806,9 +806,11 @@ static void nsim_dev_port_del_all(struct nsim_dev *nsim_dev)
 {
        struct nsim_dev_port *nsim_dev_port, *tmp;
 
+       mutex_lock(&nsim_dev->port_list_lock);
        list_for_each_entry_safe(nsim_dev_port, tmp,
                                 &nsim_dev->port_list, list)
                __nsim_dev_port_del(nsim_dev_port);
+       mutex_unlock(&nsim_dev->port_list_lock);
 }
 
 int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev)
@@ -822,14 +824,17 @@ int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev)
                return PTR_ERR(nsim_dev);
        dev_set_drvdata(&nsim_bus_dev->dev, nsim_dev);
 
+       mutex_lock(&nsim_dev->port_list_lock);
        for (i = 0; i < nsim_bus_dev->port_count; i++) {
                err = __nsim_dev_port_add(nsim_dev, i);
                if (err)
                        goto err_port_del_all;
        }
+       mutex_unlock(&nsim_dev->port_list_lock);
        return 0;
 
 err_port_del_all:
+       mutex_unlock(&nsim_dev->port_list_lock);
        nsim_dev_port_del_all(nsim_dev);
        nsim_dev_destroy(nsim_dev);
        return err;
index 20e2ebe458f26354968eca866c983f87fb3ff223..a578f7ebf715e69680b23e35c1aec90d33f200f4 100644 (file)
@@ -87,8 +87,24 @@ struct phylink {
        phylink_printk(KERN_WARNING, pl, fmt, ##__VA_ARGS__)
 #define phylink_info(pl, fmt, ...) \
        phylink_printk(KERN_INFO, pl, fmt, ##__VA_ARGS__)
+#if defined(CONFIG_DYNAMIC_DEBUG)
 #define phylink_dbg(pl, fmt, ...) \
+do {                                                                   \
+       if ((pl)->config->type == PHYLINK_NETDEV)                       \
+               netdev_dbg((pl)->netdev, fmt, ##__VA_ARGS__);           \
+       else if ((pl)->config->type == PHYLINK_DEV)                     \
+               dev_dbg((pl)->dev, fmt, ##__VA_ARGS__);                 \
+} while (0)
+#elif defined(DEBUG)
+#define phylink_dbg(pl, fmt, ...)                                      \
        phylink_printk(KERN_DEBUG, pl, fmt, ##__VA_ARGS__)
+#else
+#define phylink_dbg(pl, fmt, ...)                                      \
+({                                                                     \
+       if (0)                                                          \
+               phylink_printk(KERN_DEBUG, pl, fmt, ##__VA_ARGS__);     \
+})
+#endif
 
 /**
  * phylink_set_port_modes() - set the port type modes in the ethtool mask
index dc3d92d340c4d7a019c53706c96b0513cee13356..b732982507939563d08a49f7c6ec22d86f1b0dcf 100644 (file)
@@ -327,6 +327,7 @@ static struct phy_driver smsc_phy_driver[] = {
        .name           = "SMSC LAN8740",
 
        /* PHY_BASIC_FEATURES */
+       .flags          = PHY_RST_AFTER_CLK_EN,
 
        .probe          = smsc_phy_probe,
 
index 9a1b006904a7dfa3ec5aa98c7cfd6b9a6d9c5a34..61824bbb55887232ce61c0d0b5f5bc304274ed3e 100644 (file)
@@ -1324,8 +1324,6 @@ static int ppp_dev_init(struct net_device *dev)
 {
        struct ppp *ppp;
 
-       netdev_lockdep_set_classes(dev);
-
        ppp = netdev_priv(dev);
        /* Let the netdevice take a reference on the ppp file. This ensures
         * that ppp_destroy_interface() won't run before the device gets
index e8089def5a4671bad10efbde7b00297e4c37df69..8156b33ee3e7919188127c9ed7e732d89501eb66 100644 (file)
@@ -1615,7 +1615,6 @@ static int team_init(struct net_device *dev)
        int err;
 
        team->dev = dev;
-       mutex_init(&team->lock);
        team_set_no_mode(team);
 
        team->pcpu_stats = netdev_alloc_pcpu_stats(struct team_pcpu_stats);
@@ -1642,7 +1641,8 @@ static int team_init(struct net_device *dev)
                goto err_options_register;
        netif_carrier_off(dev);
 
-       netdev_lockdep_set_classes(dev);
+       lockdep_register_key(&team->team_lock_key);
+       __mutex_init(&team->lock, "team->team_lock_key", &team->team_lock_key);
 
        return 0;
 
@@ -1673,6 +1673,7 @@ static void team_uninit(struct net_device *dev)
        team_queue_override_fini(team);
        mutex_unlock(&team->lock);
        netdev_change_features(dev);
+       lockdep_unregister_key(&team->team_lock_key);
 }
 
 static void team_destructor(struct net_device *dev)
@@ -1976,8 +1977,15 @@ static int team_del_slave(struct net_device *dev, struct net_device *port_dev)
        err = team_port_del(team, port_dev);
        mutex_unlock(&team->lock);
 
-       if (!err)
-               netdev_change_features(dev);
+       if (err)
+               return err;
+
+       if (netif_is_team_master(port_dev)) {
+               lockdep_unregister_key(&team->team_lock_key);
+               lockdep_register_key(&team->team_lock_key);
+               lockdep_set_class(&team->lock, &team->team_lock_key);
+       }
+       netdev_change_features(dev);
 
        return err;
 }
index 32f53de5b1fe7abff0eb2882240bcd295977af08..fe630438f67b040e28e81675cb54a44b863acb83 100644 (file)
@@ -787,6 +787,13 @@ static const struct usb_device_id  products[] = {
        .driver_info = 0,
 },
 
+/* ThinkPad USB-C Dock Gen 2 (based on Realtek RTL8153) */
+{
+       USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0xa387, USB_CLASS_COMM,
+                       USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+       .driver_info = 0,
+},
+
 /* NVIDIA Tegra USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */
 {
        USB_DEVICE_AND_INTERFACE_INFO(NVIDIA_VENDOR_ID, 0x09ff, USB_CLASS_COMM,
index 00cab3f43a4ca3f3e91f1471f5ab189e78d601dc..a245597a39024ed301bc9da5d5c787bf2d39c915 100644 (file)
@@ -578,8 +578,8 @@ static void cdc_ncm_set_dgram_size(struct usbnet *dev, int new_size)
        /* read current mtu value from device */
        err = usbnet_read_cmd(dev, USB_CDC_GET_MAX_DATAGRAM_SIZE,
                              USB_TYPE_CLASS | USB_DIR_IN | USB_RECIP_INTERFACE,
-                             0, iface_no, &max_datagram_size, 2);
-       if (err < 0) {
+                             0, iface_no, &max_datagram_size, sizeof(max_datagram_size));
+       if (err < sizeof(max_datagram_size)) {
                dev_dbg(&dev->intf->dev, "GET_MAX_DATAGRAM_SIZE failed\n");
                goto out;
        }
@@ -590,7 +590,7 @@ static void cdc_ncm_set_dgram_size(struct usbnet *dev, int new_size)
        max_datagram_size = cpu_to_le16(ctx->max_datagram_size);
        err = usbnet_write_cmd(dev, USB_CDC_SET_MAX_DATAGRAM_SIZE,
                               USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE,
-                              0, iface_no, &max_datagram_size, 2);
+                              0, iface_no, &max_datagram_size, sizeof(max_datagram_size));
        if (err < 0)
                dev_dbg(&dev->intf->dev, "SET_MAX_DATAGRAM_SIZE failed\n");
 
index 62948098191ff0462436b3b5fb677e629c45db70..f24a1b0b801f032aec74d910c9e13ecec3559f80 100644 (file)
@@ -1264,8 +1264,11 @@ static void lan78xx_status(struct lan78xx_net *dev, struct urb *urb)
                netif_dbg(dev, link, dev->net, "PHY INTR: 0x%08x\n", intdata);
                lan78xx_defer_kevent(dev, EVENT_LINK_RESET);
 
-               if (dev->domain_data.phyirq > 0)
+               if (dev->domain_data.phyirq > 0) {
+                       local_irq_disable();
                        generic_handle_irq(dev->domain_data.phyirq);
+                       local_irq_enable();
+               }
        } else
                netdev_warn(dev->net,
                            "unexpected interrupt: 0x%08x\n", intdata);
index 596428ec71df6742d8b150e6c7076a79f477af94..56d334b9ad450ab920d6ff3f4e48b596352568f5 100644 (file)
@@ -1362,6 +1362,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x413c, 0x81b6, 8)},    /* Dell Wireless 5811e */
        {QMI_FIXED_INTF(0x413c, 0x81b6, 10)},   /* Dell Wireless 5811e */
        {QMI_FIXED_INTF(0x413c, 0x81d7, 0)},    /* Dell Wireless 5821e */
+       {QMI_FIXED_INTF(0x413c, 0x81e0, 0)},    /* Dell Wireless 5821e with eSIM support*/
        {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)},    /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */
        {QMI_FIXED_INTF(0x03f0, 0x9d1d, 1)},    /* HP lt4120 Snapdragon X5 LTE */
        {QMI_FIXED_INTF(0x22de, 0x9061, 3)},    /* WeTelecom WPD-600N */
index cee9fef925cdc66052fb924d8ca96b89ddf2116a..d4a95b50bda6b22004472e74fcb7bd2faa4e55d9 100644 (file)
@@ -5755,6 +5755,7 @@ static const struct usb_device_id rtl8152_table[] = {
        {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x7205)},
        {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x720c)},
        {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x7214)},
+       {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0xa387)},
        {REALTEK_USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041)},
        {REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA,  0x09ff)},
        {REALTEK_USB_DEVICE(VENDOR_ID_TPLINK,  0x0601)},
index ee52bde058df4bf20e2d720802476d3635d91393..b8228f50bc9412e8d6037510b0cc46df55369202 100644 (file)
@@ -865,7 +865,6 @@ static int vrf_dev_init(struct net_device *dev)
 
        /* similarly, oper state is irrelevant; set to up to avoid confusion */
        dev->operstate = IF_OPER_UP;
-       netdev_lockdep_set_classes(dev);
        return 0;
 
 out_rth:
index 3d9bcc957f7da15b58aad5d9cb6acdb9803f4553..8869154fad8895194a3a101f93119890a930c542 100644 (file)
@@ -2487,9 +2487,11 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
                vni = tunnel_id_to_key32(info->key.tun_id);
                ifindex = 0;
                dst_cache = &info->dst_cache;
-               if (info->options_len &&
-                   info->key.tun_flags & TUNNEL_VXLAN_OPT)
+               if (info->key.tun_flags & TUNNEL_VXLAN_OPT) {
+                       if (info->options_len < sizeof(*md))
+                               goto drop;
                        md = ip_tunnel_info_opts(info);
+               }
                ttl = info->key.ttl;
                tos = info->key.tos;
                label = info->key.label;
@@ -3566,10 +3568,13 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev,
 {
        struct vxlan_net *vn = net_generic(net, vxlan_net_id);
        struct vxlan_dev *vxlan = netdev_priv(dev);
+       struct net_device *remote_dev = NULL;
        struct vxlan_fdb *f = NULL;
        bool unregister = false;
+       struct vxlan_rdst *dst;
        int err;
 
+       dst = &vxlan->default_dst;
        err = vxlan_dev_configure(net, dev, conf, false, extack);
        if (err)
                return err;
@@ -3577,14 +3582,14 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev,
        dev->ethtool_ops = &vxlan_ethtool_ops;
 
        /* create an fdb entry for a valid default destination */
-       if (!vxlan_addr_any(&vxlan->default_dst.remote_ip)) {
+       if (!vxlan_addr_any(&dst->remote_ip)) {
                err = vxlan_fdb_create(vxlan, all_zeros_mac,
-                                      &vxlan->default_dst.remote_ip,
+                                      &dst->remote_ip,
                                       NUD_REACHABLE | NUD_PERMANENT,
                                       vxlan->cfg.dst_port,
-                                      vxlan->default_dst.remote_vni,
-                                      vxlan->default_dst.remote_vni,
-                                      vxlan->default_dst.remote_ifindex,
+                                      dst->remote_vni,
+                                      dst->remote_vni,
+                                      dst->remote_ifindex,
                                       NTF_SELF, &f);
                if (err)
                        return err;
@@ -3595,26 +3600,41 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev,
                goto errout;
        unregister = true;
 
+       if (dst->remote_ifindex) {
+               remote_dev = __dev_get_by_index(net, dst->remote_ifindex);
+               if (!remote_dev)
+                       goto errout;
+
+               err = netdev_upper_dev_link(remote_dev, dev, extack);
+               if (err)
+                       goto errout;
+       }
+
        err = rtnl_configure_link(dev, NULL);
        if (err)
-               goto errout;
+               goto unlink;
 
        if (f) {
-               vxlan_fdb_insert(vxlan, all_zeros_mac,
-                                vxlan->default_dst.remote_vni, f);
+               vxlan_fdb_insert(vxlan, all_zeros_mac, dst->remote_vni, f);
 
                /* notify default fdb entry */
                err = vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f),
                                       RTM_NEWNEIGH, true, extack);
                if (err) {
                        vxlan_fdb_destroy(vxlan, f, false, false);
+                       if (remote_dev)
+                               netdev_upper_dev_unlink(remote_dev, dev);
                        goto unregister;
                }
        }
 
        list_add(&vxlan->next, &vn->vxlan_list);
+       if (remote_dev)
+               dst->remote_dev = remote_dev;
        return 0;
-
+unlink:
+       if (remote_dev)
+               netdev_upper_dev_unlink(remote_dev, dev);
 errout:
        /* unregister_netdevice() destroys the default FDB entry with deletion
         * notification. But the addition notification was not sent yet, so
@@ -3932,11 +3952,12 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
                            struct netlink_ext_ack *extack)
 {
        struct vxlan_dev *vxlan = netdev_priv(dev);
-       struct vxlan_rdst *dst = &vxlan->default_dst;
        struct net_device *lowerdev;
        struct vxlan_config conf;
+       struct vxlan_rdst *dst;
        int err;
 
+       dst = &vxlan->default_dst;
        err = vxlan_nl2conf(tb, data, dev, &conf, true, extack);
        if (err)
                return err;
@@ -3946,6 +3967,14 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
        if (err)
                return err;
 
+       if (dst->remote_dev == lowerdev)
+               lowerdev = NULL;
+
+       err = netdev_adjacent_change_prepare(dst->remote_dev, lowerdev, dev,
+                                            extack);
+       if (err)
+               return err;
+
        /* handle default dst entry */
        if (!vxlan_addr_equal(&conf.remote_ip, &dst->remote_ip)) {
                u32 hash_index = fdb_head_index(vxlan, all_zeros_mac, conf.vni);
@@ -3962,6 +3991,8 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
                                               NTF_SELF, true, extack);
                        if (err) {
                                spin_unlock_bh(&vxlan->hash_lock[hash_index]);
+                               netdev_adjacent_change_abort(dst->remote_dev,
+                                                            lowerdev, dev);
                                return err;
                        }
                }
@@ -3979,6 +4010,11 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
        if (conf.age_interval != vxlan->cfg.age_interval)
                mod_timer(&vxlan->age_timer, jiffies);
 
+       netdev_adjacent_change_commit(dst->remote_dev, lowerdev, dev);
+       if (lowerdev && lowerdev != dst->remote_dev) {
+               dst->remote_dev = lowerdev;
+               netdev_update_lockdep_key(lowerdev);
+       }
        vxlan_config_apply(dev, &conf, lowerdev, vxlan->net, true);
        return 0;
 }
@@ -3991,6 +4027,8 @@ static void vxlan_dellink(struct net_device *dev, struct list_head *head)
 
        list_del(&vxlan->next);
        unregister_netdevice_queue(dev, head);
+       if (vxlan->default_dst.remote_dev)
+               netdev_upper_dev_unlink(vxlan->default_dst.remote_dev, dev);
 }
 
 static size_t vxlan_get_size(const struct net_device *dev)
index 8efb493ceec2fc96cda43cb56cde5e6d19e91015..5c79f052cad20925c63e6c72adda3a97af3ee0fd 100644 (file)
@@ -127,12 +127,12 @@ int i2400m_op_rfkill_sw_toggle(struct wimax_dev *wimax_dev,
                        "%d\n", result);
        result = 0;
 error_cmd:
-       kfree(cmd);
        kfree_skb(ack_skb);
 error_msg_to_dev:
 error_alloc:
        d_fnend(4, dev, "(wimax_dev %p state %d) = %d\n",
                wimax_dev, state, result);
+       kfree(cmd);
        return result;
 }
 
index 39c64850cb6f04ca25ff305a5cb4b9fe94d9584b..c0750ced5ac2952f6dec3965abefca731530c4db 100644 (file)
@@ -520,7 +520,7 @@ struct iwl_scan_dwell {
 } __packed;
 
 /**
- * struct iwl_scan_config
+ * struct iwl_scan_config_v1
  * @flags:                     enum scan_config_flags
  * @tx_chains:                 valid_tx antenna - ANT_* definitions
  * @rx_chains:                 valid_rx antenna - ANT_* definitions
@@ -552,7 +552,7 @@ struct iwl_scan_config_v1 {
 #define SCAN_LB_LMAC_IDX 0
 #define SCAN_HB_LMAC_IDX 1
 
-struct iwl_scan_config {
+struct iwl_scan_config_v2 {
        __le32 flags;
        __le32 tx_chains;
        __le32 rx_chains;
@@ -564,6 +564,24 @@ struct iwl_scan_config {
        u8 bcast_sta_id;
        u8 channel_flags;
        u8 channel_array[];
+} __packed; /* SCAN_CONFIG_DB_CMD_API_S_2 */
+
+/**
+ * struct iwl_scan_config
+ * @enable_cam_mode: whether to enable CAM mode.
+ * @enable_promiscouos_mode: whether to enable promiscouos mode
+ * @bcast_sta_id: the index of the station in the fw
+ * @reserved: reserved
+ * @tx_chains: valid_tx antenna - ANT_* definitions
+ * @rx_chains: valid_rx antenna - ANT_* definitions
+ */
+struct iwl_scan_config {
+       u8 enable_cam_mode;
+       u8 enable_promiscouos_mode;
+       u8 bcast_sta_id;
+       u8 reserved;
+       __le32 tx_chains;
+       __le32 rx_chains;
 } __packed; /* SCAN_CONFIG_DB_CMD_API_S_3 */
 
 /**
index 423cc0cf8e78139146664fd19d30d2a37f8e635b..0d5bc4ce5c072d0f4402f2dbd376f970f5409df3 100644 (file)
@@ -288,6 +288,8 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t;
  *     STA_CONTEXT_DOT11AX_API_S
  * @IWL_UCODE_TLV_CAPA_SAR_TABLE_VER: This ucode supports different sar
  *     version tables.
+ * @IWL_UCODE_TLV_API_REDUCED_SCAN_CONFIG: This ucode supports v3 of
+ *  SCAN_CONFIG_DB_CMD_API_S.
  *
  * @NUM_IWL_UCODE_TLV_API: number of bits used
  */
@@ -321,6 +323,7 @@ enum iwl_ucode_tlv_api {
        IWL_UCODE_TLV_API_WOWLAN_TCP_SYN_WAKE   = (__force iwl_ucode_tlv_api_t)53,
        IWL_UCODE_TLV_API_FTM_RTT_ACCURACY      = (__force iwl_ucode_tlv_api_t)54,
        IWL_UCODE_TLV_API_SAR_TABLE_VER         = (__force iwl_ucode_tlv_api_t)55,
+       IWL_UCODE_TLV_API_REDUCED_SCAN_CONFIG   = (__force iwl_ucode_tlv_api_t)56,
        IWL_UCODE_TLV_API_ADWELL_HB_DEF_N_AP    = (__force iwl_ucode_tlv_api_t)57,
        IWL_UCODE_TLV_API_SCAN_EXT_CHAN_VER     = (__force iwl_ucode_tlv_api_t)58,
 
index cb4c5514a55605c2d6215396244ab8b3f5daa514..695bbaa86273dd025f7d9322221ef2c439a97342 100644 (file)
  *         Indicates MAC is entering a power-saving sleep power-down.
  *         Not a good time to access device-internal resources.
  */
+#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE                     (0x00000004)
 #define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP         (0x00000010)
 #define CSR_GP_CNTRL_REG_FLAG_XTAL_ON               (0x00000400)
 
index f47e0f97acf89d3c5d9bc483b7e2b75eefc4f8ec..23c25a7665f27087a58bd556de4c955e81e7cabd 100644 (file)
@@ -449,6 +449,11 @@ enum {
 #define PERSISTENCE_BIT                        BIT(12)
 #define PREG_WFPM_ACCESS               BIT(12)
 
+#define HPM_HIPM_GEN_CFG                       0xA03458
+#define HPM_HIPM_GEN_CFG_CR_PG_EN              BIT(0)
+#define HPM_HIPM_GEN_CFG_CR_SLP_EN             BIT(1)
+#define HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE       BIT(10)
+
 #define UREG_DOORBELL_TO_ISR6          0xA05C04
 #define UREG_DOORBELL_TO_ISR6_NMI_BIT  BIT(0)
 #define UREG_DOORBELL_TO_ISR6_SUSPEND  BIT(18)
index 843d00bf2bd55504d057075871968291f9897a3a..5ca50f39a023db3f5af56519ea9f135b74a204a5 100644 (file)
@@ -1405,6 +1405,12 @@ static inline bool iwl_mvm_is_scan_ext_chan_supported(struct iwl_mvm *mvm)
                          IWL_UCODE_TLV_API_SCAN_EXT_CHAN_VER);
 }
 
+static inline bool iwl_mvm_is_reduced_config_scan_supported(struct iwl_mvm *mvm)
+{
+       return fw_has_api(&mvm->fw->ucode_capa,
+                         IWL_UCODE_TLV_API_REDUCED_SCAN_CONFIG);
+}
+
 static inline bool iwl_mvm_has_new_rx_stats_api(struct iwl_mvm *mvm)
 {
        return fw_has_api(&mvm->fw->ucode_capa,
index f6b3045badbdec548b695c39e8744f6a1f3e9ced..fcafa22ec6ce222878a29496f6940347fe5620f4 100644 (file)
@@ -1137,11 +1137,11 @@ static void iwl_mvm_fill_scan_config_v1(struct iwl_mvm *mvm, void *config,
        iwl_mvm_fill_channels(mvm, cfg->channel_array, max_channels);
 }
 
-static void iwl_mvm_fill_scan_config(struct iwl_mvm *mvm, void *config,
-                                    u32 flags, u8 channel_flags,
-                                    u32 max_channels)
+static void iwl_mvm_fill_scan_config_v2(struct iwl_mvm *mvm, void *config,
+                                       u32 flags, u8 channel_flags,
+                                       u32 max_channels)
 {
-       struct iwl_scan_config *cfg = config;
+       struct iwl_scan_config_v2 *cfg = config;
 
        cfg->flags = cpu_to_le32(flags);
        cfg->tx_chains = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm));
@@ -1185,7 +1185,7 @@ static void iwl_mvm_fill_scan_config(struct iwl_mvm *mvm, void *config,
        iwl_mvm_fill_channels(mvm, cfg->channel_array, max_channels);
 }
 
-int iwl_mvm_config_scan(struct iwl_mvm *mvm)
+static int iwl_mvm_legacy_config_scan(struct iwl_mvm *mvm)
 {
        void *cfg;
        int ret, cmd_size;
@@ -1217,7 +1217,7 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
        }
 
        if (iwl_mvm_cdb_scan_api(mvm))
-               cmd_size = sizeof(struct iwl_scan_config);
+               cmd_size = sizeof(struct iwl_scan_config_v2);
        else
                cmd_size = sizeof(struct iwl_scan_config_v1);
        cmd_size += num_channels;
@@ -1254,8 +1254,8 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
                        flags |= (iwl_mvm_is_scan_fragmented(hb_type)) ?
                                 SCAN_CONFIG_FLAG_SET_LMAC2_FRAGMENTED :
                                 SCAN_CONFIG_FLAG_CLEAR_LMAC2_FRAGMENTED;
-               iwl_mvm_fill_scan_config(mvm, cfg, flags, channel_flags,
-                                        num_channels);
+               iwl_mvm_fill_scan_config_v2(mvm, cfg, flags, channel_flags,
+                                           num_channels);
        } else {
                iwl_mvm_fill_scan_config_v1(mvm, cfg, flags, channel_flags,
                                            num_channels);
@@ -1277,6 +1277,30 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
        return ret;
 }
 
+int iwl_mvm_config_scan(struct iwl_mvm *mvm)
+{
+       struct iwl_scan_config cfg;
+       struct iwl_host_cmd cmd = {
+               .id = iwl_cmd_id(SCAN_CFG_CMD, IWL_ALWAYS_LONG_GROUP, 0),
+               .len[0] = sizeof(cfg),
+               .data[0] = &cfg,
+               .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
+       };
+
+       if (!iwl_mvm_is_reduced_config_scan_supported(mvm))
+               return iwl_mvm_legacy_config_scan(mvm);
+
+       memset(&cfg, 0, sizeof(cfg));
+
+       cfg.bcast_sta_id = mvm->aux_sta.sta_id;
+       cfg.tx_chains = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm));
+       cfg.rx_chains = cpu_to_le32(iwl_mvm_scan_rx_ant(mvm));
+
+       IWL_DEBUG_SCAN(mvm, "Sending UMAC scan config\n");
+
+       return iwl_mvm_send_cmd(mvm, &cmd);
+}
+
 static int iwl_mvm_scan_uid_by_status(struct iwl_mvm *mvm, int status)
 {
        int i;
index 0bedba4c61f2ae898c7ddbb612d041e9c9fdd7dc..b3768d5d852ae367394630a9e4d72d03b28ab2a9 100644 (file)
@@ -1482,6 +1482,13 @@ static void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm,
                                            mvm_sta->sta_id, i);
                        txq_id = iwl_mvm_tvqm_enable_txq(mvm, mvm_sta->sta_id,
                                                         i, wdg);
+                       /*
+                        * on failures, just set it to IWL_MVM_INVALID_QUEUE
+                        * to try again later, we have no other good way of
+                        * failing here
+                        */
+                       if (txq_id < 0)
+                               txq_id = IWL_MVM_INVALID_QUEUE;
                        tid_data->txq_id = txq_id;
 
                        /*
@@ -1950,30 +1957,73 @@ void iwl_mvm_dealloc_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta)
        sta->sta_id = IWL_MVM_INVALID_STA;
 }
 
-static void iwl_mvm_enable_aux_snif_queue(struct iwl_mvm *mvm, u16 *queue,
+static void iwl_mvm_enable_aux_snif_queue(struct iwl_mvm *mvm, u16 queue,
                                          u8 sta_id, u8 fifo)
 {
        unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ?
                mvm->trans->trans_cfg->base_params->wd_timeout :
                IWL_WATCHDOG_DISABLED;
+       struct iwl_trans_txq_scd_cfg cfg = {
+               .fifo = fifo,
+               .sta_id = sta_id,
+               .tid = IWL_MAX_TID_COUNT,
+               .aggregate = false,
+               .frame_limit = IWL_FRAME_LIMIT,
+       };
+
+       WARN_ON(iwl_mvm_has_new_tx_api(mvm));
+
+       iwl_mvm_enable_txq(mvm, NULL, queue, 0, &cfg, wdg_timeout);
+}
+
+static int iwl_mvm_enable_aux_snif_queue_tvqm(struct iwl_mvm *mvm, u8 sta_id)
+{
+       unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ?
+               mvm->trans->trans_cfg->base_params->wd_timeout :
+               IWL_WATCHDOG_DISABLED;
+
+       WARN_ON(!iwl_mvm_has_new_tx_api(mvm));
+
+       return iwl_mvm_tvqm_enable_txq(mvm, sta_id, IWL_MAX_TID_COUNT,
+                                      wdg_timeout);
+}
 
+static int iwl_mvm_add_int_sta_with_queue(struct iwl_mvm *mvm, int macidx,
+                                         int maccolor,
+                                         struct iwl_mvm_int_sta *sta,
+                                         u16 *queue, int fifo)
+{
+       int ret;
+
+       /* Map queue to fifo - needs to happen before adding station */
+       if (!iwl_mvm_has_new_tx_api(mvm))
+               iwl_mvm_enable_aux_snif_queue(mvm, *queue, sta->sta_id, fifo);
+
+       ret = iwl_mvm_add_int_sta_common(mvm, sta, NULL, macidx, maccolor);
+       if (ret) {
+               if (!iwl_mvm_has_new_tx_api(mvm))
+                       iwl_mvm_disable_txq(mvm, NULL, *queue,
+                                           IWL_MAX_TID_COUNT, 0);
+               return ret;
+       }
+
+       /*
+        * For 22000 firmware and on we cannot add queue to a station unknown
+        * to firmware so enable queue here - after the station was added
+        */
        if (iwl_mvm_has_new_tx_api(mvm)) {
-               int tvqm_queue =
-                       iwl_mvm_tvqm_enable_txq(mvm, sta_id,
-                                               IWL_MAX_TID_COUNT,
-                                               wdg_timeout);
-               *queue = tvqm_queue;
-       } else {
-               struct iwl_trans_txq_scd_cfg cfg = {
-                       .fifo = fifo,
-                       .sta_id = sta_id,
-                       .tid = IWL_MAX_TID_COUNT,
-                       .aggregate = false,
-                       .frame_limit = IWL_FRAME_LIMIT,
-               };
+               int txq;
 
-               iwl_mvm_enable_txq(mvm, NULL, *queue, 0, &cfg, wdg_timeout);
+               txq = iwl_mvm_enable_aux_snif_queue_tvqm(mvm, sta->sta_id);
+               if (txq < 0) {
+                       iwl_mvm_rm_sta_common(mvm, sta->sta_id);
+                       return txq;
+               }
+
+               *queue = txq;
        }
+
+       return 0;
 }
 
 int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
@@ -1989,59 +2039,26 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
        if (ret)
                return ret;
 
-       /* Map Aux queue to fifo - needs to happen before adding Aux station */
-       if (!iwl_mvm_has_new_tx_api(mvm))
-               iwl_mvm_enable_aux_snif_queue(mvm, &mvm->aux_queue,
-                                             mvm->aux_sta.sta_id,
-                                             IWL_MVM_TX_FIFO_MCAST);
-
-       ret = iwl_mvm_add_int_sta_common(mvm, &mvm->aux_sta, NULL,
-                                        MAC_INDEX_AUX, 0);
+       ret = iwl_mvm_add_int_sta_with_queue(mvm, MAC_INDEX_AUX, 0,
+                                            &mvm->aux_sta, &mvm->aux_queue,
+                                            IWL_MVM_TX_FIFO_MCAST);
        if (ret) {
                iwl_mvm_dealloc_int_sta(mvm, &mvm->aux_sta);
                return ret;
        }
 
-       /*
-        * For 22000 firmware and on we cannot add queue to a station unknown
-        * to firmware so enable queue here - after the station was added
-        */
-       if (iwl_mvm_has_new_tx_api(mvm))
-               iwl_mvm_enable_aux_snif_queue(mvm, &mvm->aux_queue,
-                                             mvm->aux_sta.sta_id,
-                                             IWL_MVM_TX_FIFO_MCAST);
-
        return 0;
 }
 
 int iwl_mvm_add_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 {
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-       int ret;
 
        lockdep_assert_held(&mvm->mutex);
 
-       /* Map snif queue to fifo - must happen before adding snif station */
-       if (!iwl_mvm_has_new_tx_api(mvm))
-               iwl_mvm_enable_aux_snif_queue(mvm, &mvm->snif_queue,
-                                             mvm->snif_sta.sta_id,
+       return iwl_mvm_add_int_sta_with_queue(mvm, mvmvif->id, mvmvif->color,
+                                             &mvm->snif_sta, &mvm->snif_queue,
                                              IWL_MVM_TX_FIFO_BE);
-
-       ret = iwl_mvm_add_int_sta_common(mvm, &mvm->snif_sta, vif->addr,
-                                        mvmvif->id, 0);
-       if (ret)
-               return ret;
-
-       /*
-        * For 22000 firmware and on we cannot add queue to a station unknown
-        * to firmware so enable queue here - after the station was added
-        */
-       if (iwl_mvm_has_new_tx_api(mvm))
-               iwl_mvm_enable_aux_snif_queue(mvm, &mvm->snif_queue,
-                                             mvm->snif_sta.sta_id,
-                                             IWL_MVM_TX_FIFO_BE);
-
-       return 0;
 }
 
 int iwl_mvm_rm_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
@@ -2133,6 +2150,10 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
                queue = iwl_mvm_tvqm_enable_txq(mvm, bsta->sta_id,
                                                IWL_MAX_TID_COUNT,
                                                wdg_timeout);
+               if (queue < 0) {
+                       iwl_mvm_rm_sta_common(mvm, bsta->sta_id);
+                       return queue;
+               }
 
                if (vif->type == NL80211_IFTYPE_AP ||
                    vif->type == NL80211_IFTYPE_ADHOC)
@@ -2307,10 +2328,8 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
        }
        ret = iwl_mvm_add_int_sta_common(mvm, msta, maddr,
                                         mvmvif->id, mvmvif->color);
-       if (ret) {
-               iwl_mvm_dealloc_int_sta(mvm, msta);
-               return ret;
-       }
+       if (ret)
+               goto err;
 
        /*
         * Enable cab queue after the ADD_STA command is sent.
@@ -2323,6 +2342,10 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
                int queue = iwl_mvm_tvqm_enable_txq(mvm, msta->sta_id,
                                                    0,
                                                    timeout);
+               if (queue < 0) {
+                       ret = queue;
+                       goto err;
+               }
                mvmvif->cab_queue = queue;
        } else if (!fw_has_api(&mvm->fw->ucode_capa,
                               IWL_UCODE_TLV_API_STA_TYPE))
@@ -2330,6 +2353,9 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
                                   timeout);
 
        return 0;
+err:
+       iwl_mvm_dealloc_int_sta(mvm, msta);
+       return ret;
 }
 
 static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id,
index 6f4bb7ce71a53487022e37a1a88379256144f00d..040cec17d3ad68c4e2d38ee1af19f686c1bbc90e 100644 (file)
@@ -573,20 +573,20 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
        {IWL_PCI_DEVICE(0x2526, 0x0034, iwl9560_2ac_cfg)},
        {IWL_PCI_DEVICE(0x2526, 0x0038, iwl9560_2ac_160_cfg)},
        {IWL_PCI_DEVICE(0x2526, 0x003C, iwl9560_2ac_160_cfg)},
-       {IWL_PCI_DEVICE(0x2526, 0x0060, iwl9460_2ac_cfg)},
-       {IWL_PCI_DEVICE(0x2526, 0x0064, iwl9460_2ac_cfg)},
-       {IWL_PCI_DEVICE(0x2526, 0x00A0, iwl9460_2ac_cfg)},
-       {IWL_PCI_DEVICE(0x2526, 0x00A4, iwl9460_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x2526, 0x0060, iwl9461_2ac_cfg_soc)},
+       {IWL_PCI_DEVICE(0x2526, 0x0064, iwl9461_2ac_cfg_soc)},
+       {IWL_PCI_DEVICE(0x2526, 0x00A0, iwl9462_2ac_cfg_soc)},
+       {IWL_PCI_DEVICE(0x2526, 0x00A4, iwl9462_2ac_cfg_soc)},
        {IWL_PCI_DEVICE(0x2526, 0x0210, iwl9260_2ac_cfg)},
        {IWL_PCI_DEVICE(0x2526, 0x0214, iwl9260_2ac_cfg)},
        {IWL_PCI_DEVICE(0x2526, 0x0230, iwl9560_2ac_cfg)},
        {IWL_PCI_DEVICE(0x2526, 0x0234, iwl9560_2ac_cfg)},
        {IWL_PCI_DEVICE(0x2526, 0x0238, iwl9560_2ac_cfg)},
        {IWL_PCI_DEVICE(0x2526, 0x023C, iwl9560_2ac_cfg)},
-       {IWL_PCI_DEVICE(0x2526, 0x0260, iwl9460_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x2526, 0x0260, iwl9461_2ac_cfg_soc)},
        {IWL_PCI_DEVICE(0x2526, 0x0264, iwl9461_2ac_cfg_soc)},
-       {IWL_PCI_DEVICE(0x2526, 0x02A0, iwl9460_2ac_cfg)},
-       {IWL_PCI_DEVICE(0x2526, 0x02A4, iwl9460_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x2526, 0x02A0, iwl9462_2ac_cfg_soc)},
+       {IWL_PCI_DEVICE(0x2526, 0x02A4, iwl9462_2ac_cfg_soc)},
        {IWL_PCI_DEVICE(0x2526, 0x1010, iwl9260_2ac_cfg)},
        {IWL_PCI_DEVICE(0x2526, 0x1030, iwl9560_2ac_cfg)},
        {IWL_PCI_DEVICE(0x2526, 0x1210, iwl9260_2ac_cfg)},
@@ -603,7 +603,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
        {IWL_PCI_DEVICE(0x2526, 0x401C, iwl9260_2ac_160_cfg)},
        {IWL_PCI_DEVICE(0x2526, 0x4030, iwl9560_2ac_160_cfg)},
        {IWL_PCI_DEVICE(0x2526, 0x4034, iwl9560_2ac_160_cfg_soc)},
-       {IWL_PCI_DEVICE(0x2526, 0x40A4, iwl9460_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x2526, 0x40A4, iwl9462_2ac_cfg_soc)},
        {IWL_PCI_DEVICE(0x2526, 0x4234, iwl9560_2ac_cfg_soc)},
        {IWL_PCI_DEVICE(0x2526, 0x42A4, iwl9462_2ac_cfg_soc)},
        {IWL_PCI_DEVICE(0x2526, 0x6010, iwl9260_2ac_160_cfg)},
@@ -618,60 +618,61 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
        {IWL_PCI_DEVICE(0x271B, 0x0210, iwl9160_2ac_cfg)},
        {IWL_PCI_DEVICE(0x271B, 0x0214, iwl9260_2ac_cfg)},
        {IWL_PCI_DEVICE(0x271C, 0x0214, iwl9260_2ac_cfg)},
-       {IWL_PCI_DEVICE(0x2720, 0x0034, iwl9560_2ac_160_cfg)},
-       {IWL_PCI_DEVICE(0x2720, 0x0038, iwl9560_2ac_160_cfg)},
-       {IWL_PCI_DEVICE(0x2720, 0x003C, iwl9560_2ac_160_cfg)},
-       {IWL_PCI_DEVICE(0x2720, 0x0060, iwl9461_2ac_cfg_soc)},
-       {IWL_PCI_DEVICE(0x2720, 0x0064, iwl9461_2ac_cfg_soc)},
-       {IWL_PCI_DEVICE(0x2720, 0x00A0, iwl9462_2ac_cfg_soc)},
-       {IWL_PCI_DEVICE(0x2720, 0x00A4, iwl9462_2ac_cfg_soc)},
-       {IWL_PCI_DEVICE(0x2720, 0x0230, iwl9560_2ac_cfg)},
-       {IWL_PCI_DEVICE(0x2720, 0x0234, iwl9560_2ac_cfg)},
-       {IWL_PCI_DEVICE(0x2720, 0x0238, iwl9560_2ac_cfg)},
-       {IWL_PCI_DEVICE(0x2720, 0x023C, iwl9560_2ac_cfg)},
-       {IWL_PCI_DEVICE(0x2720, 0x0260, iwl9461_2ac_cfg_soc)},
-       {IWL_PCI_DEVICE(0x2720, 0x0264, iwl9461_2ac_cfg_soc)},
-       {IWL_PCI_DEVICE(0x2720, 0x02A0, iwl9462_2ac_cfg_soc)},
-       {IWL_PCI_DEVICE(0x2720, 0x02A4, iwl9462_2ac_cfg_soc)},
-       {IWL_PCI_DEVICE(0x2720, 0x1010, iwl9260_2ac_cfg)},
-       {IWL_PCI_DEVICE(0x2720, 0x1030, iwl9560_2ac_cfg_soc)},
-       {IWL_PCI_DEVICE(0x2720, 0x1210, iwl9260_2ac_cfg)},
-       {IWL_PCI_DEVICE(0x2720, 0x1551, iwl9560_killer_s_2ac_cfg_soc)},
-       {IWL_PCI_DEVICE(0x2720, 0x1552, iwl9560_killer_2ac_cfg_soc)},
-       {IWL_PCI_DEVICE(0x2720, 0x2030, iwl9560_2ac_160_cfg_soc)},
-       {IWL_PCI_DEVICE(0x2720, 0x2034, iwl9560_2ac_160_cfg_soc)},
-       {IWL_PCI_DEVICE(0x2720, 0x4030, iwl9560_2ac_160_cfg)},
-       {IWL_PCI_DEVICE(0x2720, 0x4034, iwl9560_2ac_160_cfg_soc)},
-       {IWL_PCI_DEVICE(0x2720, 0x40A4, iwl9462_2ac_cfg_soc)},
-       {IWL_PCI_DEVICE(0x2720, 0x4234, iwl9560_2ac_cfg_soc)},
-       {IWL_PCI_DEVICE(0x2720, 0x42A4, iwl9462_2ac_cfg_soc)},
-
-       {IWL_PCI_DEVICE(0x30DC, 0x0030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)},
-       {IWL_PCI_DEVICE(0x30DC, 0x0034, iwl9560_2ac_cfg_qu_b0_jf_b0)},
-       {IWL_PCI_DEVICE(0x30DC, 0x0038, iwl9560_2ac_160_cfg_qu_b0_jf_b0)},
-       {IWL_PCI_DEVICE(0x30DC, 0x003C, iwl9560_2ac_160_cfg_qu_b0_jf_b0)},
-       {IWL_PCI_DEVICE(0x30DC, 0x0060, iwl9461_2ac_cfg_qu_b0_jf_b0)},
-       {IWL_PCI_DEVICE(0x30DC, 0x0064, iwl9461_2ac_cfg_qu_b0_jf_b0)},
-       {IWL_PCI_DEVICE(0x30DC, 0x00A0, iwl9462_2ac_cfg_qu_b0_jf_b0)},
-       {IWL_PCI_DEVICE(0x30DC, 0x00A4, iwl9462_2ac_cfg_qu_b0_jf_b0)},
-       {IWL_PCI_DEVICE(0x30DC, 0x0230, iwl9560_2ac_cfg_qu_b0_jf_b0)},
-       {IWL_PCI_DEVICE(0x30DC, 0x0234, iwl9560_2ac_cfg_qu_b0_jf_b0)},
-       {IWL_PCI_DEVICE(0x30DC, 0x0238, iwl9560_2ac_cfg_qu_b0_jf_b0)},
-       {IWL_PCI_DEVICE(0x30DC, 0x023C, iwl9560_2ac_cfg_qu_b0_jf_b0)},
-       {IWL_PCI_DEVICE(0x30DC, 0x0260, iwl9461_2ac_cfg_qu_b0_jf_b0)},
-       {IWL_PCI_DEVICE(0x30DC, 0x0264, iwl9461_2ac_cfg_qu_b0_jf_b0)},
-       {IWL_PCI_DEVICE(0x30DC, 0x02A0, iwl9462_2ac_cfg_qu_b0_jf_b0)},
-       {IWL_PCI_DEVICE(0x30DC, 0x02A4, iwl9462_2ac_cfg_qu_b0_jf_b0)},
-       {IWL_PCI_DEVICE(0x30DC, 0x1030, iwl9560_2ac_cfg_qu_b0_jf_b0)},
-       {IWL_PCI_DEVICE(0x30DC, 0x1551, killer1550s_2ac_cfg_qu_b0_jf_b0)},
-       {IWL_PCI_DEVICE(0x30DC, 0x1552, killer1550i_2ac_cfg_qu_b0_jf_b0)},
-       {IWL_PCI_DEVICE(0x30DC, 0x2030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)},
-       {IWL_PCI_DEVICE(0x30DC, 0x2034, iwl9560_2ac_160_cfg_qu_b0_jf_b0)},
-       {IWL_PCI_DEVICE(0x30DC, 0x4030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)},
-       {IWL_PCI_DEVICE(0x30DC, 0x4034, iwl9560_2ac_160_cfg_qu_b0_jf_b0)},
-       {IWL_PCI_DEVICE(0x30DC, 0x40A4, iwl9462_2ac_cfg_qu_b0_jf_b0)},
-       {IWL_PCI_DEVICE(0x30DC, 0x4234, iwl9560_2ac_cfg_qu_b0_jf_b0)},
-       {IWL_PCI_DEVICE(0x30DC, 0x42A4, iwl9462_2ac_cfg_qu_b0_jf_b0)},
+
+       {IWL_PCI_DEVICE(0x2720, 0x0034, iwl9560_2ac_cfg_qu_b0_jf_b0)},
+       {IWL_PCI_DEVICE(0x2720, 0x0038, iwl9560_2ac_160_cfg_qu_b0_jf_b0)},
+       {IWL_PCI_DEVICE(0x2720, 0x003C, iwl9560_2ac_160_cfg_qu_b0_jf_b0)},
+       {IWL_PCI_DEVICE(0x2720, 0x0060, iwl9461_2ac_cfg_qu_b0_jf_b0)},
+       {IWL_PCI_DEVICE(0x2720, 0x0064, iwl9461_2ac_cfg_qu_b0_jf_b0)},
+       {IWL_PCI_DEVICE(0x2720, 0x00A0, iwl9462_2ac_cfg_qu_b0_jf_b0)},
+       {IWL_PCI_DEVICE(0x2720, 0x00A4, iwl9462_2ac_cfg_qu_b0_jf_b0)},
+       {IWL_PCI_DEVICE(0x2720, 0x0230, iwl9560_2ac_cfg_qu_b0_jf_b0)},
+       {IWL_PCI_DEVICE(0x2720, 0x0234, iwl9560_2ac_cfg_qu_b0_jf_b0)},
+       {IWL_PCI_DEVICE(0x2720, 0x0238, iwl9560_2ac_cfg_qu_b0_jf_b0)},
+       {IWL_PCI_DEVICE(0x2720, 0x023C, iwl9560_2ac_cfg_qu_b0_jf_b0)},
+       {IWL_PCI_DEVICE(0x2720, 0x0260, iwl9461_2ac_cfg_qu_b0_jf_b0)},
+       {IWL_PCI_DEVICE(0x2720, 0x0264, iwl9461_2ac_cfg_qu_b0_jf_b0)},
+       {IWL_PCI_DEVICE(0x2720, 0x02A0, iwl9462_2ac_cfg_qu_b0_jf_b0)},
+       {IWL_PCI_DEVICE(0x2720, 0x02A4, iwl9462_2ac_cfg_qu_b0_jf_b0)},
+       {IWL_PCI_DEVICE(0x2720, 0x1030, iwl9560_2ac_cfg_qu_b0_jf_b0)},
+       {IWL_PCI_DEVICE(0x2720, 0x1551, killer1550s_2ac_cfg_qu_b0_jf_b0)},
+       {IWL_PCI_DEVICE(0x2720, 0x1552, killer1550i_2ac_cfg_qu_b0_jf_b0)},
+       {IWL_PCI_DEVICE(0x2720, 0x2030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)},
+       {IWL_PCI_DEVICE(0x2720, 0x2034, iwl9560_2ac_160_cfg_qu_b0_jf_b0)},
+       {IWL_PCI_DEVICE(0x2720, 0x4030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)},
+       {IWL_PCI_DEVICE(0x2720, 0x4034, iwl9560_2ac_160_cfg_qu_b0_jf_b0)},
+       {IWL_PCI_DEVICE(0x2720, 0x40A4, iwl9462_2ac_cfg_qu_b0_jf_b0)},
+       {IWL_PCI_DEVICE(0x2720, 0x4234, iwl9560_2ac_cfg_qu_b0_jf_b0)},
+       {IWL_PCI_DEVICE(0x2720, 0x42A4, iwl9462_2ac_cfg_qu_b0_jf_b0)},
+
+       {IWL_PCI_DEVICE(0x30DC, 0x0030, iwl9560_2ac_160_cfg_soc)},
+       {IWL_PCI_DEVICE(0x30DC, 0x0034, iwl9560_2ac_cfg_soc)},
+       {IWL_PCI_DEVICE(0x30DC, 0x0038, iwl9560_2ac_160_cfg_soc)},
+       {IWL_PCI_DEVICE(0x30DC, 0x003C, iwl9560_2ac_160_cfg_soc)},
+       {IWL_PCI_DEVICE(0x30DC, 0x0060, iwl9460_2ac_cfg_soc)},
+       {IWL_PCI_DEVICE(0x30DC, 0x0064, iwl9461_2ac_cfg_soc)},
+       {IWL_PCI_DEVICE(0x30DC, 0x00A0, iwl9462_2ac_cfg_soc)},
+       {IWL_PCI_DEVICE(0x30DC, 0x00A4, iwl9462_2ac_cfg_soc)},
+       {IWL_PCI_DEVICE(0x30DC, 0x0230, iwl9560_2ac_cfg_soc)},
+       {IWL_PCI_DEVICE(0x30DC, 0x0234, iwl9560_2ac_cfg_soc)},
+       {IWL_PCI_DEVICE(0x30DC, 0x0238, iwl9560_2ac_cfg_soc)},
+       {IWL_PCI_DEVICE(0x30DC, 0x023C, iwl9560_2ac_cfg_soc)},
+       {IWL_PCI_DEVICE(0x30DC, 0x0260, iwl9461_2ac_cfg_soc)},
+       {IWL_PCI_DEVICE(0x30DC, 0x0264, iwl9461_2ac_cfg_soc)},
+       {IWL_PCI_DEVICE(0x30DC, 0x02A0, iwl9462_2ac_cfg_soc)},
+       {IWL_PCI_DEVICE(0x30DC, 0x02A4, iwl9462_2ac_cfg_soc)},
+       {IWL_PCI_DEVICE(0x30DC, 0x1010, iwl9260_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x30DC, 0x1030, iwl9560_2ac_cfg_soc)},
+       {IWL_PCI_DEVICE(0x30DC, 0x1210, iwl9260_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x30DC, 0x1551, iwl9560_killer_s_2ac_cfg_soc)},
+       {IWL_PCI_DEVICE(0x30DC, 0x1552, iwl9560_killer_2ac_cfg_soc)},
+       {IWL_PCI_DEVICE(0x30DC, 0x2030, iwl9560_2ac_160_cfg_soc)},
+       {IWL_PCI_DEVICE(0x30DC, 0x2034, iwl9560_2ac_160_cfg_soc)},
+       {IWL_PCI_DEVICE(0x30DC, 0x4030, iwl9560_2ac_160_cfg_soc)},
+       {IWL_PCI_DEVICE(0x30DC, 0x4034, iwl9560_2ac_160_cfg_soc)},
+       {IWL_PCI_DEVICE(0x30DC, 0x40A4, iwl9462_2ac_cfg_soc)},
+       {IWL_PCI_DEVICE(0x30DC, 0x4234, iwl9560_2ac_cfg_soc)},
+       {IWL_PCI_DEVICE(0x30DC, 0x42A4, iwl9462_2ac_cfg_soc)},
 
        {IWL_PCI_DEVICE(0x31DC, 0x0030, iwl9560_2ac_160_cfg_shared_clk)},
        {IWL_PCI_DEVICE(0x31DC, 0x0034, iwl9560_2ac_cfg_shared_clk)},
@@ -1067,11 +1068,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                }
        } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) ==
                   CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) &&
-                  ((cfg != &iwl_ax200_cfg_cc &&
-                    cfg != &killer1650x_2ax_cfg &&
-                    cfg != &killer1650w_2ax_cfg &&
-                    cfg != &iwl_ax201_cfg_quz_hr) ||
-                   iwl_trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0)) {
+                  iwl_trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0) {
                u32 hw_status;
 
                hw_status = iwl_read_prph(iwl_trans, UMAG_GEN_HW_STATUS);
index df8455f14e4d82462238de74a9b3f4ea664ccfe0..ca3bb4d65b00e2ff99421cf867f2812a4f2da563 100644 (file)
 #include "internal.h"
 #include "fw/dbg.h"
 
+static int iwl_pcie_gen2_force_power_gating(struct iwl_trans *trans)
+{
+       iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG,
+                         HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
+       udelay(20);
+       iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG,
+                         HPM_HIPM_GEN_CFG_CR_PG_EN |
+                         HPM_HIPM_GEN_CFG_CR_SLP_EN);
+       udelay(20);
+       iwl_clear_bits_prph(trans, HPM_HIPM_GEN_CFG,
+                           HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
+
+       iwl_trans_sw_reset(trans);
+       iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+
+       return 0;
+}
+
 /*
  * Start up NIC's basic functionality after it has been reset
  * (e.g. after platform boot, or shutdown via iwl_pcie_apm_stop())
@@ -92,6 +110,13 @@ int iwl_pcie_gen2_apm_init(struct iwl_trans *trans)
 
        iwl_pcie_apm_config(trans);
 
+       if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000 &&
+           trans->cfg->integrated) {
+               ret = iwl_pcie_gen2_force_power_gating(trans);
+               if (ret)
+                       return ret;
+       }
+
        ret = iwl_finish_nic_init(trans, trans->trans_cfg);
        if (ret)
                return ret;
index 158a3d762e55d6e31afd2c358c81f7d93f7264c6..e323e9a5999fd5a307ec8609044cb553db65682f 100644 (file)
@@ -3041,30 +3041,6 @@ static void prism2_clear_set_tim_queue(local_info_t *local)
        }
 }
 
-
-/*
- * HostAP uses two layers of net devices, where the inner
- * layer gets called all the time from the outer layer.
- * This is a natural nesting, which needs a split lock type.
- */
-static struct lock_class_key hostap_netdev_xmit_lock_key;
-static struct lock_class_key hostap_netdev_addr_lock_key;
-
-static void prism2_set_lockdep_class_one(struct net_device *dev,
-                                        struct netdev_queue *txq,
-                                        void *_unused)
-{
-       lockdep_set_class(&txq->_xmit_lock,
-                         &hostap_netdev_xmit_lock_key);
-}
-
-static void prism2_set_lockdep_class(struct net_device *dev)
-{
-       lockdep_set_class(&dev->addr_list_lock,
-                         &hostap_netdev_addr_lock_key);
-       netdev_for_each_tx_queue(dev, prism2_set_lockdep_class_one, NULL);
-}
-
 static struct net_device *
 prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx,
                       struct device *sdev)
@@ -3223,7 +3199,6 @@ while (0)
        if (ret >= 0)
                ret = register_netdevice(dev);
 
-       prism2_set_lockdep_class(dev);
        rtnl_unlock();
        if (ret < 0) {
                printk(KERN_WARNING "%s: register netdevice failed!\n",
index 4d03596e891f11c66ff6cb011d3f4a39830fff1b..d7a1ddc9e40742a718337e7e35201eb8f81c079f 100644 (file)
@@ -8,6 +8,8 @@ mt76-y := \
        mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \
        tx.o agg-rx.o mcu.o
 
+mt76-$(CONFIG_PCI) += pci.o
+
 mt76-usb-y := usb.o usb_trace.o
 
 CFLAGS_trace.o := -I$(src)
index c747eb24581c42683f93f6e285a660e2edd9daea..8f69d00bd940a98aaa84a0166c7375357ecab82a 100644 (file)
@@ -53,8 +53,10 @@ mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q,
        u32 ctrl;
        int i, idx = -1;
 
-       if (txwi)
+       if (txwi) {
                q->entry[q->head].txwi = DMA_DUMMY_DATA;
+               q->entry[q->head].skip_buf0 = true;
+       }
 
        for (i = 0; i < nbufs; i += 2, buf += 2) {
                u32 buf0 = buf[0].addr, buf1 = 0;
@@ -97,7 +99,7 @@ mt76_dma_tx_cleanup_idx(struct mt76_dev *dev, struct mt76_queue *q, int idx,
        __le32 __ctrl = READ_ONCE(q->desc[idx].ctrl);
        u32 ctrl = le32_to_cpu(__ctrl);
 
-       if (!e->txwi || !e->skb) {
+       if (!e->skip_buf0) {
                __le32 addr = READ_ONCE(q->desc[idx].buf0);
                u32 len = FIELD_GET(MT_DMA_CTL_SD_LEN0, ctrl);
 
index 570c159515a09cae82d2e17cd74324cea5132cd5..8aec7ccf2d79b45ccbcd9388ab72e97e4c98bb2c 100644 (file)
@@ -93,8 +93,9 @@ struct mt76_queue_entry {
                struct urb *urb;
        };
        enum mt76_txq_id qid;
-       bool schedule;
-       bool done;
+       bool skip_buf0:1;
+       bool schedule:1;
+       bool done:1;
 };
 
 struct mt76_queue_regs {
@@ -578,6 +579,7 @@ bool __mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
 #define mt76_poll_msec(dev, ...) __mt76_poll_msec(&((dev)->mt76), __VA_ARGS__)
 
 void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs);
+void mt76_pci_disable_aspm(struct pci_dev *pdev);
 
 static inline u16 mt76_chip(struct mt76_dev *dev)
 {
index 73c3104f88582bbdefca26fb44b86f765248642e..cf611d1b817c07dd5179c1dc2aa0182975904a3f 100644 (file)
@@ -81,6 +81,8 @@ mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        /* RG_SSUSB_CDR_BR_PE1D = 0x3 */
        mt76_rmw_field(dev, 0x15c58, 0x3 << 6, 0x3);
 
+       mt76_pci_disable_aspm(pdev);
+
        return 0;
 
 error:
diff --git a/drivers/net/wireless/mediatek/mt76/pci.c b/drivers/net/wireless/mediatek/mt76/pci.c
new file mode 100644 (file)
index 0000000..04c5a69
--- /dev/null
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Copyright (C) 2019 Lorenzo Bianconi <lorenzo@kernel.org>
+ */
+
+#include <linux/pci.h>
+
+void mt76_pci_disable_aspm(struct pci_dev *pdev)
+{
+       struct pci_dev *parent = pdev->bus->self;
+       u16 aspm_conf, parent_aspm_conf = 0;
+
+       pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &aspm_conf);
+       aspm_conf &= PCI_EXP_LNKCTL_ASPMC;
+       if (parent) {
+               pcie_capability_read_word(parent, PCI_EXP_LNKCTL,
+                                         &parent_aspm_conf);
+               parent_aspm_conf &= PCI_EXP_LNKCTL_ASPMC;
+       }
+
+       if (!aspm_conf && (!parent || !parent_aspm_conf)) {
+               /* aspm already disabled */
+               return;
+       }
+
+       dev_info(&pdev->dev, "disabling ASPM %s %s\n",
+                (aspm_conf & PCI_EXP_LNKCTL_ASPM_L0S) ? "L0s" : "",
+                (aspm_conf & PCI_EXP_LNKCTL_ASPM_L1) ? "L1" : "");
+
+       if (IS_ENABLED(CONFIG_PCIEASPM)) {
+               int err;
+
+               err = pci_disable_link_state(pdev, aspm_conf);
+               if (!err)
+                       return;
+       }
+
+       /* both device and parent should have the same ASPM setting.
+        * disable ASPM in downstream component first and then upstream.
+        */
+       pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, aspm_conf);
+       if (parent)
+               pcie_capability_clear_word(parent, PCI_EXP_LNKCTL,
+                                          aspm_conf);
+}
+EXPORT_SYMBOL_GPL(mt76_pci_disable_aspm);
index 6087ec7a90a6e6ad5d2ac1921beadd243780f866..f88d26535978d958b6b21eba521e446786b87b10 100644 (file)
@@ -822,7 +822,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
                hdr = rtl_get_hdr(skb);
                fc = rtl_get_fc(skb);
 
-               if (!stats.crc && !stats.hwerror) {
+               if (!stats.crc && !stats.hwerror && (skb->len > FCS_LEN)) {
                        memcpy(IEEE80211_SKB_RXCB(skb), &rx_status,
                               sizeof(rx_status));
 
@@ -859,6 +859,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
                                _rtl_pci_rx_to_mac80211(hw, skb, rx_status);
                        }
                } else {
+                       /* drop packets with errors or those too short */
                        dev_kfree_skb_any(skb);
                }
 new_trx_end:
index 70f04c2f5b176ffe8a8178fb02cbbffbdd4a2990..fff8dda14023861158acc10bea9f6df2b203d2f6 100644 (file)
@@ -754,6 +754,9 @@ static void rtl_p2p_noa_ie(struct ieee80211_hw *hw, void *data,
                                return;
                        } else {
                                noa_num = (noa_len - 2) / 13;
+                               if (noa_num > P2P_MAX_NOA_NUM)
+                                       noa_num = P2P_MAX_NOA_NUM;
+
                        }
                        noa_index = ie[3];
                        if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode ==
@@ -848,6 +851,9 @@ static void rtl_p2p_action_ie(struct ieee80211_hw *hw, void *data,
                                return;
                        } else {
                                noa_num = (noa_len - 2) / 13;
+                               if (noa_num > P2P_MAX_NOA_NUM)
+                                       noa_num = P2P_MAX_NOA_NUM;
+
                        }
                        noa_index = ie[3];
                        if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode ==
index be92e1220284c7d07d2b8143f5b8084e1d9375da..7997cc6de334f5222f038f3b058f036078aa41db 100644 (file)
@@ -548,6 +548,7 @@ static int virt_wifi_newlink(struct net *src_net, struct net_device *dev,
        priv->is_connected = false;
        priv->is_up = false;
        INIT_DELAYED_WORK(&priv->connect, virt_wifi_connect_complete);
+       __module_get(THIS_MODULE);
 
        return 0;
 unregister_netdev:
@@ -578,6 +579,7 @@ static void virt_wifi_dellink(struct net_device *dev,
        netdev_upper_dev_unlink(priv->lowerdev, dev);
 
        unregister_netdevice_queue(dev, head);
+       module_put(THIS_MODULE);
 
        /* Deleting the wiphy is handled in the module destructor. */
 }
@@ -590,6 +592,42 @@ static struct rtnl_link_ops virt_wifi_link_ops = {
        .priv_size      = sizeof(struct virt_wifi_netdev_priv),
 };
 
+static bool netif_is_virt_wifi_dev(const struct net_device *dev)
+{
+       return rcu_access_pointer(dev->rx_handler) == virt_wifi_rx_handler;
+}
+
+static int virt_wifi_event(struct notifier_block *this, unsigned long event,
+                          void *ptr)
+{
+       struct net_device *lower_dev = netdev_notifier_info_to_dev(ptr);
+       struct virt_wifi_netdev_priv *priv;
+       struct net_device *upper_dev;
+       LIST_HEAD(list_kill);
+
+       if (!netif_is_virt_wifi_dev(lower_dev))
+               return NOTIFY_DONE;
+
+       switch (event) {
+       case NETDEV_UNREGISTER:
+               priv = rtnl_dereference(lower_dev->rx_handler_data);
+               if (!priv)
+                       return NOTIFY_DONE;
+
+               upper_dev = priv->upperdev;
+
+               upper_dev->rtnl_link_ops->dellink(upper_dev, &list_kill);
+               unregister_netdevice_many(&list_kill);
+               break;
+       }
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block virt_wifi_notifier = {
+       .notifier_call = virt_wifi_event,
+};
+
 /* Acquires and releases the rtnl lock. */
 static int __init virt_wifi_init_module(void)
 {
@@ -598,14 +636,25 @@ static int __init virt_wifi_init_module(void)
        /* Guaranteed to be locallly-administered and not multicast. */
        eth_random_addr(fake_router_bssid);
 
+       err = register_netdevice_notifier(&virt_wifi_notifier);
+       if (err)
+               return err;
+
+       err = -ENOMEM;
        common_wiphy = virt_wifi_make_wiphy();
        if (!common_wiphy)
-               return -ENOMEM;
+               goto notifier;
 
        err = rtnl_link_register(&virt_wifi_link_ops);
        if (err)
-               virt_wifi_destroy_wiphy(common_wiphy);
+               goto destroy_wiphy;
 
+       return 0;
+
+destroy_wiphy:
+       virt_wifi_destroy_wiphy(common_wiphy);
+notifier:
+       unregister_netdevice_notifier(&virt_wifi_notifier);
        return err;
 }
 
@@ -615,6 +664,7 @@ static void __exit virt_wifi_cleanup_module(void)
        /* Will delete any devices that depend on the wiphy. */
        rtnl_link_unregister(&virt_wifi_link_ops);
        virt_wifi_destroy_wiphy(common_wiphy);
+       unregister_netdevice_notifier(&virt_wifi_notifier);
 }
 
 module_init(virt_wifi_init_module);
index 1cd113c8d7cba702d623860aac986b4b6751b9f9..ad0abb1f0bae9b76135d9f41ed2763d36c95ebac 100644 (file)
@@ -259,7 +259,7 @@ static void fdp_nci_i2c_read_device_properties(struct device *dev,
                                                  *fw_vsc_cfg, len);
 
                if (r) {
-                       devm_kfree(dev, fw_vsc_cfg);
+                       devm_kfree(dev, *fw_vsc_cfg);
                        goto vsc_read_err;
                }
        } else {
index f9ac176cf257b214197ba04da40a4f458f1dae7a..2ce17932a073bf680c37bae3616c2fbd7c10cdb5 100644 (file)
@@ -708,6 +708,7 @@ static int st21nfca_hci_complete_target_discovered(struct nfc_hci_dev *hdev,
                                                        NFC_PROTO_FELICA_MASK;
                } else {
                        kfree_skb(nfcid_skb);
+                       nfcid_skb = NULL;
                        /* P2P in type A */
                        r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_F_GATE,
                                        ST21NFCA_RF_READER_F_NFCID1,
index 30de7efef00357f5231ebdee06953aa341aac6fc..e0f064dcbd0211ec188cde84de322ffc7880d40a 100644 (file)
@@ -158,9 +158,11 @@ void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl)
        struct nvme_ns *ns;
 
        mutex_lock(&ctrl->scan_lock);
+       down_read(&ctrl->namespaces_rwsem);
        list_for_each_entry(ns, &ctrl->namespaces, list)
                if (nvme_mpath_clear_current_path(ns))
                        kblockd_schedule_work(&ns->head->requeue_work);
+       up_read(&ctrl->namespaces_rwsem);
        mutex_unlock(&ctrl->scan_lock);
 }
 
@@ -522,14 +524,13 @@ static int nvme_update_ana_state(struct nvme_ctrl *ctrl,
        return 0;
 }
 
-static int nvme_read_ana_log(struct nvme_ctrl *ctrl, bool groups_only)
+static int nvme_read_ana_log(struct nvme_ctrl *ctrl)
 {
        u32 nr_change_groups = 0;
        int error;
 
        mutex_lock(&ctrl->ana_lock);
-       error = nvme_get_log(ctrl, NVME_NSID_ALL, NVME_LOG_ANA,
-                       groups_only ? NVME_ANA_LOG_RGO : 0,
+       error = nvme_get_log(ctrl, NVME_NSID_ALL, NVME_LOG_ANA, 0,
                        ctrl->ana_log_buf, ctrl->ana_log_size, 0);
        if (error) {
                dev_warn(ctrl->device, "Failed to get ANA log: %d\n", error);
@@ -565,7 +566,7 @@ static void nvme_ana_work(struct work_struct *work)
 {
        struct nvme_ctrl *ctrl = container_of(work, struct nvme_ctrl, ana_work);
 
-       nvme_read_ana_log(ctrl, false);
+       nvme_read_ana_log(ctrl);
 }
 
 static void nvme_anatt_timeout(struct timer_list *t)
@@ -715,7 +716,7 @@ int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
                goto out;
        }
 
-       error = nvme_read_ana_log(ctrl, true);
+       error = nvme_read_ana_log(ctrl);
        if (error)
                goto out_free_ana_log_buf;
        return 0;
index f19a28b4e997f473c40c56c0564645565b8c71e7..cb4c3000a57e88fa5cbb0ce740713d14238f0845 100644 (file)
@@ -2133,8 +2133,16 @@ err_unreg_client:
 
 static void __exit nvme_rdma_cleanup_module(void)
 {
+       struct nvme_rdma_ctrl *ctrl;
+
        nvmf_unregister_transport(&nvme_rdma_transport);
        ib_unregister_client(&nvme_rdma_ib_client);
+
+       mutex_lock(&nvme_rdma_ctrl_mutex);
+       list_for_each_entry(ctrl, &nvme_rdma_ctrl_list, list)
+               nvme_delete_ctrl(&ctrl->ctrl);
+       mutex_unlock(&nvme_rdma_ctrl_mutex);
+       flush_workqueue(nvme_delete_wq);
 }
 
 module_init(nvme_rdma_init_module);
index 770dbcbc999e0bff81b8643644cab20599a0c2e3..7544be84ab3582e27ded19298b45960ce3460d96 100644 (file)
@@ -2219,7 +2219,7 @@ static int nvme_tcp_poll(struct blk_mq_hw_ctx *hctx)
        struct nvme_tcp_queue *queue = hctx->driver_data;
        struct sock *sk = queue->sock->sk;
 
-       if (sk_can_busy_loop(sk) && skb_queue_empty(&sk->sk_receive_queue))
+       if (sk_can_busy_loop(sk) && skb_queue_empty_lockless(&sk->sk_receive_queue))
                sk_busy_loop(sk, true);
        nvme_tcp_try_recv(queue);
        return queue->nr_cqe;
index 7989703b883ce64ebe9fa8f58a7c718b6dd10db1..6bd610ee2cd734bf91d61a35c7ddb12df4cec0ba 100644 (file)
@@ -324,8 +324,10 @@ int of_reserved_mem_device_init_by_idx(struct device *dev,
        if (!target)
                return -ENODEV;
 
-       if (!of_device_is_available(target))
+       if (!of_device_is_available(target)) {
+               of_node_put(target);
                return 0;
+       }
 
        rmem = __find_rmem(target);
        of_node_put(target);
index 480a21e2ed39c738cbd1f66945ccdd3c2e0211b7..92e895d8645844a6a87a453259a5819541becd2c 100644 (file)
@@ -1207,6 +1207,7 @@ static int __init unittest_data_add(void)
        of_fdt_unflatten_tree(unittest_data, NULL, &unittest_data_node);
        if (!unittest_data_node) {
                pr_warn("%s: No tree to attach; not running tests\n", __func__);
+               kfree(unittest_data);
                return -ENODATA;
        }
 
index 3b7ffd0234e9c7c44a1bcbd9b924a1879b9e4207..9ff0538ee83a015d68af4425547a9998656d28eb 100644 (file)
@@ -1626,12 +1626,6 @@ struct opp_table *dev_pm_opp_set_regulators(struct device *dev,
                        goto free_regulators;
                }
 
-               ret = regulator_enable(reg);
-               if (ret < 0) {
-                       regulator_put(reg);
-                       goto free_regulators;
-               }
-
                opp_table->regulators[i] = reg;
        }
 
@@ -1645,10 +1639,8 @@ struct opp_table *dev_pm_opp_set_regulators(struct device *dev,
        return opp_table;
 
 free_regulators:
-       while (i--) {
-               regulator_disable(opp_table->regulators[i]);
-               regulator_put(opp_table->regulators[i]);
-       }
+       while (i != 0)
+               regulator_put(opp_table->regulators[--i]);
 
        kfree(opp_table->regulators);
        opp_table->regulators = NULL;
@@ -1674,10 +1666,8 @@ void dev_pm_opp_put_regulators(struct opp_table *opp_table)
        /* Make sure there are no concurrent readers while updating opp_table */
        WARN_ON(!list_empty(&opp_table->opp_list));
 
-       for (i = opp_table->regulator_count - 1; i >= 0; i--) {
-               regulator_disable(opp_table->regulators[i]);
+       for (i = opp_table->regulator_count - 1; i >= 0; i--)
                regulator_put(opp_table->regulators[i]);
-       }
 
        _free_set_opp_data(opp_table);
 
index 1813f5ad5fa23b4f4a0f81ef16c7aab159320e96..1cbb58240b8016383d9f1e9137b7190cff345935 100644 (file)
@@ -77,8 +77,6 @@ static struct dev_pm_opp *_find_opp_of_np(struct opp_table *opp_table,
 {
        struct dev_pm_opp *opp;
 
-       lockdep_assert_held(&opp_table_lock);
-
        mutex_lock(&opp_table->lock);
 
        list_for_each_entry(opp, &opp_table->opp_list, node) {
@@ -665,6 +663,13 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table)
                return 0;
        }
 
+       /*
+        * Re-initialize list_kref every time we add static OPPs to the OPP
+        * table as the reference count may be 0 after the last tie static OPPs
+        * were removed.
+        */
+       kref_init(&opp_table->list_kref);
+
        /* We have opp-table node now, iterate over it and add OPPs */
        for_each_available_child_of_node(opp_table->np, np) {
                opp = _opp_add_static_v2(opp_table, dev, np);
index 648ddb7f038a3e866c240c64a1636defeba46c60..c6800d220920ecb3613789ac094d8105ae0cdd94 100644 (file)
@@ -87,7 +87,7 @@ FUNC_GROUP_DECL(MACLINK3, L23);
 
 #define K25 7
 SIG_EXPR_LIST_DECL_SESG(K25, MACLINK4, MACLINK4, SIG_DESC_SET(SCU410, 7));
-SIG_EXPR_LIST_DECL_SESG(K25, SDA14, SDA14, SIG_DESC_SET(SCU4B0, 7));
+SIG_EXPR_LIST_DECL_SESG(K25, SDA14, I2C14, SIG_DESC_SET(SCU4B0, 7));
 PIN_DECL_2(K25, GPIOA7, MACLINK4, SDA14);
 FUNC_GROUP_DECL(MACLINK4, K25);
 
@@ -1262,13 +1262,13 @@ GROUP_DECL(SPI1, AB11, AC11, AA11);
 #define AD11 206
 SIG_EXPR_LIST_DECL_SEMG(AD11, SPI1DQ2, QSPI1, SPI1, SIG_DESC_SET(SCU438, 14));
 SIG_EXPR_LIST_DECL_SEMG(AD11, TXD13, UART13G1, UART13,
-                       SIG_DESC_SET(SCU438, 14));
+                       SIG_DESC_CLEAR(SCU4B8, 2), SIG_DESC_SET(SCU4D8, 14));
 PIN_DECL_2(AD11, GPIOZ6, SPI1DQ2, TXD13);
 
 #define AF10 207
 SIG_EXPR_LIST_DECL_SEMG(AF10, SPI1DQ3, QSPI1, SPI1, SIG_DESC_SET(SCU438, 15));
 SIG_EXPR_LIST_DECL_SEMG(AF10, RXD13, UART13G1, UART13,
-                       SIG_DESC_SET(SCU438, 15));
+                       SIG_DESC_CLEAR(SCU4B8, 3), SIG_DESC_SET(SCU4D8, 15));
 PIN_DECL_2(AF10, GPIOZ7, SPI1DQ3, RXD13);
 
 GROUP_DECL(QSPI1, AB11, AC11, AA11, AD11, AF10);
@@ -1440,91 +1440,85 @@ FUNC_GROUP_DECL(RGMII2, D4, C2, C1, D3, E4, F5, D2, E3, D1, F4, E2, E1);
 FUNC_GROUP_DECL(RMII2, D4, C2, C1, D3, D2, D1, F4, E2, E1);
 
 #define AB4 232
-SIG_EXPR_LIST_DECL_SESG(AB4, SD3CLK, SD3, SIG_DESC_SET(SCU400, 24));
-PIN_DECL_1(AB4, GPIO18D0, SD3CLK);
+SIG_EXPR_LIST_DECL_SEMG(AB4, EMMCCLK, EMMCG1, EMMC, SIG_DESC_SET(SCU400, 24));
+PIN_DECL_1(AB4, GPIO18D0, EMMCCLK);
 
 #define AA4 233
-SIG_EXPR_LIST_DECL_SESG(AA4, SD3CMD, SD3, SIG_DESC_SET(SCU400, 25));
-PIN_DECL_1(AA4, GPIO18D1, SD3CMD);
+SIG_EXPR_LIST_DECL_SEMG(AA4, EMMCCMD, EMMCG1, EMMC, SIG_DESC_SET(SCU400, 25));
+PIN_DECL_1(AA4, GPIO18D1, EMMCCMD);
 
 #define AC4 234
-SIG_EXPR_LIST_DECL_SESG(AC4, SD3DAT0, SD3, SIG_DESC_SET(SCU400, 26));
-PIN_DECL_1(AC4, GPIO18D2, SD3DAT0);
+SIG_EXPR_LIST_DECL_SEMG(AC4, EMMCDAT0, EMMCG1, EMMC, SIG_DESC_SET(SCU400, 26));
+PIN_DECL_1(AC4, GPIO18D2, EMMCDAT0);
 
 #define AA5 235
-SIG_EXPR_LIST_DECL_SESG(AA5, SD3DAT1, SD3, SIG_DESC_SET(SCU400, 27));
-PIN_DECL_1(AA5, GPIO18D3, SD3DAT1);
+SIG_EXPR_LIST_DECL_SEMG(AA5, EMMCDAT1, EMMCG4, EMMC, SIG_DESC_SET(SCU400, 27));
+PIN_DECL_1(AA5, GPIO18D3, EMMCDAT1);
 
 #define Y5 236
-SIG_EXPR_LIST_DECL_SESG(Y5, SD3DAT2, SD3, SIG_DESC_SET(SCU400, 28));
-PIN_DECL_1(Y5, GPIO18D4, SD3DAT2);
+SIG_EXPR_LIST_DECL_SEMG(Y5, EMMCDAT2, EMMCG4, EMMC, SIG_DESC_SET(SCU400, 28));
+PIN_DECL_1(Y5, GPIO18D4, EMMCDAT2);
 
 #define AB5 237
-SIG_EXPR_LIST_DECL_SESG(AB5, SD3DAT3, SD3, SIG_DESC_SET(SCU400, 29));
-PIN_DECL_1(AB5, GPIO18D5, SD3DAT3);
+SIG_EXPR_LIST_DECL_SEMG(AB5, EMMCDAT3, EMMCG4, EMMC, SIG_DESC_SET(SCU400, 29));
+PIN_DECL_1(AB5, GPIO18D5, EMMCDAT3);
 
 #define AB6 238
-SIG_EXPR_LIST_DECL_SESG(AB6, SD3CD, SD3, SIG_DESC_SET(SCU400, 30));
-PIN_DECL_1(AB6, GPIO18D6, SD3CD);
+SIG_EXPR_LIST_DECL_SEMG(AB6, EMMCCD, EMMCG1, EMMC, SIG_DESC_SET(SCU400, 30));
+PIN_DECL_1(AB6, GPIO18D6, EMMCCD);
 
 #define AC5 239
-SIG_EXPR_LIST_DECL_SESG(AC5, SD3WP, SD3, SIG_DESC_SET(SCU400, 31));
-PIN_DECL_1(AC5, GPIO18D7, SD3WP);
+SIG_EXPR_LIST_DECL_SEMG(AC5, EMMCWP, EMMCG1, EMMC, SIG_DESC_SET(SCU400, 31));
+PIN_DECL_1(AC5, GPIO18D7, EMMCWP);
 
-FUNC_GROUP_DECL(SD3, AB4, AA4, AC4, AA5, Y5, AB5, AB6, AC5);
+GROUP_DECL(EMMCG1, AB4, AA4, AC4, AB6, AC5);
+GROUP_DECL(EMMCG4, AB4, AA4, AC4, AA5, Y5, AB5, AB6, AC5);
 
 #define Y1 240
 SIG_EXPR_LIST_DECL_SEMG(Y1, FWSPIDCS, FWSPID, FWSPID, SIG_DESC_SET(SCU500, 3));
 SIG_EXPR_LIST_DECL_SESG(Y1, VBCS, VB, SIG_DESC_SET(SCU500, 5));
-SIG_EXPR_LIST_DECL_SESG(Y1, SD3DAT4, SD3DAT4, SIG_DESC_SET(SCU404, 0));
-PIN_DECL_3(Y1, GPIO18E0, FWSPIDCS, VBCS, SD3DAT4);
-FUNC_GROUP_DECL(SD3DAT4, Y1);
+SIG_EXPR_LIST_DECL_SEMG(Y1, EMMCDAT4, EMMCG8, EMMC, SIG_DESC_SET(SCU404, 0));
+PIN_DECL_3(Y1, GPIO18E0, FWSPIDCS, VBCS, EMMCDAT4);
 
 #define Y2 241
 SIG_EXPR_LIST_DECL_SEMG(Y2, FWSPIDCK, FWSPID, FWSPID, SIG_DESC_SET(SCU500, 3));
 SIG_EXPR_LIST_DECL_SESG(Y2, VBCK, VB, SIG_DESC_SET(SCU500, 5));
-SIG_EXPR_LIST_DECL_SESG(Y2, SD3DAT5, SD3DAT5, SIG_DESC_SET(SCU404, 1));
-PIN_DECL_3(Y2, GPIO18E1, FWSPIDCK, VBCK, SD3DAT5);
-FUNC_GROUP_DECL(SD3DAT5, Y2);
+SIG_EXPR_LIST_DECL_SEMG(Y2, EMMCDAT5, EMMCG8, EMMC, SIG_DESC_SET(SCU404, 1));
+PIN_DECL_3(Y2, GPIO18E1, FWSPIDCK, VBCK, EMMCDAT5);
 
 #define Y3 242
 SIG_EXPR_LIST_DECL_SEMG(Y3, FWSPIDMOSI, FWSPID, FWSPID,
                        SIG_DESC_SET(SCU500, 3));
 SIG_EXPR_LIST_DECL_SESG(Y3, VBMOSI, VB, SIG_DESC_SET(SCU500, 5));
-SIG_EXPR_LIST_DECL_SESG(Y3, SD3DAT6, SD3DAT6, SIG_DESC_SET(SCU404, 2));
-PIN_DECL_3(Y3, GPIO18E2, FWSPIDMOSI, VBMOSI, SD3DAT6);
-FUNC_GROUP_DECL(SD3DAT6, Y3);
+SIG_EXPR_LIST_DECL_SEMG(Y3, EMMCDAT6, EMMCG8, EMMC, SIG_DESC_SET(SCU404, 2));
+PIN_DECL_3(Y3, GPIO18E2, FWSPIDMOSI, VBMOSI, EMMCDAT6);
 
 #define Y4 243
 SIG_EXPR_LIST_DECL_SEMG(Y4, FWSPIDMISO, FWSPID, FWSPID,
                        SIG_DESC_SET(SCU500, 3));
 SIG_EXPR_LIST_DECL_SESG(Y4, VBMISO, VB, SIG_DESC_SET(SCU500, 5));
-SIG_EXPR_LIST_DECL_SESG(Y4, SD3DAT7, SD3DAT7, SIG_DESC_SET(SCU404, 3));
-PIN_DECL_3(Y4, GPIO18E3, FWSPIDMISO, VBMISO, SD3DAT7);
-FUNC_GROUP_DECL(SD3DAT7, Y4);
+SIG_EXPR_LIST_DECL_SEMG(Y4, EMMCDAT7, EMMCG8, EMMC, SIG_DESC_SET(SCU404, 3));
+PIN_DECL_3(Y4, GPIO18E3, FWSPIDMISO, VBMISO, EMMCDAT7);
 
 GROUP_DECL(FWSPID, Y1, Y2, Y3, Y4);
 GROUP_DECL(FWQSPID, Y1, Y2, Y3, Y4, AE12, AF12);
+GROUP_DECL(EMMCG8, AB4, AA4, AC4, AA5, Y5, AB5, AB6, AC5, Y1, Y2, Y3, Y4);
 FUNC_DECL_2(FWSPID, FWSPID, FWQSPID);
 FUNC_GROUP_DECL(VB, Y1, Y2, Y3, Y4);
-
+FUNC_DECL_3(EMMC, EMMCG1, EMMCG4, EMMCG8);
 /*
  * FIXME: Confirm bits and priorities are the right way around for the
  * following 4 pins
  */
 #define AF25 244
-SIG_EXPR_LIST_DECL_SEMG(AF25, I3C3SCL, I3C3, I3C3, SIG_DESC_SET(SCU438, 20),
-                       SIG_DESC_SET(SCU4D8, 20));
-SIG_EXPR_LIST_DECL_SESG(AF25, FSI1CLK, FSI1, SIG_DESC_CLEAR(SCU438, 20),
-                       SIG_DESC_SET(SCU4D8, 20));
+SIG_EXPR_LIST_DECL_SEMG(AF25, I3C3SCL, I3C3, I3C3, SIG_DESC_SET(SCU438, 20));
+SIG_EXPR_LIST_DECL_SESG(AF25, FSI1CLK, FSI1, SIG_DESC_SET(SCU4D8, 20));
 PIN_DECL_(AF25, SIG_EXPR_LIST_PTR(AF25, I3C3SCL),
          SIG_EXPR_LIST_PTR(AF25, FSI1CLK));
 
 #define AE26 245
-SIG_EXPR_LIST_DECL_SEMG(AE26, I3C3SDA, I3C3, I3C3, SIG_DESC_SET(SCU438, 21),
-                       SIG_DESC_SET(SCU4D8, 21));
-SIG_EXPR_LIST_DECL_SESG(AE26, FSI1DATA, FSI1, SIG_DESC_CLEAR(SCU438, 21),
-                       SIG_DESC_SET(SCU4D8, 21));
+SIG_EXPR_LIST_DECL_SEMG(AE26, I3C3SDA, I3C3, I3C3, SIG_DESC_SET(SCU438, 21));
+SIG_EXPR_LIST_DECL_SESG(AE26, FSI1DATA, FSI1, SIG_DESC_SET(SCU4D8, 21));
 PIN_DECL_(AE26, SIG_EXPR_LIST_PTR(AE26, I3C3SDA),
          SIG_EXPR_LIST_PTR(AE26, FSI1DATA));
 
@@ -1533,18 +1527,14 @@ FUNC_DECL_2(I3C3, HVI3C3, I3C3);
 FUNC_GROUP_DECL(FSI1, AF25, AE26);
 
 #define AE25 246
-SIG_EXPR_LIST_DECL_SEMG(AE25, I3C4SCL, I3C4, I3C4, SIG_DESC_SET(SCU438, 22),
-                       SIG_DESC_SET(SCU4D8, 22));
-SIG_EXPR_LIST_DECL_SESG(AE25, FSI2CLK, FSI2, SIG_DESC_CLEAR(SCU438, 22),
-                       SIG_DESC_SET(SCU4D8, 22));
+SIG_EXPR_LIST_DECL_SEMG(AE25, I3C4SCL, I3C4, I3C4, SIG_DESC_SET(SCU438, 22));
+SIG_EXPR_LIST_DECL_SESG(AE25, FSI2CLK, FSI2, SIG_DESC_SET(SCU4D8, 22));
 PIN_DECL_(AE25, SIG_EXPR_LIST_PTR(AE25, I3C4SCL),
          SIG_EXPR_LIST_PTR(AE25, FSI2CLK));
 
 #define AF24 247
-SIG_EXPR_LIST_DECL_SEMG(AF24, I3C4SDA, I3C4, I3C4, SIG_DESC_SET(SCU438, 23),
-                       SIG_DESC_SET(SCU4D8, 23));
-SIG_EXPR_LIST_DECL_SESG(AF24, FSI2DATA, FSI2, SIG_DESC_CLEAR(SCU438, 23),
-                       SIG_DESC_SET(SCU4D8, 23));
+SIG_EXPR_LIST_DECL_SEMG(AF24, I3C4SDA, I3C4, I3C4, SIG_DESC_SET(SCU438, 23));
+SIG_EXPR_LIST_DECL_SESG(AF24, FSI2DATA, FSI2, SIG_DESC_SET(SCU4D8, 23));
 PIN_DECL_(AF24, SIG_EXPR_LIST_PTR(AF24, I3C4SDA),
          SIG_EXPR_LIST_PTR(AF24, FSI2DATA));
 
@@ -1574,6 +1564,8 @@ static struct pinctrl_pin_desc aspeed_g6_pins[ASPEED_G6_NR_PINS] = {
        ASPEED_PINCTRL_PIN(A3),
        ASPEED_PINCTRL_PIN(AA11),
        ASPEED_PINCTRL_PIN(AA12),
+       ASPEED_PINCTRL_PIN(AA16),
+       ASPEED_PINCTRL_PIN(AA17),
        ASPEED_PINCTRL_PIN(AA23),
        ASPEED_PINCTRL_PIN(AA24),
        ASPEED_PINCTRL_PIN(AA25),
@@ -1585,6 +1577,8 @@ static struct pinctrl_pin_desc aspeed_g6_pins[ASPEED_G6_NR_PINS] = {
        ASPEED_PINCTRL_PIN(AB11),
        ASPEED_PINCTRL_PIN(AB12),
        ASPEED_PINCTRL_PIN(AB15),
+       ASPEED_PINCTRL_PIN(AB16),
+       ASPEED_PINCTRL_PIN(AB17),
        ASPEED_PINCTRL_PIN(AB18),
        ASPEED_PINCTRL_PIN(AB19),
        ASPEED_PINCTRL_PIN(AB22),
@@ -1602,6 +1596,7 @@ static struct pinctrl_pin_desc aspeed_g6_pins[ASPEED_G6_NR_PINS] = {
        ASPEED_PINCTRL_PIN(AC11),
        ASPEED_PINCTRL_PIN(AC12),
        ASPEED_PINCTRL_PIN(AC15),
+       ASPEED_PINCTRL_PIN(AC16),
        ASPEED_PINCTRL_PIN(AC17),
        ASPEED_PINCTRL_PIN(AC18),
        ASPEED_PINCTRL_PIN(AC19),
@@ -1619,6 +1614,7 @@ static struct pinctrl_pin_desc aspeed_g6_pins[ASPEED_G6_NR_PINS] = {
        ASPEED_PINCTRL_PIN(AD12),
        ASPEED_PINCTRL_PIN(AD14),
        ASPEED_PINCTRL_PIN(AD15),
+       ASPEED_PINCTRL_PIN(AD16),
        ASPEED_PINCTRL_PIN(AD19),
        ASPEED_PINCTRL_PIN(AD20),
        ASPEED_PINCTRL_PIN(AD22),
@@ -1634,8 +1630,11 @@ static struct pinctrl_pin_desc aspeed_g6_pins[ASPEED_G6_NR_PINS] = {
        ASPEED_PINCTRL_PIN(AE12),
        ASPEED_PINCTRL_PIN(AE14),
        ASPEED_PINCTRL_PIN(AE15),
+       ASPEED_PINCTRL_PIN(AE16),
        ASPEED_PINCTRL_PIN(AE18),
        ASPEED_PINCTRL_PIN(AE19),
+       ASPEED_PINCTRL_PIN(AE25),
+       ASPEED_PINCTRL_PIN(AE26),
        ASPEED_PINCTRL_PIN(AE7),
        ASPEED_PINCTRL_PIN(AE8),
        ASPEED_PINCTRL_PIN(AF10),
@@ -1643,6 +1642,8 @@ static struct pinctrl_pin_desc aspeed_g6_pins[ASPEED_G6_NR_PINS] = {
        ASPEED_PINCTRL_PIN(AF12),
        ASPEED_PINCTRL_PIN(AF14),
        ASPEED_PINCTRL_PIN(AF15),
+       ASPEED_PINCTRL_PIN(AF24),
+       ASPEED_PINCTRL_PIN(AF25),
        ASPEED_PINCTRL_PIN(AF7),
        ASPEED_PINCTRL_PIN(AF8),
        ASPEED_PINCTRL_PIN(AF9),
@@ -1792,17 +1793,6 @@ static struct pinctrl_pin_desc aspeed_g6_pins[ASPEED_G6_NR_PINS] = {
        ASPEED_PINCTRL_PIN(Y3),
        ASPEED_PINCTRL_PIN(Y4),
        ASPEED_PINCTRL_PIN(Y5),
-       ASPEED_PINCTRL_PIN(AB16),
-       ASPEED_PINCTRL_PIN(AA17),
-       ASPEED_PINCTRL_PIN(AB17),
-       ASPEED_PINCTRL_PIN(AE16),
-       ASPEED_PINCTRL_PIN(AC16),
-       ASPEED_PINCTRL_PIN(AA16),
-       ASPEED_PINCTRL_PIN(AD16),
-       ASPEED_PINCTRL_PIN(AF25),
-       ASPEED_PINCTRL_PIN(AE26),
-       ASPEED_PINCTRL_PIN(AE25),
-       ASPEED_PINCTRL_PIN(AF24),
 };
 
 static const struct aspeed_pin_group aspeed_g6_groups[] = {
@@ -1976,11 +1966,9 @@ static const struct aspeed_pin_group aspeed_g6_groups[] = {
        ASPEED_PINCTRL_GROUP(SALT9G1),
        ASPEED_PINCTRL_GROUP(SD1),
        ASPEED_PINCTRL_GROUP(SD2),
-       ASPEED_PINCTRL_GROUP(SD3),
-       ASPEED_PINCTRL_GROUP(SD3DAT4),
-       ASPEED_PINCTRL_GROUP(SD3DAT5),
-       ASPEED_PINCTRL_GROUP(SD3DAT6),
-       ASPEED_PINCTRL_GROUP(SD3DAT7),
+       ASPEED_PINCTRL_GROUP(EMMCG1),
+       ASPEED_PINCTRL_GROUP(EMMCG4),
+       ASPEED_PINCTRL_GROUP(EMMCG8),
        ASPEED_PINCTRL_GROUP(SGPM1),
        ASPEED_PINCTRL_GROUP(SGPS1),
        ASPEED_PINCTRL_GROUP(SIOONCTRL),
@@ -2059,6 +2047,7 @@ static const struct aspeed_pin_function aspeed_g6_functions[] = {
        ASPEED_PINCTRL_FUNC(ADC8),
        ASPEED_PINCTRL_FUNC(ADC9),
        ASPEED_PINCTRL_FUNC(BMCINT),
+       ASPEED_PINCTRL_FUNC(EMMC),
        ASPEED_PINCTRL_FUNC(ESPI),
        ASPEED_PINCTRL_FUNC(ESPIALT),
        ASPEED_PINCTRL_FUNC(FSI1),
@@ -2191,11 +2180,6 @@ static const struct aspeed_pin_function aspeed_g6_functions[] = {
        ASPEED_PINCTRL_FUNC(SALT9),
        ASPEED_PINCTRL_FUNC(SD1),
        ASPEED_PINCTRL_FUNC(SD2),
-       ASPEED_PINCTRL_FUNC(SD3),
-       ASPEED_PINCTRL_FUNC(SD3DAT4),
-       ASPEED_PINCTRL_FUNC(SD3DAT5),
-       ASPEED_PINCTRL_FUNC(SD3DAT6),
-       ASPEED_PINCTRL_FUNC(SD3DAT7),
        ASPEED_PINCTRL_FUNC(SGPM1),
        ASPEED_PINCTRL_FUNC(SGPS1),
        ASPEED_PINCTRL_FUNC(SIOONCTRL),
index a2c0d52e4f7b654cb360e91aa7227a8abaa295ac..140c5ce9fbc11a4614627d69b7bbdefb9c469b7e 100644 (file)
@@ -508,7 +508,7 @@ struct aspeed_pin_desc {
  * @idx: The bit index in the register
  */
 #define SIG_DESC_SET(reg, idx) SIG_DESC_IP_BIT(ASPEED_IP_SCU, reg, idx, 1)
-#define SIG_DESC_CLEAR(reg, idx) SIG_DESC_IP_BIT(ASPEED_IP_SCU, reg, idx, 0)
+#define SIG_DESC_CLEAR(reg, idx) { ASPEED_IP_SCU, reg, BIT_MASK(idx), 0, 0 }
 
 #define SIG_DESC_LIST_SYM(sig, group) sig_descs_ ## sig ## _ ## group
 #define SIG_DESC_LIST_DECL(sig, group, ...) \
@@ -738,6 +738,7 @@ struct aspeed_pin_desc {
        static const char *FUNC_SYM(func)[] = { __VA_ARGS__ }
 
 #define FUNC_DECL_2(func, one, two) FUNC_DECL_(func, #one, #two)
+#define FUNC_DECL_3(func, one, two, three) FUNC_DECL_(func, #one, #two, #three)
 
 #define FUNC_GROUP_DECL(func, ...) \
        GROUP_DECL(func, __VA_ARGS__); \
index 6f7d3a2f2e97d8943302e64089ce21717aebc98c..42f7ab383ad9f4dda27b51e5432bd64833abc6a2 100644 (file)
@@ -1,14 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (C) 2014-2017 Broadcom
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 /*
@@ -853,7 +845,7 @@ static int iproc_gpio_probe(struct platform_device *pdev)
 
        /* optional GPIO interrupt support */
        irq = platform_get_irq(pdev, 0);
-       if (irq) {
+       if (irq > 0) {
                struct irq_chip *irqc;
                struct gpio_irq_chip *girq;
 
index 2bf6af7df7d94f0b8e5c09fec4876d7818728673..9fabc451550ead855a0beed670522dcba03d290e 100644 (file)
@@ -640,8 +640,8 @@ static int ns2_pinmux_enable(struct pinctrl_dev *pctrl_dev,
        const struct ns2_pin_function *func;
        const struct ns2_pin_group *grp;
 
-       if (grp_select > pinctrl->num_groups ||
-               func_select > pinctrl->num_functions)
+       if (grp_select >= pinctrl->num_groups ||
+               func_select >= pinctrl->num_functions)
                return -EINVAL;
 
        func = &pinctrl->functions[func_select];
index 44f8ccdbeeff0a6677de61b729bacec41a606e89..9dfdc275ee33aef3adee096a67489a4bc71ebb67 100644 (file)
@@ -43,7 +43,7 @@ static const struct berlin_desc_group as370_soc_pinctrl_groups[] = {
                        BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO5 */
                        BERLIN_PINCTRL_FUNCTION(0x1, "i2s1"), /* DO3 */
                        BERLIN_PINCTRL_FUNCTION(0x2, "pwm"), /* PWM5 */
-                       BERLIN_PINCTRL_FUNCTION(0x3, "spififib"), /* SPDIFIB */
+                       BERLIN_PINCTRL_FUNCTION(0x3, "spdifib"), /* SPDIFIB */
                        BERLIN_PINCTRL_FUNCTION(0x4, "spdifo"), /* SPDIFO */
                        BERLIN_PINCTRL_FUNCTION(0x5, "phy")), /* DBG5 */
        BERLIN_PINCTRL_GROUP("I2S1_MCLK", 0x0, 0x3, 0x12,
index aae51c507f590e77c854a3547779995ea227e7e4..2c419fa5d1c1b8b0863bdcb54846eb5b08dbb890 100644 (file)
@@ -147,6 +147,7 @@ struct chv_pin_context {
  * @pctldesc: Pin controller description
  * @pctldev: Pointer to the pin controller device
  * @chip: GPIO chip in this pin controller
+ * @irqchip: IRQ chip in this pin controller
  * @regs: MMIO registers
  * @intr_lines: Stores mapping between 16 HW interrupt wires and GPIO
  *             offset (in GPIO number space)
@@ -162,6 +163,7 @@ struct chv_pinctrl {
        struct pinctrl_desc pctldesc;
        struct pinctrl_dev *pctldev;
        struct gpio_chip chip;
+       struct irq_chip irqchip;
        void __iomem *regs;
        unsigned intr_lines[16];
        const struct chv_community *community;
@@ -1466,16 +1468,6 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned int type)
        return 0;
 }
 
-static struct irq_chip chv_gpio_irqchip = {
-       .name = "chv-gpio",
-       .irq_startup = chv_gpio_irq_startup,
-       .irq_ack = chv_gpio_irq_ack,
-       .irq_mask = chv_gpio_irq_mask,
-       .irq_unmask = chv_gpio_irq_unmask,
-       .irq_set_type = chv_gpio_irq_type,
-       .flags = IRQCHIP_SKIP_SET_WAKE,
-};
-
 static void chv_gpio_irq_handler(struct irq_desc *desc)
 {
        struct gpio_chip *gc = irq_desc_get_handler_data(desc);
@@ -1513,7 +1505,6 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
                        DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_Strago"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
                },
        },
        {
@@ -1521,7 +1512,6 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "HP"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "Setzer"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
                },
        },
        {
@@ -1529,7 +1519,6 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "Cyan"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
                },
        },
        {
@@ -1537,7 +1526,6 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "Celes"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
                },
        },
        {}
@@ -1563,7 +1551,7 @@ static void chv_init_irq_valid_mask(struct gpio_chip *chip,
                intsel >>= CHV_PADCTRL0_INTSEL_SHIFT;
 
                if (intsel >= community->nirqs)
-                       clear_bit(i, valid_mask);
+                       clear_bit(desc->number, valid_mask);
        }
 }
 
@@ -1629,7 +1617,15 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
                }
        }
 
-       ret = gpiochip_irqchip_add(chip, &chv_gpio_irqchip, 0,
+       pctrl->irqchip.name = "chv-gpio";
+       pctrl->irqchip.irq_startup = chv_gpio_irq_startup;
+       pctrl->irqchip.irq_ack = chv_gpio_irq_ack;
+       pctrl->irqchip.irq_mask = chv_gpio_irq_mask;
+       pctrl->irqchip.irq_unmask = chv_gpio_irq_unmask;
+       pctrl->irqchip.irq_set_type = chv_gpio_irq_type;
+       pctrl->irqchip.flags = IRQCHIP_SKIP_SET_WAKE;
+
+       ret = gpiochip_irqchip_add(chip, &pctrl->irqchip, 0,
                                   handle_bad_irq, IRQ_TYPE_NONE);
        if (ret) {
                dev_err(pctrl->dev, "failed to add IRQ chip\n");
@@ -1646,7 +1642,7 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
                }
        }
 
-       gpiochip_set_chained_irqchip(chip, &chv_gpio_irqchip, irq,
+       gpiochip_set_chained_irqchip(chip, &pctrl->irqchip, irq,
                                     chv_gpio_irq_handler);
        return 0;
 }
index 1f13bcd0e4e1447a63cea190dfca301929ea38af..83981ad66a71e05f522ba81f679908ed04424e33 100644 (file)
@@ -52,6 +52,7 @@
 #define PADCFG0_GPIROUTNMI             BIT(17)
 #define PADCFG0_PMODE_SHIFT            10
 #define PADCFG0_PMODE_MASK             GENMASK(13, 10)
+#define PADCFG0_PMODE_GPIO             0
 #define PADCFG0_GPIORXDIS              BIT(9)
 #define PADCFG0_GPIOTXDIS              BIT(8)
 #define PADCFG0_GPIORXSTATE            BIT(1)
@@ -96,6 +97,7 @@ struct intel_pinctrl_context {
  * @pctldesc: Pin controller description
  * @pctldev: Pointer to the pin controller device
  * @chip: GPIO chip in this pin controller
+ * @irqchip: IRQ chip in this pin controller
  * @soc: SoC/PCH specific pin configuration data
  * @communities: All communities in this pin controller
  * @ncommunities: Number of communities in this pin controller
@@ -108,6 +110,7 @@ struct intel_pinctrl {
        struct pinctrl_desc pctldesc;
        struct pinctrl_dev *pctldev;
        struct gpio_chip chip;
+       struct irq_chip irqchip;
        const struct intel_pinctrl_soc_data *soc;
        struct intel_community *communities;
        size_t ncommunities;
@@ -330,7 +333,7 @@ static void intel_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
        cfg1 = readl(intel_get_padcfg(pctrl, pin, PADCFG1));
 
        mode = (cfg0 & PADCFG0_PMODE_MASK) >> PADCFG0_PMODE_SHIFT;
-       if (!mode)
+       if (mode == PADCFG0_PMODE_GPIO)
                seq_puts(s, "GPIO ");
        else
                seq_printf(s, "mode %d ", mode);
@@ -456,6 +459,11 @@ static void __intel_gpio_set_direction(void __iomem *padcfg0, bool input)
        writel(value, padcfg0);
 }
 
+static int intel_gpio_get_gpio_mode(void __iomem *padcfg0)
+{
+       return (readl(padcfg0) & PADCFG0_PMODE_MASK) >> PADCFG0_PMODE_SHIFT;
+}
+
 static void intel_gpio_set_gpio_mode(void __iomem *padcfg0)
 {
        u32 value;
@@ -489,7 +497,20 @@ static int intel_gpio_request_enable(struct pinctrl_dev *pctldev,
        }
 
        padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0);
+
+       /*
+        * If pin is already configured in GPIO mode, we assume that
+        * firmware provides correct settings. In such case we avoid
+        * potential glitches on the pin. Otherwise, for the pin in
+        * alternative mode, consumer has to supply respective flags.
+        */
+       if (intel_gpio_get_gpio_mode(padcfg0) == PADCFG0_PMODE_GPIO) {
+               raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+               return 0;
+       }
+
        intel_gpio_set_gpio_mode(padcfg0);
+
        /* Disable TX buffer and enable RX (this will be input) */
        __intel_gpio_set_direction(padcfg0, true);
 
@@ -1139,16 +1160,6 @@ static irqreturn_t intel_gpio_irq(int irq, void *data)
        return ret;
 }
 
-static struct irq_chip intel_gpio_irqchip = {
-       .name = "intel-gpio",
-       .irq_ack = intel_gpio_irq_ack,
-       .irq_mask = intel_gpio_irq_mask,
-       .irq_unmask = intel_gpio_irq_unmask,
-       .irq_set_type = intel_gpio_irq_type,
-       .irq_set_wake = intel_gpio_irq_wake,
-       .flags = IRQCHIP_MASK_ON_SUSPEND,
-};
-
 static int intel_gpio_add_pin_ranges(struct intel_pinctrl *pctrl,
                                     const struct intel_community *community)
 {
@@ -1198,12 +1209,22 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
 
        pctrl->chip = intel_gpio_chip;
 
+       /* Setup GPIO chip */
        pctrl->chip.ngpio = intel_gpio_ngpio(pctrl);
        pctrl->chip.label = dev_name(pctrl->dev);
        pctrl->chip.parent = pctrl->dev;
        pctrl->chip.base = -1;
        pctrl->irq = irq;
 
+       /* Setup IRQ chip */
+       pctrl->irqchip.name = dev_name(pctrl->dev);
+       pctrl->irqchip.irq_ack = intel_gpio_irq_ack;
+       pctrl->irqchip.irq_mask = intel_gpio_irq_mask;
+       pctrl->irqchip.irq_unmask = intel_gpio_irq_unmask;
+       pctrl->irqchip.irq_set_type = intel_gpio_irq_type;
+       pctrl->irqchip.irq_set_wake = intel_gpio_irq_wake;
+       pctrl->irqchip.flags = IRQCHIP_MASK_ON_SUSPEND;
+
        ret = devm_gpiochip_add_data(pctrl->dev, &pctrl->chip, pctrl);
        if (ret) {
                dev_err(pctrl->dev, "failed to register gpiochip\n");
@@ -1233,15 +1254,14 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
                return ret;
        }
 
-       ret = gpiochip_irqchip_add(&pctrl->chip, &intel_gpio_irqchip, 0,
+       ret = gpiochip_irqchip_add(&pctrl->chip, &pctrl->irqchip, 0,
                                   handle_bad_irq, IRQ_TYPE_NONE);
        if (ret) {
                dev_err(pctrl->dev, "failed to add irqchip\n");
                return ret;
        }
 
-       gpiochip_set_chained_irqchip(&pctrl->chip, &intel_gpio_irqchip, irq,
-                                    NULL);
+       gpiochip_set_chained_irqchip(&pctrl->chip, &pctrl->irqchip, irq, NULL);
        return 0;
 }
 
index 6462d3ca7ceb9b44b406015397102eadec5c2f99..f2f5fcd9a2374f1f1c8a403724503050fad5dc75 100644 (file)
@@ -183,10 +183,10 @@ static struct armada_37xx_pin_group armada_37xx_nb_groups[] = {
        PIN_GRP_EXTRA("uart2", 9, 2, BIT(1) | BIT(13) | BIT(14) | BIT(19),
                      BIT(1) | BIT(13) | BIT(14), BIT(1) | BIT(19),
                      18, 2, "gpio", "uart"),
-       PIN_GRP_GPIO("led0_od", 11, 1, BIT(20), "led"),
-       PIN_GRP_GPIO("led1_od", 12, 1, BIT(21), "led"),
-       PIN_GRP_GPIO("led2_od", 13, 1, BIT(22), "led"),
-       PIN_GRP_GPIO("led3_od", 14, 1, BIT(23), "led"),
+       PIN_GRP_GPIO_2("led0_od", 11, 1, BIT(20), BIT(20), 0, "led"),
+       PIN_GRP_GPIO_2("led1_od", 12, 1, BIT(21), BIT(21), 0, "led"),
+       PIN_GRP_GPIO_2("led2_od", 13, 1, BIT(22), BIT(22), 0, "led"),
+       PIN_GRP_GPIO_2("led3_od", 14, 1, BIT(23), BIT(23), 0, "led"),
 
 };
 
@@ -221,11 +221,11 @@ static const struct armada_37xx_pin_data armada_37xx_pin_sb = {
 };
 
 static inline void armada_37xx_update_reg(unsigned int *reg,
-                                         unsigned int offset)
+                                         unsigned int *offset)
 {
        /* We never have more than 2 registers */
-       if (offset >= GPIO_PER_REG) {
-               offset -= GPIO_PER_REG;
+       if (*offset >= GPIO_PER_REG) {
+               *offset -= GPIO_PER_REG;
                *reg += sizeof(u32);
        }
 }
@@ -376,7 +376,7 @@ static inline void armada_37xx_irq_update_reg(unsigned int *reg,
 {
        int offset = irqd_to_hwirq(d);
 
-       armada_37xx_update_reg(reg, offset);
+       armada_37xx_update_reg(reg, &offset);
 }
 
 static int armada_37xx_gpio_direction_input(struct gpio_chip *chip,
@@ -386,7 +386,7 @@ static int armada_37xx_gpio_direction_input(struct gpio_chip *chip,
        unsigned int reg = OUTPUT_EN;
        unsigned int mask;
 
-       armada_37xx_update_reg(&reg, offset);
+       armada_37xx_update_reg(&reg, &offset);
        mask = BIT(offset);
 
        return regmap_update_bits(info->regmap, reg, mask, 0);
@@ -399,7 +399,7 @@ static int armada_37xx_gpio_get_direction(struct gpio_chip *chip,
        unsigned int reg = OUTPUT_EN;
        unsigned int val, mask;
 
-       armada_37xx_update_reg(&reg, offset);
+       armada_37xx_update_reg(&reg, &offset);
        mask = BIT(offset);
        regmap_read(info->regmap, reg, &val);
 
@@ -413,7 +413,7 @@ static int armada_37xx_gpio_direction_output(struct gpio_chip *chip,
        unsigned int reg = OUTPUT_EN;
        unsigned int mask, val, ret;
 
-       armada_37xx_update_reg(&reg, offset);
+       armada_37xx_update_reg(&reg, &offset);
        mask = BIT(offset);
 
        ret = regmap_update_bits(info->regmap, reg, mask, mask);
@@ -434,7 +434,7 @@ static int armada_37xx_gpio_get(struct gpio_chip *chip, unsigned int offset)
        unsigned int reg = INPUT_VAL;
        unsigned int val, mask;
 
-       armada_37xx_update_reg(&reg, offset);
+       armada_37xx_update_reg(&reg, &offset);
        mask = BIT(offset);
 
        regmap_read(info->regmap, reg, &val);
@@ -449,7 +449,7 @@ static void armada_37xx_gpio_set(struct gpio_chip *chip, unsigned int offset,
        unsigned int reg = OUTPUT_VAL;
        unsigned int mask, val;
 
-       armada_37xx_update_reg(&reg, offset);
+       armada_37xx_update_reg(&reg, &offset);
        mask = BIT(offset);
        val = value ? mask : 0;
 
index 974973777395d13ef1409d2d721c84ec1fac99ba..ccdf0bb2141493bef84dbfbfe90a5dbbdd358c2f 100644 (file)
@@ -585,19 +585,6 @@ static int stmfx_pinctrl_gpio_function_enable(struct stmfx_pinctrl *pctl)
        return stmfx_function_enable(pctl->stmfx, func);
 }
 
-static int stmfx_pinctrl_gpio_init_valid_mask(struct gpio_chip *gc,
-                                             unsigned long *valid_mask,
-                                             unsigned int ngpios)
-{
-       struct stmfx_pinctrl *pctl = gpiochip_get_data(gc);
-       u32 n;
-
-       for_each_clear_bit(n, &pctl->gpio_valid_mask, ngpios)
-               clear_bit(n, valid_mask);
-
-       return 0;
-}
-
 static int stmfx_pinctrl_probe(struct platform_device *pdev)
 {
        struct stmfx *stmfx = dev_get_drvdata(pdev->dev.parent);
@@ -660,7 +647,6 @@ static int stmfx_pinctrl_probe(struct platform_device *pdev)
        pctl->gpio_chip.ngpio = pctl->pctl_desc.npins;
        pctl->gpio_chip.can_sleep = true;
        pctl->gpio_chip.of_node = np;
-       pctl->gpio_chip.init_valid_mask = stmfx_pinctrl_gpio_init_valid_mask;
 
        ret = devm_gpiochip_add_data(pctl->dev, &pctl->gpio_chip, pctl);
        if (ret) {
@@ -705,7 +691,7 @@ static int stmfx_pinctrl_probe(struct platform_device *pdev)
 
 static int stmfx_pinctrl_remove(struct platform_device *pdev)
 {
-       struct stmfx *stmfx = dev_get_platdata(&pdev->dev);
+       struct stmfx *stmfx = dev_get_drvdata(pdev->dev.parent);
 
        return stmfx_function_disable(stmfx,
                                      STMFX_FUNC_GPIO |
index 6ad51aa60c03dd1cf8afd00410a53a459f4d0a35..f877e77d9184be47710178e11ba8d30bf8522259 100644 (file)
@@ -472,14 +472,7 @@ int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state)
                if (err)
                        return err;
 
-               /*
-                * .apply might have to round some values in *state, if possible
-                * read the actually implemented value back.
-                */
-               if (chip->ops->get_state)
-                       chip->ops->get_state(chip, pwm, &pwm->state);
-               else
-                       pwm->state = *state;
+               pwm->state = *state;
        } else {
                /*
                 * FIXME: restore the initial state in case of error.
index 56c38cfae92ca9285d69e6bd6596cd80d95fcae7..1f829edd8ee709c18b0b247c8ca945c607d4d505 100644 (file)
@@ -187,6 +187,7 @@ static int iproc_pwmc_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 static const struct pwm_ops iproc_pwm_ops = {
        .apply = iproc_pwmc_apply,
        .get_state = iproc_pwmc_get_state,
+       .owner = THIS_MODULE,
 };
 
 static int iproc_pwmc_probe(struct platform_device *pdev)
index afe94470b67f7588a28930731d3a4ab6f4d2a331..a46be221dbdcba78160781d223c7ee6e2f2f5665 100644 (file)
@@ -5053,6 +5053,19 @@ regulator_register(const struct regulator_desc *regulator_desc,
 
        init_data = regulator_of_get_init_data(dev, regulator_desc, config,
                                               &rdev->dev.of_node);
+
+       /*
+        * Sometimes not all resources are probed already so we need to take
+        * that into account. This happens most the time if the ena_gpiod comes
+        * from a gpio extender or something else.
+        */
+       if (PTR_ERR(init_data) == -EPROBE_DEFER) {
+               kfree(config);
+               kfree(rdev);
+               ret = -EPROBE_DEFER;
+               goto rinse;
+       }
+
        /*
         * We need to keep track of any GPIO descriptor coming from the
         * device tree until we have handled it over to the core. If the
index 56f3f72d77075e01e61beb9592acbbc221750fd7..710e67081d531e630d972feadfd08b177b6748bd 100644 (file)
@@ -136,7 +136,6 @@ static int da9062_buck_set_mode(struct regulator_dev *rdev, unsigned mode)
 static unsigned da9062_buck_get_mode(struct regulator_dev *rdev)
 {
        struct da9062_regulator *regl = rdev_get_drvdata(rdev);
-       struct regmap_field *field;
        unsigned int val, mode = 0;
        int ret;
 
@@ -158,18 +157,7 @@ static unsigned da9062_buck_get_mode(struct regulator_dev *rdev)
                return REGULATOR_MODE_NORMAL;
        }
 
-       /* Detect current regulator state */
-       ret = regmap_field_read(regl->suspend, &val);
-       if (ret < 0)
-               return 0;
-
-       /* Read regulator mode from proper register, depending on state */
-       if (val)
-               field = regl->suspend_sleep;
-       else
-               field = regl->sleep;
-
-       ret = regmap_field_read(field, &val);
+       ret = regmap_field_read(regl->sleep, &val);
        if (ret < 0)
                return 0;
 
@@ -208,21 +196,9 @@ static int da9062_ldo_set_mode(struct regulator_dev *rdev, unsigned mode)
 static unsigned da9062_ldo_get_mode(struct regulator_dev *rdev)
 {
        struct da9062_regulator *regl = rdev_get_drvdata(rdev);
-       struct regmap_field *field;
        int ret, val;
 
-       /* Detect current regulator state */
-       ret = regmap_field_read(regl->suspend, &val);
-       if (ret < 0)
-               return 0;
-
-       /* Read regulator mode from proper register, depending on state */
-       if (val)
-               field = regl->suspend_sleep;
-       else
-               field = regl->sleep;
-
-       ret = regmap_field_read(field, &val);
+       ret = regmap_field_read(regl->sleep, &val);
        if (ret < 0)
                return 0;
 
@@ -408,10 +384,10 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = {
                        __builtin_ffs((int)DA9062AA_BUCK1_MODE_MASK) - 1,
                        sizeof(unsigned int) * 8 -
                        __builtin_clz((DA9062AA_BUCK1_MODE_MASK)) - 1),
-               .suspend = REG_FIELD(DA9062AA_DVC_1,
-                       __builtin_ffs((int)DA9062AA_VBUCK1_SEL_MASK) - 1,
+               .suspend = REG_FIELD(DA9062AA_BUCK1_CONT,
+                       __builtin_ffs((int)DA9062AA_BUCK1_CONF_MASK) - 1,
                        sizeof(unsigned int) * 8 -
-                       __builtin_clz((DA9062AA_VBUCK1_SEL_MASK)) - 1),
+                       __builtin_clz(DA9062AA_BUCK1_CONF_MASK) - 1),
        },
        {
                .desc.id = DA9061_ID_BUCK2,
@@ -444,10 +420,10 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = {
                        __builtin_ffs((int)DA9062AA_BUCK3_MODE_MASK) - 1,
                        sizeof(unsigned int) * 8 -
                        __builtin_clz((DA9062AA_BUCK3_MODE_MASK)) - 1),
-               .suspend = REG_FIELD(DA9062AA_DVC_1,
-                       __builtin_ffs((int)DA9062AA_VBUCK3_SEL_MASK) - 1,
+               .suspend = REG_FIELD(DA9062AA_BUCK3_CONT,
+                       __builtin_ffs((int)DA9062AA_BUCK3_CONF_MASK) - 1,
                        sizeof(unsigned int) * 8 -
-                       __builtin_clz((DA9062AA_VBUCK3_SEL_MASK)) - 1),
+                       __builtin_clz(DA9062AA_BUCK3_CONF_MASK) - 1),
        },
        {
                .desc.id = DA9061_ID_BUCK3,
@@ -480,10 +456,10 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = {
                        __builtin_ffs((int)DA9062AA_BUCK4_MODE_MASK) - 1,
                        sizeof(unsigned int) * 8 -
                        __builtin_clz((DA9062AA_BUCK4_MODE_MASK)) - 1),
-               .suspend = REG_FIELD(DA9062AA_DVC_1,
-                       __builtin_ffs((int)DA9062AA_VBUCK4_SEL_MASK) - 1,
+               .suspend = REG_FIELD(DA9062AA_BUCK4_CONT,
+                       __builtin_ffs((int)DA9062AA_BUCK4_CONF_MASK) - 1,
                        sizeof(unsigned int) * 8 -
-                       __builtin_clz((DA9062AA_VBUCK4_SEL_MASK)) - 1),
+                       __builtin_clz(DA9062AA_BUCK4_CONF_MASK) - 1),
        },
        {
                .desc.id = DA9061_ID_LDO1,
@@ -509,10 +485,10 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = {
                        sizeof(unsigned int) * 8 -
                        __builtin_clz((DA9062AA_LDO1_SL_B_MASK)) - 1),
                .suspend_vsel_reg = DA9062AA_VLDO1_B,
-               .suspend = REG_FIELD(DA9062AA_DVC_1,
-                       __builtin_ffs((int)DA9062AA_VLDO1_SEL_MASK) - 1,
+               .suspend = REG_FIELD(DA9062AA_LDO1_CONT,
+                       __builtin_ffs((int)DA9062AA_LDO1_CONF_MASK) - 1,
                        sizeof(unsigned int) * 8 -
-                       __builtin_clz((DA9062AA_VLDO1_SEL_MASK)) - 1),
+                       __builtin_clz(DA9062AA_LDO1_CONF_MASK) - 1),
                .oc_event = REG_FIELD(DA9062AA_STATUS_D,
                        __builtin_ffs((int)DA9062AA_LDO1_ILIM_MASK) - 1,
                        sizeof(unsigned int) * 8 -
@@ -542,10 +518,10 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = {
                        sizeof(unsigned int) * 8 -
                        __builtin_clz((DA9062AA_LDO2_SL_B_MASK)) - 1),
                .suspend_vsel_reg = DA9062AA_VLDO2_B,
-               .suspend = REG_FIELD(DA9062AA_DVC_1,
-                       __builtin_ffs((int)DA9062AA_VLDO2_SEL_MASK) - 1,
+               .suspend = REG_FIELD(DA9062AA_LDO2_CONT,
+                       __builtin_ffs((int)DA9062AA_LDO2_CONF_MASK) - 1,
                        sizeof(unsigned int) * 8 -
-                       __builtin_clz((DA9062AA_VLDO2_SEL_MASK)) - 1),
+                       __builtin_clz(DA9062AA_LDO2_CONF_MASK) - 1),
                .oc_event = REG_FIELD(DA9062AA_STATUS_D,
                        __builtin_ffs((int)DA9062AA_LDO2_ILIM_MASK) - 1,
                        sizeof(unsigned int) * 8 -
@@ -575,10 +551,10 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = {
                        sizeof(unsigned int) * 8 -
                        __builtin_clz((DA9062AA_LDO3_SL_B_MASK)) - 1),
                .suspend_vsel_reg = DA9062AA_VLDO3_B,
-               .suspend = REG_FIELD(DA9062AA_DVC_1,
-                       __builtin_ffs((int)DA9062AA_VLDO3_SEL_MASK) - 1,
+               .suspend = REG_FIELD(DA9062AA_LDO3_CONT,
+                       __builtin_ffs((int)DA9062AA_LDO3_CONF_MASK) - 1,
                        sizeof(unsigned int) * 8 -
-                       __builtin_clz((DA9062AA_VLDO3_SEL_MASK)) - 1),
+                       __builtin_clz(DA9062AA_LDO3_CONF_MASK) - 1),
                .oc_event = REG_FIELD(DA9062AA_STATUS_D,
                        __builtin_ffs((int)DA9062AA_LDO3_ILIM_MASK) - 1,
                        sizeof(unsigned int) * 8 -
@@ -608,10 +584,10 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = {
                        sizeof(unsigned int) * 8 -
                        __builtin_clz((DA9062AA_LDO4_SL_B_MASK)) - 1),
                .suspend_vsel_reg = DA9062AA_VLDO4_B,
-               .suspend = REG_FIELD(DA9062AA_DVC_1,
-                       __builtin_ffs((int)DA9062AA_VLDO4_SEL_MASK) - 1,
+               .suspend = REG_FIELD(DA9062AA_LDO4_CONT,
+                       __builtin_ffs((int)DA9062AA_LDO4_CONF_MASK) - 1,
                        sizeof(unsigned int) * 8 -
-                       __builtin_clz((DA9062AA_VLDO4_SEL_MASK)) - 1),
+                       __builtin_clz(DA9062AA_LDO4_CONF_MASK) - 1),
                .oc_event = REG_FIELD(DA9062AA_STATUS_D,
                        __builtin_ffs((int)DA9062AA_LDO4_ILIM_MASK) - 1,
                        sizeof(unsigned int) * 8 -
@@ -652,10 +628,10 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = {
                        __builtin_ffs((int)DA9062AA_BUCK1_MODE_MASK) - 1,
                        sizeof(unsigned int) * 8 -
                        __builtin_clz((DA9062AA_BUCK1_MODE_MASK)) - 1),
-               .suspend = REG_FIELD(DA9062AA_DVC_1,
-                       __builtin_ffs((int)DA9062AA_VBUCK1_SEL_MASK) - 1,
+               .suspend = REG_FIELD(DA9062AA_BUCK1_CONT,
+                       __builtin_ffs((int)DA9062AA_BUCK1_CONF_MASK) - 1,
                        sizeof(unsigned int) * 8 -
-                       __builtin_clz((DA9062AA_VBUCK1_SEL_MASK)) - 1),
+                       __builtin_clz(DA9062AA_BUCK1_CONF_MASK) - 1),
        },
        {
                .desc.id = DA9062_ID_BUCK2,
@@ -688,10 +664,10 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = {
                        __builtin_ffs((int)DA9062AA_BUCK2_MODE_MASK) - 1,
                        sizeof(unsigned int) * 8 -
                        __builtin_clz((DA9062AA_BUCK2_MODE_MASK)) - 1),
-               .suspend = REG_FIELD(DA9062AA_DVC_1,
-                       __builtin_ffs((int)DA9062AA_VBUCK2_SEL_MASK) - 1,
+               .suspend = REG_FIELD(DA9062AA_BUCK2_CONT,
+                       __builtin_ffs((int)DA9062AA_BUCK2_CONF_MASK) - 1,
                        sizeof(unsigned int) * 8 -
-                       __builtin_clz((DA9062AA_VBUCK2_SEL_MASK)) - 1),
+                       __builtin_clz(DA9062AA_BUCK2_CONF_MASK) - 1),
        },
        {
                .desc.id = DA9062_ID_BUCK3,
@@ -724,10 +700,10 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = {
                        __builtin_ffs((int)DA9062AA_BUCK3_MODE_MASK) - 1,
                        sizeof(unsigned int) * 8 -
                        __builtin_clz((DA9062AA_BUCK3_MODE_MASK)) - 1),
-               .suspend = REG_FIELD(DA9062AA_DVC_1,
-                       __builtin_ffs((int)DA9062AA_VBUCK3_SEL_MASK) - 1,
+               .suspend = REG_FIELD(DA9062AA_BUCK3_CONT,
+                       __builtin_ffs((int)DA9062AA_BUCK3_CONF_MASK) - 1,
                        sizeof(unsigned int) * 8 -
-                       __builtin_clz((DA9062AA_VBUCK3_SEL_MASK)) - 1),
+                       __builtin_clz(DA9062AA_BUCK3_CONF_MASK) - 1),
        },
        {
                .desc.id = DA9062_ID_BUCK4,
@@ -760,10 +736,10 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = {
                        __builtin_ffs((int)DA9062AA_BUCK4_MODE_MASK) - 1,
                        sizeof(unsigned int) * 8 -
                        __builtin_clz((DA9062AA_BUCK4_MODE_MASK)) - 1),
-               .suspend = REG_FIELD(DA9062AA_DVC_1,
-                       __builtin_ffs((int)DA9062AA_VBUCK4_SEL_MASK) - 1,
+               .suspend = REG_FIELD(DA9062AA_BUCK4_CONT,
+                       __builtin_ffs((int)DA9062AA_BUCK4_CONF_MASK) - 1,
                        sizeof(unsigned int) * 8 -
-                       __builtin_clz((DA9062AA_VBUCK4_SEL_MASK)) - 1),
+                       __builtin_clz(DA9062AA_BUCK4_CONF_MASK) - 1),
        },
        {
                .desc.id = DA9062_ID_LDO1,
@@ -789,10 +765,10 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = {
                        sizeof(unsigned int) * 8 -
                        __builtin_clz((DA9062AA_LDO1_SL_B_MASK)) - 1),
                .suspend_vsel_reg = DA9062AA_VLDO1_B,
-               .suspend = REG_FIELD(DA9062AA_DVC_1,
-                       __builtin_ffs((int)DA9062AA_VLDO1_SEL_MASK) - 1,
+               .suspend = REG_FIELD(DA9062AA_LDO1_CONT,
+                       __builtin_ffs((int)DA9062AA_LDO1_CONF_MASK) - 1,
                        sizeof(unsigned int) * 8 -
-                       __builtin_clz((DA9062AA_VLDO1_SEL_MASK)) - 1),
+                       __builtin_clz(DA9062AA_LDO1_CONF_MASK) - 1),
                .oc_event = REG_FIELD(DA9062AA_STATUS_D,
                        __builtin_ffs((int)DA9062AA_LDO1_ILIM_MASK) - 1,
                        sizeof(unsigned int) * 8 -
@@ -822,10 +798,10 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = {
                        sizeof(unsigned int) * 8 -
                        __builtin_clz((DA9062AA_LDO2_SL_B_MASK)) - 1),
                .suspend_vsel_reg = DA9062AA_VLDO2_B,
-               .suspend = REG_FIELD(DA9062AA_DVC_1,
-                       __builtin_ffs((int)DA9062AA_VLDO2_SEL_MASK) - 1,
+               .suspend = REG_FIELD(DA9062AA_LDO2_CONT,
+                       __builtin_ffs((int)DA9062AA_LDO2_CONF_MASK) - 1,
                        sizeof(unsigned int) * 8 -
-                       __builtin_clz((DA9062AA_VLDO2_SEL_MASK)) - 1),
+                       __builtin_clz(DA9062AA_LDO2_CONF_MASK) - 1),
                .oc_event = REG_FIELD(DA9062AA_STATUS_D,
                        __builtin_ffs((int)DA9062AA_LDO2_ILIM_MASK) - 1,
                        sizeof(unsigned int) * 8 -
@@ -855,10 +831,10 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = {
                        sizeof(unsigned int) * 8 -
                        __builtin_clz((DA9062AA_LDO3_SL_B_MASK)) - 1),
                .suspend_vsel_reg = DA9062AA_VLDO3_B,
-               .suspend = REG_FIELD(DA9062AA_DVC_1,
-                       __builtin_ffs((int)DA9062AA_VLDO3_SEL_MASK) - 1,
+               .suspend = REG_FIELD(DA9062AA_LDO3_CONT,
+                       __builtin_ffs((int)DA9062AA_LDO3_CONF_MASK) - 1,
                        sizeof(unsigned int) * 8 -
-                       __builtin_clz((DA9062AA_VLDO3_SEL_MASK)) - 1),
+                       __builtin_clz(DA9062AA_LDO3_CONF_MASK) - 1),
                .oc_event = REG_FIELD(DA9062AA_STATUS_D,
                        __builtin_ffs((int)DA9062AA_LDO3_ILIM_MASK) - 1,
                        sizeof(unsigned int) * 8 -
@@ -888,10 +864,10 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = {
                        sizeof(unsigned int) * 8 -
                        __builtin_clz((DA9062AA_LDO4_SL_B_MASK)) - 1),
                .suspend_vsel_reg = DA9062AA_VLDO4_B,
-               .suspend = REG_FIELD(DA9062AA_DVC_1,
-                       __builtin_ffs((int)DA9062AA_VLDO4_SEL_MASK) - 1,
+               .suspend = REG_FIELD(DA9062AA_LDO4_CONT,
+                       __builtin_ffs((int)DA9062AA_LDO4_CONF_MASK) - 1,
                        sizeof(unsigned int) * 8 -
-                       __builtin_clz((DA9062AA_VLDO4_SEL_MASK)) - 1),
+                       __builtin_clz(DA9062AA_LDO4_CONF_MASK) - 1),
                .oc_event = REG_FIELD(DA9062AA_STATUS_D,
                        __builtin_ffs((int)DA9062AA_LDO4_ILIM_MASK) - 1,
                        sizeof(unsigned int) * 8 -
index d90a6fd8cbc7468f67324322443254388eff2d17..f81533070058e29db66991311ec4bbbec0c32636 100644 (file)
@@ -144,8 +144,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct fixed_voltage_config *config;
        struct fixed_voltage_data *drvdata;
-       const struct fixed_dev_type *drvtype =
-               of_match_device(dev->driver->of_match_table, dev)->data;
+       const struct fixed_dev_type *drvtype = of_device_get_match_data(dev);
        struct regulator_config cfg = { };
        enum gpiod_flags gflags;
        int ret;
@@ -177,7 +176,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
        drvdata->desc.type = REGULATOR_VOLTAGE;
        drvdata->desc.owner = THIS_MODULE;
 
-       if (drvtype->has_enable_clock) {
+       if (drvtype && drvtype->has_enable_clock) {
                drvdata->desc.ops = &fixed_voltage_clkenabled_ops;
 
                drvdata->enable_clock = devm_clk_get(dev, NULL);
index ff97cc50f2eb96161a44626062e318477d0187dc..9b05e03ba83056d7beedfb4199eed2febb2b1542 100644 (file)
@@ -210,6 +210,7 @@ static const struct regulator_desc lochnagar_regulators[] = {
 
                .enable_time = 3000,
                .ramp_delay = 1000,
+               .off_on_delay = 15000,
 
                .owner = THIS_MODULE,
        },
index afefb29ce1b0decf8f7ab2105be70ee9f5d59b7a..87637eb6bcbcb9ce2e50278f21bb5dfae315d004 100644 (file)
@@ -231,12 +231,12 @@ static int of_get_regulation_constraints(struct device *dev,
                                        "regulator-off-in-suspend"))
                        suspend_state->enabled = DISABLE_IN_SUSPEND;
 
-               if (!of_property_read_u32(np, "regulator-suspend-min-microvolt",
-                                         &pval))
+               if (!of_property_read_u32(suspend_np,
+                               "regulator-suspend-min-microvolt", &pval))
                        suspend_state->min_uV = pval;
 
-               if (!of_property_read_u32(np, "regulator-suspend-max-microvolt",
-                                         &pval))
+               if (!of_property_read_u32(suspend_np,
+                               "regulator-suspend-max-microvolt", &pval))
                        suspend_state->max_uV = pval;
 
                if (!of_property_read_u32(suspend_np,
@@ -445,11 +445,20 @@ struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
                goto error;
        }
 
-       if (desc->of_parse_cb && desc->of_parse_cb(child, desc, config)) {
-               dev_err(dev,
-                       "driver callback failed to parse DT for regulator %pOFn\n",
-                       child);
-               goto error;
+       if (desc->of_parse_cb) {
+               int ret;
+
+               ret = desc->of_parse_cb(child, desc, config);
+               if (ret) {
+                       if (ret == -EPROBE_DEFER) {
+                               of_node_put(child);
+                               return ERR_PTR(-EPROBE_DEFER);
+                       }
+                       dev_err(dev,
+                               "driver callback failed to parse DT for regulator %pOFn\n",
+                               child);
+                       goto error;
+               }
        }
 
        *node = child;
index df5df1c495adb861322e356d59c091bbf94b342f..689537927f6f7d1bf4543d246490460971913117 100644 (file)
@@ -788,7 +788,13 @@ static int pfuze100_regulator_probe(struct i2c_client *client,
 
                /* SW2~SW4 high bit check and modify the voltage value table */
                if (i >= sw_check_start && i <= sw_check_end) {
-                       regmap_read(pfuze_chip->regmap, desc->vsel_reg, &val);
+                       ret = regmap_read(pfuze_chip->regmap,
+                                               desc->vsel_reg, &val);
+                       if (ret) {
+                               dev_err(&client->dev, "Fails to read from the register.\n");
+                               return ret;
+                       }
+
                        if (val & sw_hi) {
                                if (pfuze_chip->chip_id == PFUZE3000 ||
                                        pfuze_chip->chip_id == PFUZE3001) {
index db6c085da65ecf742daeca83824072ab70a3834b..0246b6f99fb50c4232449def2c005b615e31138d 100644 (file)
@@ -735,8 +735,8 @@ static const struct rpmh_vreg_hw_data pmic5_hfsmps515 = {
 static const struct rpmh_vreg_hw_data pmic5_bob = {
        .regulator_type = VRM,
        .ops = &rpmh_regulator_vrm_bypass_ops,
-       .voltage_range = REGULATOR_LINEAR_RANGE(300000, 0, 135, 32000),
-       .n_voltages = 136,
+       .voltage_range = REGULATOR_LINEAR_RANGE(3000000, 0, 31, 32000),
+       .n_voltages = 32,
        .pmic_mode_map = pmic_mode_map_pmic5_bob,
        .of_map_mode = rpmh_regulator_pmic4_bob_of_map_mode,
 };
index cced1ffb896c1169dba81bde5c9b83a63890ceab..89b9314d64c9dbe5fe152b06c252b1567600857c 100644 (file)
@@ -173,19 +173,14 @@ static int ti_abb_wait_txdone(struct device *dev, struct ti_abb *abb)
        while (timeout++ <= abb->settling_time) {
                status = ti_abb_check_txdone(abb);
                if (status)
-                       break;
+                       return 0;
 
                udelay(1);
        }
 
-       if (timeout > abb->settling_time) {
-               dev_warn_ratelimited(dev,
-                                    "%s:TRANXDONE timeout(%duS) int=0x%08x\n",
-                                    __func__, timeout, readl(abb->int_base));
-               return -ETIMEDOUT;
-       }
-
-       return 0;
+       dev_warn_ratelimited(dev, "%s:TRANXDONE timeout(%duS) int=0x%08x\n",
+                            __func__, timeout, readl(abb->int_base));
+       return -ETIMEDOUT;
 }
 
 /**
@@ -205,19 +200,14 @@ static int ti_abb_clear_all_txdone(struct device *dev, const struct ti_abb *abb)
 
                status = ti_abb_check_txdone(abb);
                if (!status)
-                       break;
+                       return 0;
 
                udelay(1);
        }
 
-       if (timeout > abb->settling_time) {
-               dev_warn_ratelimited(dev,
-                                    "%s:TRANXDONE timeout(%duS) int=0x%08x\n",
-                                    __func__, timeout, readl(abb->int_base));
-               return -ETIMEDOUT;
-       }
-
-       return 0;
+       dev_warn_ratelimited(dev, "%s:TRANXDONE timeout(%duS) int=0x%08x\n",
+                            __func__, timeout, readl(abb->int_base));
+       return -ETIMEDOUT;
 }
 
 /**
index 213ff40dda110e42a641dedd01d79bec80b56b95..3c9a64c1b7a8542cc26d65489c5200bc532047a7 100644 (file)
@@ -76,7 +76,6 @@ static const char *rcdev_name(struct reset_controller_dev *rcdev)
  * of_reset_simple_xlate - translate reset_spec to the reset line number
  * @rcdev: a pointer to the reset controller device
  * @reset_spec: reset line specifier as found in the device tree
- * @flags: a flags pointer to fill in (optional)
  *
  * This simple translation function should be used for reset controllers
  * with 1:1 mapping, where reset lines can be indexed by number without gaps.
@@ -748,6 +747,7 @@ static void reset_control_array_put(struct reset_control_array *resets)
        for (i = 0; i < resets->num_rstcs; i++)
                __reset_control_put_internal(resets->rstc[i]);
        mutex_unlock(&reset_list_mutex);
+       kfree(resets);
 }
 
 /**
@@ -825,9 +825,10 @@ int __device_reset(struct device *dev, bool optional)
 }
 EXPORT_SYMBOL_GPL(__device_reset);
 
-/**
+/*
  * APIs to manage an array of reset controls.
  */
+
 /**
  * of_reset_control_get_count - Count number of resets available with a device
  *
index 45bdb47f84c10b69572c77cbfa1b1f9ca16b1b5a..9157e728a362dbd5589e2fe786fbd585b5f3f8f5 100644 (file)
@@ -522,8 +522,7 @@ static int zcrypt_release(struct inode *inode, struct file *filp)
        if (filp->f_inode->i_cdev == &zcrypt_cdev) {
                struct zcdn_device *zcdndev;
 
-               if (mutex_lock_interruptible(&ap_perms_mutex))
-                       return -ERESTARTSYS;
+               mutex_lock(&ap_perms_mutex);
                zcdndev = find_zcdndev_by_devt(filp->f_inode->i_rdev);
                mutex_unlock(&ap_perms_mutex);
                if (zcdndev) {
index 1b92f3c19ff32f84403f05cead17ae6a0423608f..90cf4691b8c3592c3f7d6dcda993b96da639ca81 100644 (file)
@@ -898,7 +898,7 @@ config SCSI_SNI_53C710
 
 config 53C700_LE_ON_BE
        bool
-       depends on SCSI_LASI700
+       depends on SCSI_LASI700 || SCSI_SNI_53C710
        default y
 
 config SCSI_STEX
index 5f8153c37f77f3393edd428e3c4d2b901040887b..76751d6c7f0d4f13e1347e9562ca63c4e34484d1 100644 (file)
@@ -579,7 +579,6 @@ ch_release(struct inode *inode, struct file *file)
        scsi_changer *ch = file->private_data;
 
        scsi_device_put(ch->device);
-       ch->device = NULL;
        file->private_data = NULL;
        kref_put(&ch->ref, ch_destroy);
        return 0;
index 4971104b1817b5acc42fcd03e040ced92f63c179..f32da0ca529e004f448c6f9803b9c57b145a6609 100644 (file)
@@ -512,6 +512,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg)
        unsigned int tpg_desc_tbl_off;
        unsigned char orig_transition_tmo;
        unsigned long flags;
+       bool transitioning_sense = false;
 
        if (!pg->expiry) {
                unsigned long transition_tmo = ALUA_FAILOVER_TIMEOUT * HZ;
@@ -572,13 +573,19 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg)
                        goto retry;
                }
                /*
-                * Retry on ALUA state transition or if any
-                * UNIT ATTENTION occurred.
+                * If the array returns with 'ALUA state transition'
+                * sense code here it cannot return RTPG data during
+                * transition. So set the state to 'transitioning' directly.
                 */
                if (sense_hdr.sense_key == NOT_READY &&
-                   sense_hdr.asc == 0x04 && sense_hdr.ascq == 0x0a)
-                       err = SCSI_DH_RETRY;
-               else if (sense_hdr.sense_key == UNIT_ATTENTION)
+                   sense_hdr.asc == 0x04 && sense_hdr.ascq == 0x0a) {
+                       transitioning_sense = true;
+                       goto skip_rtpg;
+               }
+               /*
+                * Retry on any other UNIT ATTENTION occurred.
+                */
+               if (sense_hdr.sense_key == UNIT_ATTENTION)
                        err = SCSI_DH_RETRY;
                if (err == SCSI_DH_RETRY &&
                    pg->expiry != 0 && time_before(jiffies, pg->expiry)) {
@@ -666,7 +673,11 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg)
                off = 8 + (desc[7] * 4);
        }
 
+ skip_rtpg:
        spin_lock_irqsave(&pg->lock, flags);
+       if (transitioning_sense)
+               pg->state = SCSI_ACCESS_STATE_TRANSITIONING;
+
        sdev_printk(KERN_INFO, sdev,
                    "%s: port group %02x state %c %s supports %c%c%c%c%c%c%c\n",
                    ALUA_DH_NAME, pg->group_id, print_alua_state(pg->state),
index ac39ed79ccaa15cebf9a3b7d86230130f4d5b076..216e557f703e6c0b466fc29dddc05364b3127bf2 100644 (file)
@@ -5477,6 +5477,8 @@ static int hpsa_ciss_submit(struct ctlr_info *h,
                return SCSI_MLQUEUE_HOST_BUSY;
        }
 
+       c->device = dev;
+
        enqueue_cmd_and_start_io(h, c);
        /* the cmd'll come back via intr handler in complete_scsi_command()  */
        return 0;
@@ -5548,6 +5550,7 @@ static int hpsa_ioaccel_submit(struct ctlr_info *h,
                hpsa_cmd_init(h, c->cmdindex, c);
                c->cmd_type = CMD_SCSI;
                c->scsi_cmd = cmd;
+               c->device = dev;
                rc = hpsa_scsi_ioaccel_raid_map(h, c);
                if (rc < 0)     /* scsi_dma_map failed. */
                        rc = SCSI_MLQUEUE_HOST_BUSY;
@@ -5555,6 +5558,7 @@ static int hpsa_ioaccel_submit(struct ctlr_info *h,
                hpsa_cmd_init(h, c->cmdindex, c);
                c->cmd_type = CMD_SCSI;
                c->scsi_cmd = cmd;
+               c->device = dev;
                rc = hpsa_scsi_ioaccel_direct_map(h, c);
                if (rc < 0)     /* scsi_dma_map failed. */
                        rc = SCSI_MLQUEUE_HOST_BUSY;
index e91377a4cafebad115a84465f02ebd59bc5140db..e8813d26e59415b1a584900c2ed7772438a74bc3 100644 (file)
@@ -9055,7 +9055,6 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
                }
        }
 
-#if defined(BUILD_NVME)
        /* Clear NVME stats */
        if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) {
                for (idx = 0; idx < phba->cfg_hdw_queue; idx++) {
@@ -9063,7 +9062,6 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
                               sizeof(phba->sli4_hba.hdwq[idx].nvme_cstat));
                }
        }
-#endif
 
        /* Clear SCSI stats */
        if (phba->cfg_enable_fc4_type & LPFC_ENABLE_FCP) {
index f4b879d25fe9d33229d40a5ab5675577b539c45a..fc6e4546d738a59ab1be40271f406c520437dca2 100644 (file)
@@ -851,9 +851,9 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
 
        if (!(vport->fc_flag & FC_PT2PT)) {
                /* Check config parameter use-adisc or FCP-2 */
-               if ((vport->cfg_use_adisc && (vport->fc_flag & FC_RSCN_MODE)) ||
+               if (vport->cfg_use_adisc && ((vport->fc_flag & FC_RSCN_MODE) ||
                    ((ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) &&
-                    (ndlp->nlp_type & NLP_FCP_TARGET))) {
+                    (ndlp->nlp_type & NLP_FCP_TARGET)))) {
                        spin_lock_irq(shost->host_lock);
                        ndlp->nlp_flag |= NLP_NPR_ADISC;
                        spin_unlock_irq(shost->host_lock);
index fe1097666de4375e7dfe9a0febf4ddf7d9cff026..6822cd9ff8f1ef460dea74f002d52bb7ef043b28 100644 (file)
@@ -528,7 +528,6 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba,
                        list_del_init(&psb->list);
                        psb->exch_busy = 0;
                        psb->status = IOSTAT_SUCCESS;
-#ifdef BUILD_NVME
                        if (psb->cur_iocbq.iocb_flag == LPFC_IO_NVME) {
                                qp->abts_nvme_io_bufs--;
                                spin_unlock(&qp->abts_io_buf_list_lock);
@@ -536,7 +535,6 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba,
                                lpfc_sli4_nvme_xri_aborted(phba, axri, psb);
                                return;
                        }
-#endif
                        qp->abts_scsi_io_bufs--;
                        spin_unlock(&qp->abts_io_buf_list_lock);
 
index a0c6945b81392e1f07e02934f9702e0ac783197f..614f78dddafe0f0ae1e78b0f22beafc081b57993 100644 (file)
@@ -7866,7 +7866,7 @@ lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba)
        if (sli4_hba->hdwq) {
                for (eqidx = 0; eqidx < phba->cfg_irq_chann; eqidx++) {
                        eq = phba->sli4_hba.hba_eq_hdl[eqidx].eq;
-                       if (eq->queue_id == sli4_hba->mbx_cq->assoc_qid) {
+                       if (eq && eq->queue_id == sli4_hba->mbx_cq->assoc_qid) {
                                fpeq = eq;
                                break;
                        }
index 30bafd9d21e984461b237651358196a26eb8d514..7259bce85e0e3e54be6ed45d8cd82593685c7390 100644 (file)
@@ -440,9 +440,6 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
                valid = 0;
                if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0)
                        valid = 1;
-               else if (start == (ha->flt_region_boot * 4) ||
-                   start == (ha->flt_region_fw * 4))
-                       valid = 1;
                else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha))
                        valid = 1;
                if (!valid) {
@@ -489,8 +486,10 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
                    "Writing flash region -- 0x%x/0x%x.\n",
                    ha->optrom_region_start, ha->optrom_region_size);
 
-               ha->isp_ops->write_optrom(vha, ha->optrom_buffer,
+               rval = ha->isp_ops->write_optrom(vha, ha->optrom_buffer,
                    ha->optrom_region_start, ha->optrom_region_size);
+               if (rval)
+                       rval = -EIO;
                break;
        default:
                rval = -EINVAL;
index 28d587a89ba61efcab7a497e8c9319a7b9272359..99f0a1a08143e0864e0ba69718945fe538ffd447 100644 (file)
@@ -253,7 +253,7 @@ qla2x00_process_els(struct bsg_job *bsg_job)
        srb_t *sp;
        const char *type;
        int req_sg_cnt, rsp_sg_cnt;
-       int rval =  (DRIVER_ERROR << 16);
+       int rval =  (DID_ERROR << 16);
        uint16_t nextlid = 0;
 
        if (bsg_request->msgcode == FC_BSG_RPT_ELS) {
@@ -432,7 +432,7 @@ qla2x00_process_ct(struct bsg_job *bsg_job)
        struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
        scsi_qla_host_t *vha = shost_priv(host);
        struct qla_hw_data *ha = vha->hw;
-       int rval = (DRIVER_ERROR << 16);
+       int rval = (DID_ERROR << 16);
        int req_sg_cnt, rsp_sg_cnt;
        uint16_t loop_id;
        struct fc_port *fcport;
@@ -1950,7 +1950,7 @@ qlafx00_mgmt_cmd(struct bsg_job *bsg_job)
        struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
        scsi_qla_host_t *vha = shost_priv(host);
        struct qla_hw_data *ha = vha->hw;
-       int rval = (DRIVER_ERROR << 16);
+       int rval = (DID_ERROR << 16);
        struct qla_mt_iocb_rqst_fx00 *piocb_rqst;
        srb_t *sp;
        int req_sg_cnt = 0, rsp_sg_cnt = 0;
index 1cc6913f76c4745242b72cc7aa71e5edaae54519..4a1f21c11758ea5b8ee0e2222bfb4f05fc49dc84 100644 (file)
@@ -702,6 +702,7 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
                mcp->mb[2] = LSW(risc_addr);
                mcp->mb[3] = 0;
                mcp->mb[4] = 0;
+               mcp->mb[11] = 0;
                ha->flags.using_lr_setting = 0;
                if (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) ||
                    IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
@@ -746,7 +747,7 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
                if (ha->flags.exchoffld_enabled)
                        mcp->mb[4] |= ENABLE_EXCHANGE_OFFLD;
 
-               mcp->out_mb |= MBX_4|MBX_3|MBX_2|MBX_1;
+               mcp->out_mb |= MBX_4 | MBX_3 | MBX_2 | MBX_1 | MBX_11;
                mcp->in_mb |= MBX_3 | MBX_2 | MBX_1;
        } else {
                mcp->mb[1] = LSW(risc_addr);
index 3568031c6504426b3edb6b2739a81fd169523730..337162ac3a7716c46bc18774410f7a1796e2b33a 100644 (file)
@@ -3224,6 +3224,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
            req->req_q_in, req->req_q_out, rsp->rsp_q_in, rsp->rsp_q_out);
 
        ha->wq = alloc_workqueue("qla2xxx_wq", 0, 0);
+       if (unlikely(!ha->wq)) {
+               ret = -ENOMEM;
+               goto probe_failed;
+       }
 
        if (ha->isp_ops->initialize_adapter(base_vha)) {
                ql_log(ql_log_fatal, base_vha, 0x00d6,
@@ -3531,6 +3535,10 @@ qla2x00_shutdown(struct pci_dev *pdev)
                qla2x00_try_to_stop_firmware(vha);
        }
 
+       /* Disable timer */
+       if (vha->timer_active)
+               qla2x00_stop_timer(vha);
+
        /* Turn adapter off line */
        vha->flags.online = 0;
 
index 64c96c7828ee1056042da4a913d9f3f2b9506506..6d7362e7367edc58a757cd56d3b13c5b644883b3 100644 (file)
@@ -730,6 +730,14 @@ sdev_store_delete(struct device *dev, struct device_attribute *attr,
                  const char *buf, size_t count)
 {
        struct kernfs_node *kn;
+       struct scsi_device *sdev = to_scsi_device(dev);
+
+       /*
+        * We need to try to get module, avoiding the module been removed
+        * during delete.
+        */
+       if (scsi_device_get(sdev))
+               return -ENODEV;
 
        kn = sysfs_break_active_protection(&dev->kobj, &attr->attr);
        WARN_ON_ONCE(!kn);
@@ -744,9 +752,10 @@ sdev_store_delete(struct device *dev, struct device_attribute *attr,
         * state into SDEV_DEL.
         */
        device_remove_file(dev, attr);
-       scsi_remove_device(to_scsi_device(dev));
+       scsi_remove_device(sdev);
        if (kn)
                sysfs_unbreak_active_protection(kn);
+       scsi_device_put(sdev);
        return count;
 };
 static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete);
index 03163ac5fe9583362491efa831275c77a59e6122..ebb40160539f52e1c6ee65802fb9dd731868ed89 100644 (file)
@@ -1166,11 +1166,12 @@ static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd)
        sector_t lba = sectors_to_logical(sdp, blk_rq_pos(rq));
        sector_t threshold;
        unsigned int nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq));
-       bool dif, dix;
        unsigned int mask = logical_to_sectors(sdp, 1) - 1;
        bool write = rq_data_dir(rq) == WRITE;
        unsigned char protect, fua;
        blk_status_t ret;
+       unsigned int dif;
+       bool dix;
 
        ret = scsi_init_io(cmd);
        if (ret != BLK_STS_OK)
index aef4881d8e21588f7698aeccb982ae416e6972ff..a85d52b5dc32094d04219b548619c2b7ea1de23f 100644 (file)
@@ -66,10 +66,8 @@ static int snirm710_probe(struct platform_device *dev)
 
        base = res->start;
        hostdata = kzalloc(sizeof(*hostdata), GFP_KERNEL);
-       if (!hostdata) {
-               dev_printk(KERN_ERR, dev, "Failed to allocate host data\n");
+       if (!hostdata)
                return -ENOMEM;
-       }
 
        hostdata->dev = &dev->dev;
        dma_set_mask(&dev->dev, DMA_BIT_MASK(32));
index a9344eb4e047f1e73c28212024c1e8dcefb19228..dc2f6d2b46edc306f8696cd4471358a86dd6df49 100644 (file)
@@ -98,6 +98,8 @@ static int ufs_bsg_request(struct bsg_job *job)
 
        bsg_reply->reply_payload_rcv_len = 0;
 
+       pm_runtime_get_sync(hba->dev);
+
        msgcode = bsg_request->msgcode;
        switch (msgcode) {
        case UPIU_TRANSACTION_QUERY_REQ:
@@ -135,6 +137,8 @@ static int ufs_bsg_request(struct bsg_job *job)
                break;
        }
 
+       pm_runtime_put_sync(hba->dev);
+
        if (!desc_buff)
                goto out;
 
index d9231bd3c691aac7388cb76c09eea9f782464112..98b9d9a902ae3fba58d2f12ac52a0deaa71265e9 100644 (file)
@@ -249,13 +249,13 @@ static struct genpd_power_state imx6_pm_domain_pu_state = {
 };
 
 static struct imx_pm_domain imx_gpc_domains[] = {
-       [GPC_PGC_DOMAIN_ARM] {
+       [GPC_PGC_DOMAIN_ARM] {
                .base = {
                        .name = "ARM",
                        .flags = GENPD_FLAG_ALWAYS_ON,
                },
        },
-       [GPC_PGC_DOMAIN_PU] {
+       [GPC_PGC_DOMAIN_PU] {
                .base = {
                        .name = "PU",
                        .power_off = imx6_pm_domain_power_off,
@@ -266,7 +266,7 @@ static struct imx_pm_domain imx_gpc_domains[] = {
                .reg_offs = 0x260,
                .cntr_pdn_bit = 0,
        },
-       [GPC_PGC_DOMAIN_DISPLAY] {
+       [GPC_PGC_DOMAIN_DISPLAY] {
                .base = {
                        .name = "DISPLAY",
                        .power_off = imx6_pm_domain_power_off,
@@ -275,7 +275,7 @@ static struct imx_pm_domain imx_gpc_domains[] = {
                .reg_offs = 0x240,
                .cntr_pdn_bit = 4,
        },
-       [GPC_PGC_DOMAIN_PCI] {
+       [GPC_PGC_DOMAIN_PCI] {
                .base = {
                        .name = "PCI",
                        .power_off = imx6_pm_domain_power_off,
index 50831ebf126afcdc2ea26e5c2d1db98e05cd0afa..c68882eb80f778e93bf7b1e29cc18b8e06f44d7a 100644 (file)
@@ -46,7 +46,7 @@ static ssize_t soc_uid_show(struct device *dev,
        hdr->func = IMX_SC_MISC_FUNC_UNIQUE_ID;
        hdr->size = 1;
 
-       ret = imx_scu_call_rpc(soc_ipc_handle, &msg, false);
+       ret = imx_scu_call_rpc(soc_ipc_handle, &msg, true);
        if (ret) {
                pr_err("%s: get soc uid failed, ret %d\n", __func__, ret);
                return ret;
index f518273cfbe3cbcd4cc4ed0c462550a3c9e11d03..c8c80df090d13f36affe45241575b398aa2d7339 100644 (file)
@@ -5,6 +5,7 @@
 
 menuconfig SOUNDWIRE
        tristate "SoundWire support"
+       depends on ACPI || OF
        help
          SoundWire is a 2-Pin interface with data and clock line ratified
          by the MIPI Alliance. SoundWire is used for transporting data
index f1e38a293967052831fceaf440030581ded8d5db..13c54eac0cc3e2b3cb609fb907c2e832bbe711ae 100644 (file)
@@ -900,7 +900,7 @@ static int intel_register_dai(struct sdw_intel *sdw)
        /* Create PCM DAIs */
        stream = &cdns->pcm;
 
-       ret = intel_create_dai(cdns, dais, INTEL_PDI_IN, stream->num_in,
+       ret = intel_create_dai(cdns, dais, INTEL_PDI_IN, cdns->pcm.num_in,
                               off, stream->num_ch_in, true);
        if (ret)
                return ret;
@@ -931,7 +931,7 @@ static int intel_register_dai(struct sdw_intel *sdw)
        if (ret)
                return ret;
 
-       off += cdns->pdm.num_bd;
+       off += cdns->pdm.num_out;
        ret = intel_create_dai(cdns, dais, INTEL_PDI_BD, cdns->pdm.num_bd,
                               off, stream->num_ch_bd, false);
        if (ret)
index 48a63ca130d2b2db4ccce74193f76e71c27f571c..6473fa602f82cc81b745f97cca97df1323618939 100644 (file)
@@ -128,7 +128,8 @@ int sdw_of_find_slaves(struct sdw_bus *bus)
        struct device_node *node;
 
        for_each_child_of_node(bus->dev->of_node, node) {
-               int link_id, sdw_version, ret, len;
+               int link_id, ret, len;
+               unsigned int sdw_version;
                const char *compat = NULL;
                struct sdw_slave_id id;
                const __be32 *addr;
index 6f1fa4c849a1685f8a28a528eac6a0a787d8bca1..927d29eb92c6f2bbbc0d0f1ca4b5ae9650a05f97 100644 (file)
@@ -125,4 +125,6 @@ source "drivers/staging/exfat/Kconfig"
 
 source "drivers/staging/qlge/Kconfig"
 
+source "drivers/staging/vboxsf/Kconfig"
+
 endif # STAGING
index a90f9b308c8dea54f302704bdde1617bdc08d173..f01f04199073d047cd2f92b910243a387c4ca3e4 100644 (file)
@@ -53,3 +53,4 @@ obj-$(CONFIG_UWB)             += uwb/
 obj-$(CONFIG_USB_WUSB)         += wusbcore/
 obj-$(CONFIG_EXFAT_FS)         += exfat/
 obj-$(CONFIG_QLGE)             += qlge/
+obj-$(CONFIG_VBOXSF_FS)                += vboxsf/
diff --git a/drivers/staging/vboxsf/Kconfig b/drivers/staging/vboxsf/Kconfig
new file mode 100644 (file)
index 0000000..b84586a
--- /dev/null
@@ -0,0 +1,10 @@
+config VBOXSF_FS
+       tristate "VirtualBox guest shared folder (vboxsf) support"
+       depends on X86 && VBOXGUEST
+       select NLS
+       help
+         VirtualBox hosts can share folders with guests, this driver
+         implements the Linux-guest side of this allowing folders exported
+         by the host to be mounted under Linux.
+
+         If you want to use shared folders in VirtualBox guests, answer Y or M.
diff --git a/drivers/staging/vboxsf/Makefile b/drivers/staging/vboxsf/Makefile
new file mode 100644 (file)
index 0000000..9e4328e
--- /dev/null
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: MIT
+
+obj-$(CONFIG_VBOXSF_FS) += vboxsf.o
+
+vboxsf-y := dir.o file.o utils.o vboxsf_wrappers.o super.o
diff --git a/drivers/staging/vboxsf/TODO b/drivers/staging/vboxsf/TODO
new file mode 100644 (file)
index 0000000..8b9193d
--- /dev/null
@@ -0,0 +1,7 @@
+TODO:
+- Find a file-system developer to review this and give their Reviewed-By
+- Address any items coming up during review
+- Move to fs/vboxfs
+
+Please send any patches to Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+and Hans de Goede <hdegoede@redhat.com>
diff --git a/drivers/staging/vboxsf/dir.c b/drivers/staging/vboxsf/dir.c
new file mode 100644 (file)
index 0000000..f260b5c
--- /dev/null
@@ -0,0 +1,418 @@
+// SPDX-License-Identifier: MIT
+/*
+ * VirtualBox Guest Shared Folders support: Directory inode and file operations
+ *
+ * Copyright (C) 2006-2018 Oracle Corporation
+ */
+
+#include <linux/namei.h>
+#include <linux/vbox_utils.h>
+#include "vfsmod.h"
+
+static int vboxsf_dir_open(struct inode *inode, struct file *file)
+{
+       struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb);
+       struct shfl_createparms params = {};
+       struct vboxsf_dir_info *sf_d;
+       int err;
+
+       sf_d = vboxsf_dir_info_alloc();
+       if (!sf_d)
+               return -ENOMEM;
+
+       params.handle = SHFL_HANDLE_NIL;
+       params.create_flags = SHFL_CF_DIRECTORY | SHFL_CF_ACT_OPEN_IF_EXISTS |
+                             SHFL_CF_ACT_FAIL_IF_NEW | SHFL_CF_ACCESS_READ;
+
+       err = vboxsf_create_at_dentry(file_dentry(file), &params);
+       if (err)
+               goto err_free_dir_info;
+
+       if (params.result != SHFL_FILE_EXISTS) {
+               err = -ENOENT;
+               goto err_close;
+       }
+
+       err = vboxsf_dir_read_all(sbi, sf_d, params.handle);
+       if (err)
+               goto err_close;
+
+       vboxsf_close(sbi->root, params.handle);
+       file->private_data = sf_d;
+       return 0;
+
+err_close:
+       vboxsf_close(sbi->root, params.handle);
+err_free_dir_info:
+       vboxsf_dir_info_free(sf_d);
+       return err;
+}
+
+static int vboxsf_dir_release(struct inode *inode, struct file *file)
+{
+       if (file->private_data)
+               vboxsf_dir_info_free(file->private_data);
+
+       return 0;
+}
+
+static unsigned int vboxsf_get_d_type(u32 mode)
+{
+       unsigned int d_type;
+
+       switch (mode & SHFL_TYPE_MASK) {
+       case SHFL_TYPE_FIFO:
+               d_type = DT_FIFO;
+               break;
+       case SHFL_TYPE_DEV_CHAR:
+               d_type = DT_CHR;
+               break;
+       case SHFL_TYPE_DIRECTORY:
+               d_type = DT_DIR;
+               break;
+       case SHFL_TYPE_DEV_BLOCK:
+               d_type = DT_BLK;
+               break;
+       case SHFL_TYPE_FILE:
+               d_type = DT_REG;
+               break;
+       case SHFL_TYPE_SYMLINK:
+               d_type = DT_LNK;
+               break;
+       case SHFL_TYPE_SOCKET:
+               d_type = DT_SOCK;
+               break;
+       case SHFL_TYPE_WHITEOUT:
+               d_type = DT_WHT;
+               break;
+       default:
+               d_type = DT_UNKNOWN;
+               break;
+       }
+       return d_type;
+}
+
+static bool vboxsf_dir_emit(struct file *dir, struct dir_context *ctx)
+{
+       struct vboxsf_sbi *sbi = VBOXSF_SBI(file_inode(dir)->i_sb);
+       struct vboxsf_dir_info *sf_d = dir->private_data;
+       struct shfl_dirinfo *info;
+       struct vboxsf_dir_buf *b;
+       unsigned int d_type;
+       loff_t i, cur = 0;
+       ino_t fake_ino;
+       size_t size;
+       int err;
+
+       list_for_each_entry(b, &sf_d->info_list, head) {
+try_next_entry:
+               if (ctx->pos >= cur + b->entries) {
+                       cur += b->entries;
+                       continue;
+               }
+
+               /*
+                * Note the vboxsf_dir_info objects we are iterating over here
+                * are variable sized, so the info pointer may end up being
+                * unaligned. This is how we get the data from the host.
+                * Since vboxsf is only supported on x86 machines this is not
+                * a problem.
+                */
+               for (i = 0, info = b->buf; i < ctx->pos - cur; i++) {
+                       size = offsetof(struct shfl_dirinfo, name.string) +
+                              info->name.size;
+                       info = (struct shfl_dirinfo *)((uintptr_t)info + size);
+               }
+
+               /* Info now points to the right entry, emit it. */
+               d_type = vboxsf_get_d_type(info->info.attr.mode);
+
+               /*
+                * On 32 bit systems pos is 64 signed, while ino is 32 bit
+                * unsigned so fake_ino may overflow, check for this.
+                */
+               if ((ino_t)(ctx->pos + 1) != (u64)(ctx->pos + 1)) {
+                       vbg_err("vboxsf: fake ino overflow, truncating dir\n");
+                       return false;
+               }
+               fake_ino = ctx->pos + 1;
+
+               if (sbi->nls) {
+                       char d_name[NAME_MAX];
+
+                       err = vboxsf_nlscpy(sbi, d_name, NAME_MAX,
+                                           info->name.string.utf8,
+                                           info->name.length);
+                       if (err) {
+                               /* skip erroneous entry and proceed */
+                               ctx->pos += 1;
+                               goto try_next_entry;
+                       }
+
+                       return dir_emit(ctx, d_name, strlen(d_name),
+                                       fake_ino, d_type);
+               }
+
+               return dir_emit(ctx, info->name.string.utf8, info->name.length,
+                               fake_ino, d_type);
+       }
+
+       return false;
+}
+
+static int vboxsf_dir_iterate(struct file *dir, struct dir_context *ctx)
+{
+       bool keep_iterating;
+
+       for (keep_iterating = true; keep_iterating; ctx->pos += 1)
+               keep_iterating = vboxsf_dir_emit(dir, ctx);
+
+       return 0;
+}
+
+const struct file_operations vboxsf_dir_fops = {
+       .open = vboxsf_dir_open,
+       .iterate = vboxsf_dir_iterate,
+       .release = vboxsf_dir_release,
+       .read = generic_read_dir,
+       .llseek = generic_file_llseek,
+};
+
+/*
+ * This is called during name resolution/lookup to check if the @dentry in
+ * the cache is still valid. the job is handled by vboxsf_inode_revalidate.
+ */
+static int vboxsf_dentry_revalidate(struct dentry *dentry, unsigned int flags)
+{
+       if (flags & LOOKUP_RCU)
+               return -ECHILD;
+
+       if (d_really_is_positive(dentry))
+               return vboxsf_inode_revalidate(dentry) == 0;
+       else
+               return vboxsf_stat_dentry(dentry, NULL) == -ENOENT;
+}
+
+const struct dentry_operations vboxsf_dentry_ops = {
+       .d_revalidate = vboxsf_dentry_revalidate
+};
+
+/* iops */
+
+static struct dentry *vboxsf_dir_lookup(struct inode *parent,
+                                       struct dentry *dentry,
+                                       unsigned int flags)
+{
+       struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb);
+       struct shfl_fsobjinfo fsinfo;
+       struct inode *inode;
+       int err;
+
+       dentry->d_time = jiffies;
+
+       err = vboxsf_stat_dentry(dentry, &fsinfo);
+       if (err) {
+               inode = (err == -ENOENT) ? NULL : ERR_PTR(err);
+       } else {
+               inode = vboxsf_new_inode(parent->i_sb);
+               if (!IS_ERR(inode))
+                       vboxsf_init_inode(sbi, inode, &fsinfo);
+       }
+
+       return d_splice_alias(inode, dentry);
+}
+
+static int vboxsf_dir_instantiate(struct inode *parent, struct dentry *dentry,
+                                 struct shfl_fsobjinfo *info)
+{
+       struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb);
+       struct vboxsf_inode *sf_i;
+       struct inode *inode;
+
+       inode = vboxsf_new_inode(parent->i_sb);
+       if (IS_ERR(inode))
+               return PTR_ERR(inode);
+
+       sf_i = VBOXSF_I(inode);
+       /* The host may have given us different attr then requested */
+       sf_i->force_restat = 1;
+       vboxsf_init_inode(sbi, inode, info);
+
+       d_instantiate(dentry, inode);
+
+       return 0;
+}
+
+static int vboxsf_dir_create(struct inode *parent, struct dentry *dentry,
+                            umode_t mode, int is_dir)
+{
+       struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent);
+       struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb);
+       struct shfl_createparms params = {};
+       int err;
+
+       params.handle = SHFL_HANDLE_NIL;
+       params.create_flags = SHFL_CF_ACT_CREATE_IF_NEW |
+                             SHFL_CF_ACT_FAIL_IF_EXISTS |
+                             SHFL_CF_ACCESS_READWRITE |
+                             (is_dir ? SHFL_CF_DIRECTORY : 0);
+       params.info.attr.mode = (mode & 0777) |
+                               (is_dir ? SHFL_TYPE_DIRECTORY : SHFL_TYPE_FILE);
+       params.info.attr.additional = SHFLFSOBJATTRADD_NOTHING;
+
+       err = vboxsf_create_at_dentry(dentry, &params);
+       if (err)
+               return err;
+
+       if (params.result != SHFL_FILE_CREATED)
+               return -EPERM;
+
+       vboxsf_close(sbi->root, params.handle);
+
+       err = vboxsf_dir_instantiate(parent, dentry, &params.info);
+       if (err)
+               return err;
+
+       /* parent directory access/change time changed */
+       sf_parent_i->force_restat = 1;
+
+       return 0;
+}
+
+static int vboxsf_dir_mkfile(struct inode *parent, struct dentry *dentry,
+                            umode_t mode, bool excl)
+{
+       return vboxsf_dir_create(parent, dentry, mode, 0);
+}
+
+static int vboxsf_dir_mkdir(struct inode *parent, struct dentry *dentry,
+                           umode_t mode)
+{
+       return vboxsf_dir_create(parent, dentry, mode, 1);
+}
+
+static int vboxsf_dir_unlink(struct inode *parent, struct dentry *dentry)
+{
+       struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb);
+       struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent);
+       struct inode *inode = d_inode(dentry);
+       struct shfl_string *path;
+       u32 flags;
+       int err;
+
+       if (S_ISDIR(inode->i_mode))
+               flags = SHFL_REMOVE_DIR;
+       else
+               flags = SHFL_REMOVE_FILE;
+
+       if (S_ISLNK(inode->i_mode))
+               flags |= SHFL_REMOVE_SYMLINK;
+
+       path = vboxsf_path_from_dentry(sbi, dentry);
+       if (IS_ERR(path))
+               return PTR_ERR(path);
+
+       err = vboxsf_remove(sbi->root, path, flags);
+       __putname(path);
+       if (err)
+               return err;
+
+       /* parent directory access/change time changed */
+       sf_parent_i->force_restat = 1;
+
+       return 0;
+}
+
+static int vboxsf_dir_rename(struct inode *old_parent,
+                            struct dentry *old_dentry,
+                            struct inode *new_parent,
+                            struct dentry *new_dentry,
+                            unsigned int flags)
+{
+       struct vboxsf_sbi *sbi = VBOXSF_SBI(old_parent->i_sb);
+       struct vboxsf_inode *sf_old_parent_i = VBOXSF_I(old_parent);
+       struct vboxsf_inode *sf_new_parent_i = VBOXSF_I(new_parent);
+       u32 shfl_flags = SHFL_RENAME_FILE | SHFL_RENAME_REPLACE_IF_EXISTS;
+       struct shfl_string *old_path, *new_path;
+       int err;
+
+       if (flags)
+               return -EINVAL;
+
+       old_path = vboxsf_path_from_dentry(sbi, old_dentry);
+       if (IS_ERR(old_path))
+               return PTR_ERR(old_path);
+
+       new_path = vboxsf_path_from_dentry(sbi, new_dentry);
+       if (IS_ERR(new_path)) {
+               err = PTR_ERR(new_path);
+               goto err_put_old_path;
+       }
+
+       if (d_inode(old_dentry)->i_mode & S_IFDIR)
+               shfl_flags = 0;
+
+       err = vboxsf_rename(sbi->root, old_path, new_path, shfl_flags);
+       if (err == 0) {
+               /* parent directories access/change time changed */
+               sf_new_parent_i->force_restat = 1;
+               sf_old_parent_i->force_restat = 1;
+       }
+
+       __putname(new_path);
+err_put_old_path:
+       __putname(old_path);
+       return err;
+}
+
+static int vboxsf_dir_symlink(struct inode *parent, struct dentry *dentry,
+                             const char *symname)
+{
+       struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent);
+       struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb);
+       int symname_size = strlen(symname) + 1;
+       struct shfl_string *path, *ssymname;
+       struct shfl_fsobjinfo info;
+       int err;
+
+       path = vboxsf_path_from_dentry(sbi, dentry);
+       if (IS_ERR(path))
+               return PTR_ERR(path);
+
+       ssymname = kmalloc(SHFLSTRING_HEADER_SIZE + symname_size, GFP_KERNEL);
+       if (!ssymname) {
+               __putname(path);
+               return -ENOMEM;
+       }
+       ssymname->length = symname_size - 1;
+       ssymname->size = symname_size;
+       memcpy(ssymname->string.utf8, symname, symname_size);
+
+       err = vboxsf_symlink(sbi->root, path, ssymname, &info);
+       kfree(ssymname);
+       __putname(path);
+       if (err) {
+               /* -EROFS means symlinks are note support -> -EPERM */
+               return (err == -EROFS) ? -EPERM : err;
+       }
+
+       err = vboxsf_dir_instantiate(parent, dentry, &info);
+       if (err)
+               return err;
+
+       /* parent directory access/change time changed */
+       sf_parent_i->force_restat = 1;
+       return 0;
+}
+
+const struct inode_operations vboxsf_dir_iops = {
+       .lookup  = vboxsf_dir_lookup,
+       .create  = vboxsf_dir_mkfile,
+       .mkdir   = vboxsf_dir_mkdir,
+       .rmdir   = vboxsf_dir_unlink,
+       .unlink  = vboxsf_dir_unlink,
+       .rename  = vboxsf_dir_rename,
+       .symlink = vboxsf_dir_symlink,
+       .getattr = vboxsf_getattr,
+       .setattr = vboxsf_setattr,
+};
diff --git a/drivers/staging/vboxsf/file.c b/drivers/staging/vboxsf/file.c
new file mode 100644 (file)
index 0000000..4b61ccf
--- /dev/null
@@ -0,0 +1,370 @@
+// SPDX-License-Identifier: MIT
+/*
+ * VirtualBox Guest Shared Folders support: Regular file inode and file ops.
+ *
+ * Copyright (C) 2006-2018 Oracle Corporation
+ */
+
+#include <linux/mm.h>
+#include <linux/page-flags.h>
+#include <linux/pagemap.h>
+#include <linux/highmem.h>
+#include <linux/sizes.h>
+#include "vfsmod.h"
+
+struct vboxsf_handle {
+       u64 handle;
+       u32 root;
+       u32 access_flags;
+       struct kref refcount;
+       struct list_head head;
+};
+
+static int vboxsf_file_open(struct inode *inode, struct file *file)
+{
+       struct vboxsf_inode *sf_i = VBOXSF_I(inode);
+       struct shfl_createparms params = {};
+       struct vboxsf_handle *sf_handle;
+       u32 access_flags = 0;
+       int err;
+
+       sf_handle = kmalloc(sizeof(*sf_handle), GFP_KERNEL);
+       if (!sf_handle)
+               return -ENOMEM;
+
+       /*
+        * We check the value of params.handle afterwards to find out if
+        * the call succeeded or failed, as the API does not seem to cleanly
+        * distinguish error and informational messages.
+        *
+        * Furthermore, we must set params.handle to SHFL_HANDLE_NIL to
+        * make the shared folders host service use our mode parameter.
+        */
+       params.handle = SHFL_HANDLE_NIL;
+       if (file->f_flags & O_CREAT) {
+               params.create_flags |= SHFL_CF_ACT_CREATE_IF_NEW;
+               /*
+                * We ignore O_EXCL, as the Linux kernel seems to call create
+                * beforehand itself, so O_EXCL should always fail.
+                */
+               if (file->f_flags & O_TRUNC)
+                       params.create_flags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS;
+               else
+                       params.create_flags |= SHFL_CF_ACT_OPEN_IF_EXISTS;
+       } else {
+               params.create_flags |= SHFL_CF_ACT_FAIL_IF_NEW;
+               if (file->f_flags & O_TRUNC)
+                       params.create_flags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS;
+       }
+
+       switch (file->f_flags & O_ACCMODE) {
+       case O_RDONLY:
+               access_flags |= SHFL_CF_ACCESS_READ;
+               break;
+
+       case O_WRONLY:
+               access_flags |= SHFL_CF_ACCESS_WRITE;
+               break;
+
+       case O_RDWR:
+               access_flags |= SHFL_CF_ACCESS_READWRITE;
+               break;
+
+       default:
+               WARN_ON(1);
+       }
+
+       if (file->f_flags & O_APPEND)
+               access_flags |= SHFL_CF_ACCESS_APPEND;
+
+       params.create_flags |= access_flags;
+       params.info.attr.mode = inode->i_mode;
+
+       err = vboxsf_create_at_dentry(file_dentry(file), &params);
+       if (err == 0 && params.handle == SHFL_HANDLE_NIL)
+               err = (params.result == SHFL_FILE_EXISTS) ? -EEXIST : -ENOENT;
+       if (err) {
+               kfree(sf_handle);
+               return err;
+       }
+
+       /* the host may have given us different attr then requested */
+       sf_i->force_restat = 1;
+
+       /* init our handle struct and add it to the inode's handles list */
+       sf_handle->handle = params.handle;
+       sf_handle->root = VBOXSF_SBI(inode->i_sb)->root;
+       sf_handle->access_flags = access_flags;
+       kref_init(&sf_handle->refcount);
+
+       mutex_lock(&sf_i->handle_list_mutex);
+       list_add(&sf_handle->head, &sf_i->handle_list);
+       mutex_unlock(&sf_i->handle_list_mutex);
+
+       file->private_data = sf_handle;
+       return 0;
+}
+
+static void vboxsf_handle_release(struct kref *refcount)
+{
+       struct vboxsf_handle *sf_handle =
+               container_of(refcount, struct vboxsf_handle, refcount);
+
+       vboxsf_close(sf_handle->root, sf_handle->handle);
+       kfree(sf_handle);
+}
+
+static int vboxsf_file_release(struct inode *inode, struct file *file)
+{
+       struct vboxsf_inode *sf_i = VBOXSF_I(inode);
+       struct vboxsf_handle *sf_handle = file->private_data;
+
+       /*
+        * When a file is closed on our (the guest) side, we want any subsequent
+        * accesses done on the host side to see all changes done from our side.
+        */
+       filemap_write_and_wait(inode->i_mapping);
+
+       mutex_lock(&sf_i->handle_list_mutex);
+       list_del(&sf_handle->head);
+       mutex_unlock(&sf_i->handle_list_mutex);
+
+       kref_put(&sf_handle->refcount, vboxsf_handle_release);
+       return 0;
+}
+
+/*
+ * Write back dirty pages now, because there may not be any suitable
+ * open files later
+ */
+static void vboxsf_vma_close(struct vm_area_struct *vma)
+{
+       filemap_write_and_wait(vma->vm_file->f_mapping);
+}
+
+static const struct vm_operations_struct vboxsf_file_vm_ops = {
+       .close          = vboxsf_vma_close,
+       .fault          = filemap_fault,
+       .map_pages      = filemap_map_pages,
+};
+
+static int vboxsf_file_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       int err;
+
+       err = generic_file_mmap(file, vma);
+       if (!err)
+               vma->vm_ops = &vboxsf_file_vm_ops;
+
+       return err;
+}
+
+/*
+ * Note that since we are accessing files on the host's filesystem, files
+ * may always be changed underneath us by the host!
+ *
+ * The vboxsf API between the guest and the host does not offer any functions
+ * to deal with this. There is no inode-generation to check for changes, no
+ * events / callback on changes and no way to lock files.
+ *
+ * To avoid returning stale data when a file gets *opened* on our (the guest)
+ * side, we do a "stat" on the host side, then compare the mtime with the
+ * last known mtime and invalidate the page-cache if they differ.
+ * This is done from vboxsf_inode_revalidate().
+ *
+ * When reads are done through the read_iter fop, it is possible to do
+ * further cache revalidation then, there are 3 options to deal with this:
+ *
+ * 1)  Rely solely on the revalidation done at open time
+ * 2)  Do another "stat" and compare mtime again. Unfortunately the vboxsf
+ *     host API does not allow stat on handles, so we would need to use
+ *     file->f_path.dentry and the stat will then fail if the file was unlinked
+ *     or renamed (and there is no thing like NFS' silly-rename). So we get:
+ * 2a) "stat" and compare mtime, on stat failure invalidate the cache
+ * 2b) "stat" and compare mtime, on stat failure do nothing
+ * 3)  Simply always call invalidate_inode_pages2_range on the range of the read
+ *
+ * Currently we are keeping things KISS and using option 1. this allows
+ * directly using generic_file_read_iter without wrapping it.
+ *
+ * This means that only data written on the host side before open() on
+ * the guest side is guaranteed to be seen by the guest. If necessary
+ * we may provide other read-cache strategies in the future and make this
+ * configurable through a mount option.
+ */
+const struct file_operations vboxsf_reg_fops = {
+       .llseek = generic_file_llseek,
+       .read_iter = generic_file_read_iter,
+       .write_iter = generic_file_write_iter,
+       .mmap = vboxsf_file_mmap,
+       .open = vboxsf_file_open,
+       .release = vboxsf_file_release,
+       .fsync = noop_fsync,
+       .splice_read = generic_file_splice_read,
+};
+
+const struct inode_operations vboxsf_reg_iops = {
+       .getattr = vboxsf_getattr,
+       .setattr = vboxsf_setattr
+};
+
+static int vboxsf_readpage(struct file *file, struct page *page)
+{
+       struct vboxsf_handle *sf_handle = file->private_data;
+       loff_t off = page_offset(page);
+       u32 nread = PAGE_SIZE;
+       u8 *buf;
+       int err;
+
+       buf = kmap(page);
+
+       err = vboxsf_read(sf_handle->root, sf_handle->handle, off, &nread, buf);
+       if (err == 0) {
+               memset(&buf[nread], 0, PAGE_SIZE - nread);
+               flush_dcache_page(page);
+               SetPageUptodate(page);
+       } else {
+               SetPageError(page);
+       }
+
+       kunmap(page);
+       unlock_page(page);
+       return err;
+}
+
+static struct vboxsf_handle *vboxsf_get_write_handle(struct vboxsf_inode *sf_i)
+{
+       struct vboxsf_handle *h, *sf_handle = NULL;
+
+       mutex_lock(&sf_i->handle_list_mutex);
+       list_for_each_entry(h, &sf_i->handle_list, head) {
+               if (h->access_flags == SHFL_CF_ACCESS_WRITE ||
+                   h->access_flags == SHFL_CF_ACCESS_READWRITE) {
+                       kref_get(&h->refcount);
+                       sf_handle = h;
+                       break;
+               }
+       }
+       mutex_unlock(&sf_i->handle_list_mutex);
+
+       return sf_handle;
+}
+
+static int vboxsf_writepage(struct page *page, struct writeback_control *wbc)
+{
+       struct inode *inode = page->mapping->host;
+       struct vboxsf_inode *sf_i = VBOXSF_I(inode);
+       struct vboxsf_handle *sf_handle;
+       loff_t off = page_offset(page);
+       loff_t size = i_size_read(inode);
+       u32 nwrite = PAGE_SIZE;
+       u8 *buf;
+       int err;
+
+       if (off + PAGE_SIZE > size)
+               nwrite = size & ~PAGE_MASK;
+
+       sf_handle = vboxsf_get_write_handle(sf_i);
+       if (!sf_handle)
+               return -EBADF;
+
+       buf = kmap(page);
+       err = vboxsf_write(sf_handle->root, sf_handle->handle,
+                          off, &nwrite, buf);
+       kunmap(page);
+
+       kref_put(&sf_handle->refcount, vboxsf_handle_release);
+
+       if (err == 0) {
+               ClearPageError(page);
+               /* mtime changed */
+               sf_i->force_restat = 1;
+       } else {
+               ClearPageUptodate(page);
+       }
+
+       unlock_page(page);
+       return err;
+}
+
+static int vboxsf_write_end(struct file *file, struct address_space *mapping,
+                           loff_t pos, unsigned int len, unsigned int copied,
+                           struct page *page, void *fsdata)
+{
+       struct inode *inode = mapping->host;
+       struct vboxsf_handle *sf_handle = file->private_data;
+       unsigned int from = pos & ~PAGE_MASK;
+       u32 nwritten = len;
+       u8 *buf;
+       int err;
+
+       buf = kmap(page);
+       err = vboxsf_write(sf_handle->root, sf_handle->handle,
+                          pos, &nwritten, buf + from);
+       kunmap(page);
+
+       if (err) {
+               nwritten = 0;
+               goto out;
+       }
+
+       /* mtime changed */
+       VBOXSF_I(inode)->force_restat = 1;
+
+       if (!PageUptodate(page) && nwritten == PAGE_SIZE)
+               SetPageUptodate(page);
+
+       pos += nwritten;
+       if (pos > inode->i_size)
+               i_size_write(inode, pos);
+
+out:
+       unlock_page(page);
+       put_page(page);
+
+       return nwritten;
+}
+
+const struct address_space_operations vboxsf_reg_aops = {
+       .readpage = vboxsf_readpage,
+       .writepage = vboxsf_writepage,
+       .set_page_dirty = __set_page_dirty_nobuffers,
+       .write_begin = simple_write_begin,
+       .write_end = vboxsf_write_end,
+};
+
+static const char *vboxsf_get_link(struct dentry *dentry, struct inode *inode,
+                                  struct delayed_call *done)
+{
+       struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb);
+       struct shfl_string *path;
+       char *link;
+       int err;
+
+       if (!dentry)
+               return ERR_PTR(-ECHILD);
+
+       path = vboxsf_path_from_dentry(sbi, dentry);
+       if (IS_ERR(path))
+               return (char *)path;
+
+       link = kzalloc(PATH_MAX, GFP_KERNEL);
+       if (!link) {
+               __putname(path);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       err = vboxsf_readlink(sbi->root, path, PATH_MAX, link);
+       __putname(path);
+       if (err) {
+               kfree(link);
+               return ERR_PTR(err);
+       }
+
+       set_delayed_call(done, kfree_link, link);
+       return link;
+}
+
+const struct inode_operations vboxsf_lnk_iops = {
+       .get_link = vboxsf_get_link
+};
diff --git a/drivers/staging/vboxsf/shfl_hostintf.h b/drivers/staging/vboxsf/shfl_hostintf.h
new file mode 100644 (file)
index 0000000..aca8290
--- /dev/null
@@ -0,0 +1,901 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * VirtualBox Shared Folders: host interface definition.
+ *
+ * Copyright (C) 2006-2018 Oracle Corporation
+ */
+
+#ifndef SHFL_HOSTINTF_H
+#define SHFL_HOSTINTF_H
+
+#include <linux/vbox_vmmdev_types.h>
+
+/* The max in/out buffer size for a FN_READ or FN_WRITE call */
+#define SHFL_MAX_RW_COUNT           (16 * SZ_1M)
+
+/*
+ * Structures shared between guest and the service
+ * can be relocated and use offsets to point to variable
+ * length parts.
+ *
+ * Shared folders protocol works with handles.
+ * Before doing any action on a file system object,
+ * one have to obtain the object handle via a SHFL_FN_CREATE
+ * request. A handle must be closed with SHFL_FN_CLOSE.
+ */
+
+enum {
+       SHFL_FN_QUERY_MAPPINGS = 1,     /* Query mappings changes. */
+       SHFL_FN_QUERY_MAP_NAME = 2,     /* Query map name. */
+       SHFL_FN_CREATE = 3,             /* Open/create object. */
+       SHFL_FN_CLOSE = 4,              /* Close object handle. */
+       SHFL_FN_READ = 5,               /* Read object content. */
+       SHFL_FN_WRITE = 6,              /* Write new object content. */
+       SHFL_FN_LOCK = 7,               /* Lock/unlock a range in the object. */
+       SHFL_FN_LIST = 8,               /* List object content. */
+       SHFL_FN_INFORMATION = 9,        /* Query/set object information. */
+       /* Note function number 10 is not used! */
+       SHFL_FN_REMOVE = 11,            /* Remove object */
+       SHFL_FN_MAP_FOLDER_OLD = 12,    /* Map folder (legacy) */
+       SHFL_FN_UNMAP_FOLDER = 13,      /* Unmap folder */
+       SHFL_FN_RENAME = 14,            /* Rename object */
+       SHFL_FN_FLUSH = 15,             /* Flush file */
+       SHFL_FN_SET_UTF8 = 16,          /* Select UTF8 filename encoding */
+       SHFL_FN_MAP_FOLDER = 17,        /* Map folder */
+       SHFL_FN_READLINK = 18,          /* Read symlink dest (as of VBox 4.0) */
+       SHFL_FN_SYMLINK = 19,           /* Create symlink (as of VBox 4.0) */
+       SHFL_FN_SET_SYMLINKS = 20,      /* Ask host to show symlinks (4.0+) */
+};
+
+/* Root handles for a mapping are of type u32, Root handles are unique. */
+#define SHFL_ROOT_NIL          UINT_MAX
+
+/* Shared folders handle for an opened object are of type u64. */
+#define SHFL_HANDLE_NIL                ULLONG_MAX
+
+/* Hardcoded maximum length (in chars) of a shared folder name. */
+#define SHFL_MAX_LEN         (256)
+/* Hardcoded maximum number of shared folder mapping available to the guest. */
+#define SHFL_MAX_MAPPINGS    (64)
+
+/** Shared folder string buffer structure. */
+struct shfl_string {
+       /** Allocated size of the string member in bytes. */
+       u16 size;
+
+       /** Length of string without trailing nul in bytes. */
+       u16 length;
+
+       /** UTF-8 or UTF-16 string. Nul terminated. */
+       union {
+               u8 utf8[2];
+               u16 utf16[1];
+               u16 ucs2[1]; /* misnomer, use utf16. */
+       } string;
+};
+VMMDEV_ASSERT_SIZE(shfl_string, 6);
+
+/* The size of shfl_string w/o the string part. */
+#define SHFLSTRING_HEADER_SIZE  4
+
+/* Calculate size of the string. */
+static inline u32 shfl_string_buf_size(const struct shfl_string *string)
+{
+       return string ? SHFLSTRING_HEADER_SIZE + string->size : 0;
+}
+
+/* Set user id on execution (S_ISUID). */
+#define SHFL_UNIX_ISUID             0004000U
+/* Set group id on execution (S_ISGID). */
+#define SHFL_UNIX_ISGID             0002000U
+/* Sticky bit (S_ISVTX / S_ISTXT). */
+#define SHFL_UNIX_ISTXT             0001000U
+
+/* Owner readable (S_IRUSR). */
+#define SHFL_UNIX_IRUSR             0000400U
+/* Owner writable (S_IWUSR). */
+#define SHFL_UNIX_IWUSR             0000200U
+/* Owner executable (S_IXUSR). */
+#define SHFL_UNIX_IXUSR             0000100U
+
+/* Group readable (S_IRGRP). */
+#define SHFL_UNIX_IRGRP             0000040U
+/* Group writable (S_IWGRP). */
+#define SHFL_UNIX_IWGRP             0000020U
+/* Group executable (S_IXGRP). */
+#define SHFL_UNIX_IXGRP             0000010U
+
+/* Other readable (S_IROTH). */
+#define SHFL_UNIX_IROTH             0000004U
+/* Other writable (S_IWOTH). */
+#define SHFL_UNIX_IWOTH             0000002U
+/* Other executable (S_IXOTH). */
+#define SHFL_UNIX_IXOTH             0000001U
+
+/* Named pipe (fifo) (S_IFIFO). */
+#define SHFL_TYPE_FIFO              0010000U
+/* Character device (S_IFCHR). */
+#define SHFL_TYPE_DEV_CHAR          0020000U
+/* Directory (S_IFDIR). */
+#define SHFL_TYPE_DIRECTORY         0040000U
+/* Block device (S_IFBLK). */
+#define SHFL_TYPE_DEV_BLOCK         0060000U
+/* Regular file (S_IFREG). */
+#define SHFL_TYPE_FILE              0100000U
+/* Symbolic link (S_IFLNK). */
+#define SHFL_TYPE_SYMLINK           0120000U
+/* Socket (S_IFSOCK). */
+#define SHFL_TYPE_SOCKET            0140000U
+/* Whiteout (S_IFWHT). */
+#define SHFL_TYPE_WHITEOUT          0160000U
+/* Type mask (S_IFMT). */
+#define SHFL_TYPE_MASK              0170000U
+
+/* Checks the mode flags indicate a directory (S_ISDIR). */
+#define SHFL_IS_DIRECTORY(m)   (((m) & SHFL_TYPE_MASK) == SHFL_TYPE_DIRECTORY)
+/* Checks the mode flags indicate a symbolic link (S_ISLNK). */
+#define SHFL_IS_SYMLINK(m)     (((m) & SHFL_TYPE_MASK) == SHFL_TYPE_SYMLINK)
+
+/** The available additional information in a shfl_fsobjattr object. */
+enum shfl_fsobjattr_add {
+       /** No additional information is available / requested. */
+       SHFLFSOBJATTRADD_NOTHING = 1,
+       /**
+        * The additional unix attributes (shfl_fsobjattr::u::unix_attr) are
+        *  available / requested.
+        */
+       SHFLFSOBJATTRADD_UNIX,
+       /**
+        * The additional extended attribute size (shfl_fsobjattr::u::size) is
+        *  available / requested.
+        */
+       SHFLFSOBJATTRADD_EASIZE,
+       /**
+        * The last valid item (inclusive).
+        * The valid range is SHFLFSOBJATTRADD_NOTHING thru
+        * SHFLFSOBJATTRADD_LAST.
+        */
+       SHFLFSOBJATTRADD_LAST = SHFLFSOBJATTRADD_EASIZE,
+
+       /** The usual 32-bit hack. */
+       SHFLFSOBJATTRADD_32BIT_SIZE_HACK = 0x7fffffff
+};
+
+/**
+ * Additional unix Attributes, these are available when
+ * shfl_fsobjattr.additional == SHFLFSOBJATTRADD_UNIX.
+ */
+struct shfl_fsobjattr_unix {
+       /**
+        * The user owning the filesystem object (st_uid).
+        * This field is ~0U if not supported.
+        */
+       u32 uid;
+
+       /**
+        * The group the filesystem object is assigned (st_gid).
+        * This field is ~0U if not supported.
+        */
+       u32 gid;
+
+       /**
+        * Number of hard links to this filesystem object (st_nlink).
+        * This field is 1 if the filesystem doesn't support hardlinking or
+        * the information isn't available.
+        */
+       u32 hardlinks;
+
+       /**
+        * The device number of the device which this filesystem object resides
+        * on (st_dev). This field is 0 if this information is not available.
+        */
+       u32 inode_id_device;
+
+       /**
+        * The unique identifier (within the filesystem) of this filesystem
+        * object (st_ino). Together with inode_id_device, this field can be
+        * used as a OS wide unique id, when both their values are not 0.
+        * This field is 0 if the information is not available.
+        */
+       u64 inode_id;
+
+       /**
+        * User flags (st_flags).
+        * This field is 0 if this information is not available.
+        */
+       u32 flags;
+
+       /**
+        * The current generation number (st_gen).
+        * This field is 0 if this information is not available.
+        */
+       u32 generation_id;
+
+       /**
+        * The device number of a char. or block device type object (st_rdev).
+        * This field is 0 if the file isn't a char. or block device or when
+        * the OS doesn't use the major+minor device idenfication scheme.
+        */
+       u32 device;
+} __packed;
+
+/** Extended attribute size. */
+struct shfl_fsobjattr_easize {
+       /** Size of EAs. */
+       s64 cb;
+} __packed;
+
+/** Shared folder filesystem object attributes. */
+struct shfl_fsobjattr {
+       /** Mode flags (st_mode). SHFL_UNIX_*, SHFL_TYPE_*, and SHFL_DOS_*. */
+       u32 mode;
+
+       /** The additional attributes available. */
+       enum shfl_fsobjattr_add additional;
+
+       /**
+        * Additional attributes.
+        *
+        * Unless explicitly specified to an API, the API can provide additional
+        * data as it is provided by the underlying OS.
+        */
+       union {
+               struct shfl_fsobjattr_unix unix_attr;
+               struct shfl_fsobjattr_easize size;
+       } __packed u;
+} __packed;
+VMMDEV_ASSERT_SIZE(shfl_fsobjattr, 44);
+
+struct shfl_timespec {
+       s64 ns_relative_to_unix_epoch;
+};
+
+/** Filesystem object information structure. */
+struct shfl_fsobjinfo {
+       /**
+        * Logical size (st_size).
+        * For normal files this is the size of the file.
+        * For symbolic links, this is the length of the path name contained
+        * in the symbolic link.
+        * For other objects this fields needs to be specified.
+        */
+       s64 size;
+
+       /** Disk allocation size (st_blocks * DEV_BSIZE). */
+       s64 allocated;
+
+       /** Time of last access (st_atime). */
+       struct shfl_timespec access_time;
+
+       /** Time of last data modification (st_mtime). */
+       struct shfl_timespec modification_time;
+
+       /**
+        * Time of last status change (st_ctime).
+        * If not available this is set to modification_time.
+        */
+       struct shfl_timespec change_time;
+
+       /**
+        * Time of file birth (st_birthtime).
+        * If not available this is set to change_time.
+        */
+       struct shfl_timespec birth_time;
+
+       /** Attributes. */
+       struct shfl_fsobjattr attr;
+
+} __packed;
+VMMDEV_ASSERT_SIZE(shfl_fsobjinfo, 92);
+
+/**
+ * result of an open/create request.
+ * Along with handle value the result code
+ * identifies what has happened while
+ * trying to open the object.
+ */
+enum shfl_create_result {
+       SHFL_NO_RESULT,
+       /** Specified path does not exist. */
+       SHFL_PATH_NOT_FOUND,
+       /** Path to file exists, but the last component does not. */
+       SHFL_FILE_NOT_FOUND,
+       /** File already exists and either has been opened or not. */
+       SHFL_FILE_EXISTS,
+       /** New file was created. */
+       SHFL_FILE_CREATED,
+       /** Existing file was replaced or overwritten. */
+       SHFL_FILE_REPLACED
+};
+
+/* No flags. Initialization value. */
+#define SHFL_CF_NONE                  (0x00000000)
+
+/*
+ * Only lookup the object, do not return a handle. When this is set all other
+ * flags are ignored.
+ */
+#define SHFL_CF_LOOKUP                (0x00000001)
+
+/*
+ * Open parent directory of specified object.
+ * Useful for the corresponding Windows FSD flag
+ * and for opening paths like \\dir\\*.* to search the 'dir'.
+ */
+#define SHFL_CF_OPEN_TARGET_DIRECTORY (0x00000002)
+
+/* Create/open a directory. */
+#define SHFL_CF_DIRECTORY             (0x00000004)
+
+/*
+ *  Open/create action to do if object exists
+ *  and if the object does not exists.
+ *  REPLACE file means atomically DELETE and CREATE.
+ *  OVERWRITE file means truncating the file to 0 and
+ *  setting new size.
+ *  When opening an existing directory REPLACE and OVERWRITE
+ *  actions are considered invalid, and cause returning
+ *  FILE_EXISTS with NIL handle.
+ */
+#define SHFL_CF_ACT_MASK_IF_EXISTS      (0x000000f0)
+#define SHFL_CF_ACT_MASK_IF_NEW         (0x00000f00)
+
+/* What to do if object exists. */
+#define SHFL_CF_ACT_OPEN_IF_EXISTS      (0x00000000)
+#define SHFL_CF_ACT_FAIL_IF_EXISTS      (0x00000010)
+#define SHFL_CF_ACT_REPLACE_IF_EXISTS   (0x00000020)
+#define SHFL_CF_ACT_OVERWRITE_IF_EXISTS (0x00000030)
+
+/* What to do if object does not exist. */
+#define SHFL_CF_ACT_CREATE_IF_NEW       (0x00000000)
+#define SHFL_CF_ACT_FAIL_IF_NEW         (0x00000100)
+
+/* Read/write requested access for the object. */
+#define SHFL_CF_ACCESS_MASK_RW          (0x00003000)
+
+/* No access requested. */
+#define SHFL_CF_ACCESS_NONE             (0x00000000)
+/* Read access requested. */
+#define SHFL_CF_ACCESS_READ             (0x00001000)
+/* Write access requested. */
+#define SHFL_CF_ACCESS_WRITE            (0x00002000)
+/* Read/Write access requested. */
+#define SHFL_CF_ACCESS_READWRITE       (0x00003000)
+
+/* Requested share access for the object. */
+#define SHFL_CF_ACCESS_MASK_DENY        (0x0000c000)
+
+/* Allow any access. */
+#define SHFL_CF_ACCESS_DENYNONE         (0x00000000)
+/* Do not allow read. */
+#define SHFL_CF_ACCESS_DENYREAD         (0x00004000)
+/* Do not allow write. */
+#define SHFL_CF_ACCESS_DENYWRITE        (0x00008000)
+/* Do not allow access. */
+#define SHFL_CF_ACCESS_DENYALL          (0x0000c000)
+
+/* Requested access to attributes of the object. */
+#define SHFL_CF_ACCESS_MASK_ATTR        (0x00030000)
+
+/* No access requested. */
+#define SHFL_CF_ACCESS_ATTR_NONE        (0x00000000)
+/* Read access requested. */
+#define SHFL_CF_ACCESS_ATTR_READ        (0x00010000)
+/* Write access requested. */
+#define SHFL_CF_ACCESS_ATTR_WRITE       (0x00020000)
+/* Read/Write access requested. */
+#define SHFL_CF_ACCESS_ATTR_READWRITE   (0x00030000)
+
+/*
+ * The file is opened in append mode.
+ * Ignored if SHFL_CF_ACCESS_WRITE is not set.
+ */
+#define SHFL_CF_ACCESS_APPEND           (0x00040000)
+
+/** Create parameters buffer struct for SHFL_FN_CREATE call */
+struct shfl_createparms {
+       /** Returned handle of opened object. */
+       u64 handle;
+
+       /** Returned result of the operation */
+       enum shfl_create_result result;
+
+       /** SHFL_CF_* */
+       u32 create_flags;
+
+       /**
+        * Attributes of object to create and
+        * returned actual attributes of opened/created object.
+        */
+       struct shfl_fsobjinfo info;
+} __packed;
+
+/** Shared Folder directory information */
+struct shfl_dirinfo {
+       /** Full information about the object. */
+       struct shfl_fsobjinfo info;
+       /**
+        * The length of the short field (number of UTF16 chars).
+        * It is 16-bit for reasons of alignment.
+        */
+       u16 short_name_len;
+       /**
+        * The short name for 8.3 compatibility.
+        * Empty string if not available.
+        */
+       u16 short_name[14];
+       struct shfl_string name;
+};
+
+/** Shared folder filesystem properties. */
+struct shfl_fsproperties {
+       /**
+        * The maximum size of a filesystem object name.
+        * This does not include the '\\0'.
+        */
+       u32 max_component_len;
+
+       /**
+        * True if the filesystem is remote.
+        * False if the filesystem is local.
+        */
+       bool remote;
+
+       /**
+        * True if the filesystem is case sensitive.
+        * False if the filesystem is case insensitive.
+        */
+       bool case_sensitive;
+
+       /**
+        * True if the filesystem is mounted read only.
+        * False if the filesystem is mounted read write.
+        */
+       bool read_only;
+
+       /**
+        * True if the filesystem can encode unicode object names.
+        * False if it can't.
+        */
+       bool supports_unicode;
+
+       /**
+        * True if the filesystem is compresses.
+        * False if it isn't or we don't know.
+        */
+       bool compressed;
+
+       /**
+        * True if the filesystem compresses of individual files.
+        * False if it doesn't or we don't know.
+        */
+       bool file_compression;
+};
+VMMDEV_ASSERT_SIZE(shfl_fsproperties, 12);
+
+struct shfl_volinfo {
+       s64 total_allocation_bytes;
+       s64 available_allocation_bytes;
+       u32 bytes_per_allocation_unit;
+       u32 bytes_per_sector;
+       u32 serial;
+       struct shfl_fsproperties properties;
+};
+
+
+/** SHFL_FN_MAP_FOLDER Parameters structure. */
+struct shfl_map_folder {
+       /**
+        * pointer, in:
+        * Points to struct shfl_string buffer.
+        */
+       struct vmmdev_hgcm_function_parameter path;
+
+       /**
+        * pointer, out: SHFLROOT (u32)
+        * Root handle of the mapping which name is queried.
+        */
+       struct vmmdev_hgcm_function_parameter root;
+
+       /**
+        * pointer, in: UTF16
+        * Path delimiter
+        */
+       struct vmmdev_hgcm_function_parameter delimiter;
+
+       /**
+        * pointer, in: SHFLROOT (u32)
+        * Case senstive flag
+        */
+       struct vmmdev_hgcm_function_parameter case_sensitive;
+
+};
+
+/* Number of parameters */
+#define SHFL_CPARMS_MAP_FOLDER (4)
+
+
+/** SHFL_FN_UNMAP_FOLDER Parameters structure. */
+struct shfl_unmap_folder {
+       /**
+        * pointer, in: SHFLROOT (u32)
+        * Root handle of the mapping which name is queried.
+        */
+       struct vmmdev_hgcm_function_parameter root;
+
+};
+
+/* Number of parameters */
+#define SHFL_CPARMS_UNMAP_FOLDER (1)
+
+
+/** SHFL_FN_CREATE Parameters structure. */
+struct shfl_create {
+       /**
+        * pointer, in: SHFLROOT (u32)
+        * Root handle of the mapping which name is queried.
+        */
+       struct vmmdev_hgcm_function_parameter root;
+
+       /**
+        * pointer, in:
+        * Points to struct shfl_string buffer.
+        */
+       struct vmmdev_hgcm_function_parameter path;
+
+       /**
+        * pointer, in/out:
+        * Points to struct shfl_createparms buffer.
+        */
+       struct vmmdev_hgcm_function_parameter parms;
+
+};
+
+/* Number of parameters */
+#define SHFL_CPARMS_CREATE (3)
+
+
+/** SHFL_FN_CLOSE Parameters structure. */
+struct shfl_close {
+       /**
+        * pointer, in: SHFLROOT (u32)
+        * Root handle of the mapping which name is queried.
+        */
+       struct vmmdev_hgcm_function_parameter root;
+
+       /**
+        * value64, in:
+        * SHFLHANDLE (u64) of object to close.
+        */
+       struct vmmdev_hgcm_function_parameter handle;
+
+};
+
+/* Number of parameters */
+#define SHFL_CPARMS_CLOSE (2)
+
+
+/** SHFL_FN_READ Parameters structure. */
+struct shfl_read {
+       /**
+        * pointer, in: SHFLROOT (u32)
+        * Root handle of the mapping which name is queried.
+        */
+       struct vmmdev_hgcm_function_parameter root;
+
+       /**
+        * value64, in:
+        * SHFLHANDLE (u64) of object to read from.
+        */
+       struct vmmdev_hgcm_function_parameter handle;
+
+       /**
+        * value64, in:
+        * Offset to read from.
+        */
+       struct vmmdev_hgcm_function_parameter offset;
+
+       /**
+        * value64, in/out:
+        * Bytes to read/How many were read.
+        */
+       struct vmmdev_hgcm_function_parameter cb;
+
+       /**
+        * pointer, out:
+        * Buffer to place data to.
+        */
+       struct vmmdev_hgcm_function_parameter buffer;
+
+};
+
+/* Number of parameters */
+#define SHFL_CPARMS_READ (5)
+
+
+/** SHFL_FN_WRITE Parameters structure. */
+struct shfl_write {
+       /**
+        * pointer, in: SHFLROOT (u32)
+        * Root handle of the mapping which name is queried.
+        */
+       struct vmmdev_hgcm_function_parameter root;
+
+       /**
+        * value64, in:
+        * SHFLHANDLE (u64) of object to write to.
+        */
+       struct vmmdev_hgcm_function_parameter handle;
+
+       /**
+        * value64, in:
+        * Offset to write to.
+        */
+       struct vmmdev_hgcm_function_parameter offset;
+
+       /**
+        * value64, in/out:
+        * Bytes to write/How many were written.
+        */
+       struct vmmdev_hgcm_function_parameter cb;
+
+       /**
+        * pointer, in:
+        * Data to write.
+        */
+       struct vmmdev_hgcm_function_parameter buffer;
+
+};
+
+/* Number of parameters */
+#define SHFL_CPARMS_WRITE (5)
+
+
+/*
+ * SHFL_FN_LIST
+ * Listing information includes variable length RTDIRENTRY[EX] structures.
+ */
+
+#define SHFL_LIST_NONE                 0
+#define SHFL_LIST_RETURN_ONE           1
+
+/** SHFL_FN_LIST Parameters structure. */
+struct shfl_list {
+       /**
+        * pointer, in: SHFLROOT (u32)
+        * Root handle of the mapping which name is queried.
+        */
+       struct vmmdev_hgcm_function_parameter root;
+
+       /**
+        * value64, in:
+        * SHFLHANDLE (u64) of object to be listed.
+        */
+       struct vmmdev_hgcm_function_parameter handle;
+
+       /**
+        * value32, in:
+        * List flags SHFL_LIST_*.
+        */
+       struct vmmdev_hgcm_function_parameter flags;
+
+       /**
+        * value32, in/out:
+        * Bytes to be used for listing information/How many bytes were used.
+        */
+       struct vmmdev_hgcm_function_parameter cb;
+
+       /**
+        * pointer, in/optional
+        * Points to struct shfl_string buffer that specifies a search path.
+        */
+       struct vmmdev_hgcm_function_parameter path;
+
+       /**
+        * pointer, out:
+        * Buffer to place listing information to. (struct shfl_dirinfo)
+        */
+       struct vmmdev_hgcm_function_parameter buffer;
+
+       /**
+        * value32, in/out:
+        * Indicates a key where the listing must be resumed.
+        * in: 0 means start from begin of object.
+        * out: 0 means listing completed.
+        */
+       struct vmmdev_hgcm_function_parameter resume_point;
+
+       /**
+        * pointer, out:
+        * Number of files returned
+        */
+       struct vmmdev_hgcm_function_parameter file_count;
+};
+
+/* Number of parameters */
+#define SHFL_CPARMS_LIST (8)
+
+
+/** SHFL_FN_READLINK Parameters structure. */
+struct shfl_readLink {
+       /**
+        * pointer, in: SHFLROOT (u32)
+        * Root handle of the mapping which name is queried.
+        */
+       struct vmmdev_hgcm_function_parameter root;
+
+       /**
+        * pointer, in:
+        * Points to struct shfl_string buffer.
+        */
+       struct vmmdev_hgcm_function_parameter path;
+
+       /**
+        * pointer, out:
+        * Buffer to place data to.
+        */
+       struct vmmdev_hgcm_function_parameter buffer;
+
+};
+
+/* Number of parameters */
+#define SHFL_CPARMS_READLINK (3)
+
+
+/* SHFL_FN_INFORMATION */
+
+/* Mask of Set/Get bit. */
+#define SHFL_INFO_MODE_MASK    (0x1)
+/* Get information */
+#define SHFL_INFO_GET          (0x0)
+/* Set information */
+#define SHFL_INFO_SET          (0x1)
+
+/* Get name of the object. */
+#define SHFL_INFO_NAME         (0x2)
+/* Set size of object (extend/trucate); only applies to file objects */
+#define SHFL_INFO_SIZE         (0x4)
+/* Get/Set file object info. */
+#define SHFL_INFO_FILE         (0x8)
+/* Get volume information. */
+#define SHFL_INFO_VOLUME       (0x10)
+
+/** SHFL_FN_INFORMATION Parameters structure. */
+struct shfl_information {
+       /**
+        * pointer, in: SHFLROOT (u32)
+        * Root handle of the mapping which name is queried.
+        */
+       struct vmmdev_hgcm_function_parameter root;
+
+       /**
+        * value64, in:
+        * SHFLHANDLE (u64) of object to be listed.
+        */
+       struct vmmdev_hgcm_function_parameter handle;
+
+       /**
+        * value32, in:
+        * SHFL_INFO_*
+        */
+       struct vmmdev_hgcm_function_parameter flags;
+
+       /**
+        * value32, in/out:
+        * Bytes to be used for information/How many bytes were used.
+        */
+       struct vmmdev_hgcm_function_parameter cb;
+
+       /**
+        * pointer, in/out:
+        * Information to be set/get (shfl_fsobjinfo or shfl_string). Do not
+        * forget to set the shfl_fsobjinfo::attr::additional for a get
+        * operation as well.
+        */
+       struct vmmdev_hgcm_function_parameter info;
+
+};
+
+/* Number of parameters */
+#define SHFL_CPARMS_INFORMATION (5)
+
+
+/* SHFL_FN_REMOVE */
+
+#define SHFL_REMOVE_FILE        (0x1)
+#define SHFL_REMOVE_DIR         (0x2)
+#define SHFL_REMOVE_SYMLINK     (0x4)
+
+/** SHFL_FN_REMOVE Parameters structure. */
+struct shfl_remove {
+       /**
+        * pointer, in: SHFLROOT (u32)
+        * Root handle of the mapping which name is queried.
+        */
+       struct vmmdev_hgcm_function_parameter root;
+
+       /**
+        * pointer, in:
+        * Points to struct shfl_string buffer.
+        */
+       struct vmmdev_hgcm_function_parameter path;
+
+       /**
+        * value32, in:
+        * remove flags (file/directory)
+        */
+       struct vmmdev_hgcm_function_parameter flags;
+
+};
+
+#define SHFL_CPARMS_REMOVE  (3)
+
+
+/* SHFL_FN_RENAME */
+
+#define SHFL_RENAME_FILE                (0x1)
+#define SHFL_RENAME_DIR                 (0x2)
+#define SHFL_RENAME_REPLACE_IF_EXISTS   (0x4)
+
+/** SHFL_FN_RENAME Parameters structure. */
+struct shfl_rename {
+       /**
+        * pointer, in: SHFLROOT (u32)
+        * Root handle of the mapping which name is queried.
+        */
+       struct vmmdev_hgcm_function_parameter root;
+
+       /**
+        * pointer, in:
+        * Points to struct shfl_string src.
+        */
+       struct vmmdev_hgcm_function_parameter src;
+
+       /**
+        * pointer, in:
+        * Points to struct shfl_string dest.
+        */
+       struct vmmdev_hgcm_function_parameter dest;
+
+       /**
+        * value32, in:
+        * rename flags (file/directory)
+        */
+       struct vmmdev_hgcm_function_parameter flags;
+
+};
+
+#define SHFL_CPARMS_RENAME  (4)
+
+
+/** SHFL_FN_SYMLINK Parameters structure. */
+struct shfl_symlink {
+       /**
+        * pointer, in: SHFLROOT (u32)
+        * Root handle of the mapping which name is queried.
+        */
+       struct vmmdev_hgcm_function_parameter root;
+
+       /**
+        * pointer, in:
+        * Points to struct shfl_string of path for the new symlink.
+        */
+       struct vmmdev_hgcm_function_parameter new_path;
+
+       /**
+        * pointer, in:
+        * Points to struct shfl_string of destination for symlink.
+        */
+       struct vmmdev_hgcm_function_parameter old_path;
+
+       /**
+        * pointer, out:
+        * Information about created symlink.
+        */
+       struct vmmdev_hgcm_function_parameter info;
+
+};
+
+#define SHFL_CPARMS_SYMLINK  (4)
+
+#endif
diff --git a/drivers/staging/vboxsf/super.c b/drivers/staging/vboxsf/super.c
new file mode 100644 (file)
index 0000000..0bf4d72
--- /dev/null
@@ -0,0 +1,501 @@
+// SPDX-License-Identifier: MIT
+/*
+ * VirtualBox Guest Shared Folders support: Virtual File System.
+ *
+ * Module initialization/finalization
+ * File system registration/deregistration
+ * Superblock reading
+ * Few utility functions
+ *
+ * Copyright (C) 2006-2018 Oracle Corporation
+ */
+
+#include <linux/idr.h>
+#include <linux/fs_parser.h>
+#include <linux/magic.h>
+#include <linux/module.h>
+#include <linux/nls.h>
+#include <linux/statfs.h>
+#include <linux/vbox_utils.h>
+#include "vfsmod.h"
+
+#define VBOXSF_SUPER_MAGIC 0x786f4256 /* 'VBox' little endian */
+
+#define VBSF_MOUNT_SIGNATURE_BYTE_0 ('\000')
+#define VBSF_MOUNT_SIGNATURE_BYTE_1 ('\377')
+#define VBSF_MOUNT_SIGNATURE_BYTE_2 ('\376')
+#define VBSF_MOUNT_SIGNATURE_BYTE_3 ('\375')
+
+static int follow_symlinks;
+module_param(follow_symlinks, int, 0444);
+MODULE_PARM_DESC(follow_symlinks,
+                "Let host resolve symlinks rather than showing them");
+
+static DEFINE_IDA(vboxsf_bdi_ida);
+static DEFINE_MUTEX(vboxsf_setup_mutex);
+static bool vboxsf_setup_done;
+static struct super_operations vboxsf_super_ops; /* forward declaration */
+static struct kmem_cache *vboxsf_inode_cachep;
+
+static char * const vboxsf_default_nls = CONFIG_NLS_DEFAULT;
+
+enum  { opt_nls, opt_uid, opt_gid, opt_ttl, opt_dmode, opt_fmode,
+       opt_dmask, opt_fmask };
+
+static const struct fs_parameter_spec vboxsf_param_specs[] = {
+       fsparam_string  ("nls",         opt_nls),
+       fsparam_u32     ("uid",         opt_uid),
+       fsparam_u32     ("gid",         opt_gid),
+       fsparam_u32     ("ttl",         opt_ttl),
+       fsparam_u32oct  ("dmode",       opt_dmode),
+       fsparam_u32oct  ("fmode",       opt_fmode),
+       fsparam_u32oct  ("dmask",       opt_dmask),
+       fsparam_u32oct  ("fmask",       opt_fmask),
+       {}
+};
+
+static const struct fs_parameter_description vboxsf_fs_parameters = {
+       .name  = "vboxsf",
+       .specs  = vboxsf_param_specs,
+};
+
+static int vboxsf_parse_param(struct fs_context *fc, struct fs_parameter *param)
+{
+       struct vboxsf_fs_context *ctx = fc->fs_private;
+       struct fs_parse_result result;
+       kuid_t uid;
+       kgid_t gid;
+       int opt;
+
+       opt = fs_parse(fc, &vboxsf_fs_parameters, param, &result);
+       if (opt < 0)
+               return opt;
+
+       switch (opt) {
+       case opt_nls:
+               if (fc->purpose != FS_CONTEXT_FOR_MOUNT) {
+                       vbg_err("vboxsf: Cannot reconfigure nls option\n");
+                       return -EINVAL;
+               }
+               ctx->nls_name = param->string;
+               param->string = NULL;
+               break;
+       case opt_uid:
+               uid = make_kuid(current_user_ns(), result.uint_32);
+               if (!uid_valid(uid))
+                       return -EINVAL;
+               ctx->o.uid = uid;
+               break;
+       case opt_gid:
+               gid = make_kgid(current_user_ns(), result.uint_32);
+               if (!gid_valid(gid))
+                       return -EINVAL;
+               ctx->o.gid = gid;
+               break;
+       case opt_ttl:
+               ctx->o.ttl = msecs_to_jiffies(result.uint_32);
+               break;
+       case opt_dmode:
+               if (result.uint_32 & ~0777)
+                       return -EINVAL;
+               ctx->o.dmode = result.uint_32;
+               ctx->o.dmode_set = true;
+               break;
+       case opt_fmode:
+               if (result.uint_32 & ~0777)
+                       return -EINVAL;
+               ctx->o.fmode = result.uint_32;
+               ctx->o.fmode_set = true;
+               break;
+       case opt_dmask:
+               if (result.uint_32 & ~07777)
+                       return -EINVAL;
+               ctx->o.dmask = result.uint_32;
+               break;
+       case opt_fmask:
+               if (result.uint_32 & ~07777)
+                       return -EINVAL;
+               ctx->o.fmask = result.uint_32;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int vboxsf_fill_super(struct super_block *sb, struct fs_context *fc)
+{
+       struct vboxsf_fs_context *ctx = fc->fs_private;
+       struct shfl_string *folder_name, root_path;
+       struct vboxsf_sbi *sbi;
+       struct dentry *droot;
+       struct inode *iroot;
+       char *nls_name;
+       size_t size;
+       int err;
+
+       if (!fc->source)
+               return -EINVAL;
+
+       sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
+       if (!sbi)
+               return -ENOMEM;
+
+       sbi->o = ctx->o;
+       idr_init(&sbi->ino_idr);
+       spin_lock_init(&sbi->ino_idr_lock);
+       sbi->next_generation = 1;
+       sbi->bdi_id = -1;
+
+       /* Load nls if not utf8 */
+       nls_name = ctx->nls_name ? ctx->nls_name : vboxsf_default_nls;
+       if (strcmp(nls_name, "utf8") != 0) {
+               if (nls_name == vboxsf_default_nls)
+                       sbi->nls = load_nls_default();
+               else
+                       sbi->nls = load_nls(nls_name);
+
+               if (!sbi->nls) {
+                       vbg_err("vboxsf: Count not load '%s' nls\n", nls_name);
+                       err = -EINVAL;
+                       goto fail_free;
+               }
+       }
+
+       sbi->bdi_id = ida_simple_get(&vboxsf_bdi_ida, 0, 0, GFP_KERNEL);
+       if (sbi->bdi_id < 0) {
+               err = sbi->bdi_id;
+               goto fail_free;
+       }
+
+       err = super_setup_bdi_name(sb, "vboxsf-%s.%d", fc->source, sbi->bdi_id);
+       if (err)
+               goto fail_free;
+
+       /* Turn source into a shfl_string and map the folder */
+       size = strlen(fc->source) + 1;
+       folder_name = kmalloc(SHFLSTRING_HEADER_SIZE + size, GFP_KERNEL);
+       if (!folder_name) {
+               err = -ENOMEM;
+               goto fail_free;
+       }
+       folder_name->size = size;
+       folder_name->length = size - 1;
+       strlcpy(folder_name->string.utf8, fc->source, size);
+       err = vboxsf_map_folder(folder_name, &sbi->root);
+       kfree(folder_name);
+       if (err) {
+               vbg_err("vboxsf: Host rejected mount of '%s' with error %d\n",
+                       fc->source, err);
+               goto fail_free;
+       }
+
+       root_path.length = 1;
+       root_path.size = 2;
+       root_path.string.utf8[0] = '/';
+       root_path.string.utf8[1] = 0;
+       err = vboxsf_stat(sbi, &root_path, &sbi->root_info);
+       if (err)
+               goto fail_unmap;
+
+       sb->s_magic = VBOXSF_SUPER_MAGIC;
+       sb->s_blocksize = 1024;
+       sb->s_maxbytes = MAX_LFS_FILESIZE;
+       sb->s_op = &vboxsf_super_ops;
+       sb->s_d_op = &vboxsf_dentry_ops;
+
+       iroot = iget_locked(sb, 0);
+       if (!iroot) {
+               err = -ENOMEM;
+               goto fail_unmap;
+       }
+       vboxsf_init_inode(sbi, iroot, &sbi->root_info);
+       unlock_new_inode(iroot);
+
+       droot = d_make_root(iroot);
+       if (!droot) {
+               err = -ENOMEM;
+               goto fail_unmap;
+       }
+
+       sb->s_root = droot;
+       sb->s_fs_info = sbi;
+       return 0;
+
+fail_unmap:
+       vboxsf_unmap_folder(sbi->root);
+fail_free:
+       if (sbi->bdi_id >= 0)
+               ida_simple_remove(&vboxsf_bdi_ida, sbi->bdi_id);
+       if (sbi->nls)
+               unload_nls(sbi->nls);
+       idr_destroy(&sbi->ino_idr);
+       kfree(sbi);
+       return err;
+}
+
+static void vboxsf_inode_init_once(void *data)
+{
+       struct vboxsf_inode *sf_i = data;
+
+       mutex_init(&sf_i->handle_list_mutex);
+       inode_init_once(&sf_i->vfs_inode);
+}
+
+static struct inode *vboxsf_alloc_inode(struct super_block *sb)
+{
+       struct vboxsf_inode *sf_i;
+
+       sf_i = kmem_cache_alloc(vboxsf_inode_cachep, GFP_NOFS);
+       if (!sf_i)
+               return NULL;
+
+       sf_i->force_restat = 0;
+       INIT_LIST_HEAD(&sf_i->handle_list);
+
+       return &sf_i->vfs_inode;
+}
+
+static void vboxsf_free_inode(struct inode *inode)
+{
+       struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb);
+       unsigned long flags;
+
+       spin_lock_irqsave(&sbi->ino_idr_lock, flags);
+       idr_remove(&sbi->ino_idr, inode->i_ino);
+       spin_unlock_irqrestore(&sbi->ino_idr_lock, flags);
+       kmem_cache_free(vboxsf_inode_cachep, VBOXSF_I(inode));
+}
+
+static void vboxsf_put_super(struct super_block *sb)
+{
+       struct vboxsf_sbi *sbi = VBOXSF_SBI(sb);
+
+       vboxsf_unmap_folder(sbi->root);
+       if (sbi->bdi_id >= 0)
+               ida_simple_remove(&vboxsf_bdi_ida, sbi->bdi_id);
+       if (sbi->nls)
+               unload_nls(sbi->nls);
+
+       /*
+        * vboxsf_free_inode uses the idr, make sure all delayed rcu free
+        * inodes are flushed.
+        */
+       rcu_barrier();
+       idr_destroy(&sbi->ino_idr);
+       kfree(sbi);
+}
+
+static int vboxsf_statfs(struct dentry *dentry, struct kstatfs *stat)
+{
+       struct super_block *sb = dentry->d_sb;
+       struct shfl_volinfo shfl_volinfo;
+       struct vboxsf_sbi *sbi;
+       u32 buf_len;
+       int err;
+
+       sbi = VBOXSF_SBI(sb);
+       buf_len = sizeof(shfl_volinfo);
+       err = vboxsf_fsinfo(sbi->root, 0, SHFL_INFO_GET | SHFL_INFO_VOLUME,
+                           &buf_len, &shfl_volinfo);
+       if (err)
+               return err;
+
+       stat->f_type = VBOXSF_SUPER_MAGIC;
+       stat->f_bsize = shfl_volinfo.bytes_per_allocation_unit;
+
+       do_div(shfl_volinfo.total_allocation_bytes,
+              shfl_volinfo.bytes_per_allocation_unit);
+       stat->f_blocks = shfl_volinfo.total_allocation_bytes;
+
+       do_div(shfl_volinfo.available_allocation_bytes,
+              shfl_volinfo.bytes_per_allocation_unit);
+       stat->f_bfree  = shfl_volinfo.available_allocation_bytes;
+       stat->f_bavail = shfl_volinfo.available_allocation_bytes;
+
+       stat->f_files = 1000;
+       /*
+        * Don't return 0 here since the guest may then think that it is not
+        * possible to create any more files.
+        */
+       stat->f_ffree = 1000000;
+       stat->f_fsid.val[0] = 0;
+       stat->f_fsid.val[1] = 0;
+       stat->f_namelen = 255;
+       return 0;
+}
+
+static struct super_operations vboxsf_super_ops = {
+       .alloc_inode    = vboxsf_alloc_inode,
+       .free_inode     = vboxsf_free_inode,
+       .put_super      = vboxsf_put_super,
+       .statfs         = vboxsf_statfs,
+};
+
+static int vboxsf_setup(void)
+{
+       int err;
+
+       mutex_lock(&vboxsf_setup_mutex);
+
+       if (vboxsf_setup_done)
+               goto success;
+
+       vboxsf_inode_cachep =
+               kmem_cache_create("vboxsf_inode_cache",
+                                 sizeof(struct vboxsf_inode), 0,
+                                 (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD |
+                                  SLAB_ACCOUNT),
+                                 vboxsf_inode_init_once);
+       if (!vboxsf_inode_cachep) {
+               err = -ENOMEM;
+               goto fail_nomem;
+       }
+
+       err = vboxsf_connect();
+       if (err) {
+               vbg_err("vboxsf: err %d connecting to guest PCI-device\n", err);
+               vbg_err("vboxsf: make sure you are inside a VirtualBox VM\n");
+               vbg_err("vboxsf: and check dmesg for vboxguest errors\n");
+               goto fail_free_cache;
+       }
+
+       err = vboxsf_set_utf8();
+       if (err) {
+               vbg_err("vboxsf_setutf8 error %d\n", err);
+               goto fail_disconnect;
+       }
+
+       if (!follow_symlinks) {
+               err = vboxsf_set_symlinks();
+               if (err)
+                       vbg_warn("vboxsf: Unable to show symlinks: %d\n", err);
+       }
+
+       vboxsf_setup_done = true;
+success:
+       mutex_unlock(&vboxsf_setup_mutex);
+       return 0;
+
+fail_disconnect:
+       vboxsf_disconnect();
+fail_free_cache:
+       kmem_cache_destroy(vboxsf_inode_cachep);
+fail_nomem:
+       mutex_unlock(&vboxsf_setup_mutex);
+       return err;
+}
+
+static int vboxsf_parse_monolithic(struct fs_context *fc, void *data)
+{
+       char *options = data;
+
+       if (options && options[0] == VBSF_MOUNT_SIGNATURE_BYTE_0 &&
+                      options[1] == VBSF_MOUNT_SIGNATURE_BYTE_1 &&
+                      options[2] == VBSF_MOUNT_SIGNATURE_BYTE_2 &&
+                      options[3] == VBSF_MOUNT_SIGNATURE_BYTE_3) {
+               vbg_err("vboxsf: Old binary mount data not supported, remove obsolete mount.vboxsf and/or update your VBoxService.\n");
+               return -EINVAL;
+       }
+
+       return generic_parse_monolithic(fc, data);
+}
+
+static int vboxsf_get_tree(struct fs_context *fc)
+{
+       int err;
+
+       err = vboxsf_setup();
+       if (err)
+               return err;
+
+       return vfs_get_super(fc, vfs_get_independent_super, vboxsf_fill_super);
+}
+
+static int vboxsf_reconfigure(struct fs_context *fc)
+{
+       struct vboxsf_sbi *sbi = VBOXSF_SBI(fc->root->d_sb);
+       struct vboxsf_fs_context *ctx = fc->fs_private;
+       struct inode *iroot;
+
+       iroot = ilookup(fc->root->d_sb, 0);
+       if (!iroot)
+               return -ENOENT;
+
+       /* Apply changed options to the root inode */
+       sbi->o = ctx->o;
+       vboxsf_init_inode(sbi, iroot, &sbi->root_info);
+
+       return 0;
+}
+
+static void vboxsf_free_fc(struct fs_context *fc)
+{
+       struct vboxsf_fs_context *ctx = fc->fs_private;
+
+       kfree(ctx->nls_name);
+       kfree(ctx);
+}
+
+static const struct fs_context_operations vboxsf_context_ops = {
+       .free                   = vboxsf_free_fc,
+       .parse_param            = vboxsf_parse_param,
+       .parse_monolithic       = vboxsf_parse_monolithic,
+       .get_tree               = vboxsf_get_tree,
+       .reconfigure            = vboxsf_reconfigure,
+};
+
+static int vboxsf_init_fs_context(struct fs_context *fc)
+{
+       struct vboxsf_fs_context *ctx;
+
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+
+       current_uid_gid(&ctx->o.uid, &ctx->o.gid);
+
+       fc->fs_private = ctx;
+       fc->ops = &vboxsf_context_ops;
+       return 0;
+}
+
+static struct file_system_type vboxsf_fs_type = {
+       .owner                  = THIS_MODULE,
+       .name                   = "vboxsf",
+       .init_fs_context        = vboxsf_init_fs_context,
+       .parameters             = &vboxsf_fs_parameters,
+       .kill_sb                = kill_anon_super
+};
+
+/* Module initialization/finalization handlers */
+static int __init vboxsf_init(void)
+{
+       return register_filesystem(&vboxsf_fs_type);
+}
+
+static void __exit vboxsf_fini(void)
+{
+       unregister_filesystem(&vboxsf_fs_type);
+
+       mutex_lock(&vboxsf_setup_mutex);
+       if (vboxsf_setup_done) {
+               vboxsf_disconnect();
+               /*
+                * Make sure all delayed rcu free inodes are flushed
+                * before we destroy the cache.
+                */
+               rcu_barrier();
+               kmem_cache_destroy(vboxsf_inode_cachep);
+       }
+       mutex_unlock(&vboxsf_setup_mutex);
+}
+
+module_init(vboxsf_init);
+module_exit(vboxsf_fini);
+
+MODULE_DESCRIPTION("Oracle VM VirtualBox Module for Host File System Access");
+MODULE_AUTHOR("Oracle Corporation");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS_FS("vboxsf");
diff --git a/drivers/staging/vboxsf/utils.c b/drivers/staging/vboxsf/utils.c
new file mode 100644 (file)
index 0000000..34a49e6
--- /dev/null
@@ -0,0 +1,551 @@
+// SPDX-License-Identifier: MIT
+/*
+ * VirtualBox Guest Shared Folders support: Utility functions.
+ * Mainly conversion from/to VirtualBox/Linux data structures.
+ *
+ * Copyright (C) 2006-2018 Oracle Corporation
+ */
+
+#include <linux/namei.h>
+#include <linux/nls.h>
+#include <linux/sizes.h>
+#include <linux/vfs.h>
+#include "vfsmod.h"
+
+struct inode *vboxsf_new_inode(struct super_block *sb)
+{
+       struct vboxsf_sbi *sbi = VBOXSF_SBI(sb);
+       struct inode *inode;
+       unsigned long flags;
+       int cursor, ret;
+       u32 gen;
+
+       inode = new_inode(sb);
+       if (!inode)
+               return ERR_PTR(-ENOMEM);
+
+       idr_preload(GFP_KERNEL);
+       spin_lock_irqsave(&sbi->ino_idr_lock, flags);
+       cursor = idr_get_cursor(&sbi->ino_idr);
+       ret = idr_alloc_cyclic(&sbi->ino_idr, inode, 1, 0, GFP_ATOMIC);
+       if (ret >= 0 && ret < cursor)
+               sbi->next_generation++;
+       gen = sbi->next_generation;
+       spin_unlock_irqrestore(&sbi->ino_idr_lock, flags);
+       idr_preload_end();
+
+       if (ret < 0) {
+               iput(inode);
+               return ERR_PTR(ret);
+       }
+
+       inode->i_ino = ret;
+       inode->i_generation = gen;
+       return inode;
+}
+
+/* set [inode] attributes based on [info], uid/gid based on [sbi] */
+void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
+                      const struct shfl_fsobjinfo *info)
+{
+       const struct shfl_fsobjattr *attr;
+       s64 allocated;
+       int mode;
+
+       attr = &info->attr;
+
+#define mode_set(r) ((attr->mode & (SHFL_UNIX_##r)) ? (S_##r) : 0)
+
+       mode = mode_set(IRUSR);
+       mode |= mode_set(IWUSR);
+       mode |= mode_set(IXUSR);
+
+       mode |= mode_set(IRGRP);
+       mode |= mode_set(IWGRP);
+       mode |= mode_set(IXGRP);
+
+       mode |= mode_set(IROTH);
+       mode |= mode_set(IWOTH);
+       mode |= mode_set(IXOTH);
+
+#undef mode_set
+
+       /* We use the host-side values for these */
+       inode->i_flags |= S_NOATIME | S_NOCMTIME;
+       inode->i_mapping->a_ops = &vboxsf_reg_aops;
+
+       if (SHFL_IS_DIRECTORY(attr->mode)) {
+               inode->i_mode = sbi->o.dmode_set ? sbi->o.dmode : mode;
+               inode->i_mode &= ~sbi->o.dmask;
+               inode->i_mode |= S_IFDIR;
+               inode->i_op = &vboxsf_dir_iops;
+               inode->i_fop = &vboxsf_dir_fops;
+               /*
+                * XXX: this probably should be set to the number of entries
+                * in the directory plus two (. ..)
+                */
+               set_nlink(inode, 1);
+       } else if (SHFL_IS_SYMLINK(attr->mode)) {
+               inode->i_mode = sbi->o.fmode_set ? sbi->o.fmode : mode;
+               inode->i_mode &= ~sbi->o.fmask;
+               inode->i_mode |= S_IFLNK;
+               inode->i_op = &vboxsf_lnk_iops;
+               set_nlink(inode, 1);
+       } else {
+               inode->i_mode = sbi->o.fmode_set ? sbi->o.fmode : mode;
+               inode->i_mode &= ~sbi->o.fmask;
+               inode->i_mode |= S_IFREG;
+               inode->i_op = &vboxsf_reg_iops;
+               inode->i_fop = &vboxsf_reg_fops;
+               set_nlink(inode, 1);
+       }
+
+       inode->i_uid = sbi->o.uid;
+       inode->i_gid = sbi->o.gid;
+
+       inode->i_size = info->size;
+       inode->i_blkbits = 12;
+       /* i_blocks always in units of 512 bytes! */
+       allocated = info->allocated + 511;
+       do_div(allocated, 512);
+       inode->i_blocks = allocated;
+
+       inode->i_atime = ns_to_timespec64(
+                                info->access_time.ns_relative_to_unix_epoch);
+       inode->i_ctime = ns_to_timespec64(
+                                info->change_time.ns_relative_to_unix_epoch);
+       inode->i_mtime = ns_to_timespec64(
+                          info->modification_time.ns_relative_to_unix_epoch);
+}
+
+int vboxsf_create_at_dentry(struct dentry *dentry,
+                           struct shfl_createparms *params)
+{
+       struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb);
+       struct shfl_string *path;
+       int err;
+
+       path = vboxsf_path_from_dentry(sbi, dentry);
+       if (IS_ERR(path))
+               return PTR_ERR(path);
+
+       err = vboxsf_create(sbi->root, path, params);
+       __putname(path);
+
+       return err;
+}
+
+int vboxsf_stat(struct vboxsf_sbi *sbi, struct shfl_string *path,
+               struct shfl_fsobjinfo *info)
+{
+       struct shfl_createparms params = {};
+       int err;
+
+       params.handle = SHFL_HANDLE_NIL;
+       params.create_flags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW;
+
+       err = vboxsf_create(sbi->root, path, &params);
+       if (err)
+               return err;
+
+       if (params.result != SHFL_FILE_EXISTS)
+               return -ENOENT;
+
+       if (info)
+               *info = params.info;
+
+       return 0;
+}
+
+int vboxsf_stat_dentry(struct dentry *dentry, struct shfl_fsobjinfo *info)
+{
+       struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb);
+       struct shfl_string *path;
+       int err;
+
+       path = vboxsf_path_from_dentry(sbi, dentry);
+       if (IS_ERR(path))
+               return PTR_ERR(path);
+
+       err = vboxsf_stat(sbi, path, info);
+       __putname(path);
+       return err;
+}
+
+int vboxsf_inode_revalidate(struct dentry *dentry)
+{
+       struct vboxsf_sbi *sbi;
+       struct vboxsf_inode *sf_i;
+       struct shfl_fsobjinfo info;
+       struct timespec64 prev_mtime;
+       struct inode *inode;
+       int err;
+
+       if (!dentry || !d_really_is_positive(dentry))
+               return -EINVAL;
+
+       inode = d_inode(dentry);
+       prev_mtime = inode->i_mtime;
+       sf_i = VBOXSF_I(inode);
+       sbi = VBOXSF_SBI(dentry->d_sb);
+       if (!sf_i->force_restat) {
+               if (time_before(jiffies, dentry->d_time + sbi->o.ttl))
+                       return 0;
+       }
+
+       err = vboxsf_stat_dentry(dentry, &info);
+       if (err)
+               return err;
+
+       dentry->d_time = jiffies;
+       sf_i->force_restat = 0;
+       vboxsf_init_inode(sbi, inode, &info);
+
+       /*
+        * If the file was changed on the host side we need to invalidate the
+        * page-cache for it.  Note this also gets triggered by our own writes,
+        * this is unavoidable.
+        */
+       if (timespec64_compare(&inode->i_mtime, &prev_mtime) > 0)
+               invalidate_inode_pages2(inode->i_mapping);
+
+       return 0;
+}
+
+int vboxsf_getattr(const struct path *path, struct kstat *kstat,
+                  u32 request_mask, unsigned int flags)
+{
+       int err;
+       struct dentry *dentry = path->dentry;
+       struct inode *inode = d_inode(dentry);
+       struct vboxsf_inode *sf_i = VBOXSF_I(inode);
+
+       switch (flags & AT_STATX_SYNC_TYPE) {
+       case AT_STATX_DONT_SYNC:
+               err = 0;
+               break;
+       case AT_STATX_FORCE_SYNC:
+               sf_i->force_restat = 1;
+               /* fall-through */
+       default:
+               err = vboxsf_inode_revalidate(dentry);
+       }
+       if (err)
+               return err;
+
+       generic_fillattr(d_inode(dentry), kstat);
+       return 0;
+}
+
+int vboxsf_setattr(struct dentry *dentry, struct iattr *iattr)
+{
+       struct vboxsf_inode *sf_i = VBOXSF_I(d_inode(dentry));
+       struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb);
+       struct shfl_createparms params = {};
+       struct shfl_fsobjinfo info = {};
+       u32 buf_len;
+       int err;
+
+       params.handle = SHFL_HANDLE_NIL;
+       params.create_flags = SHFL_CF_ACT_OPEN_IF_EXISTS |
+                             SHFL_CF_ACT_FAIL_IF_NEW |
+                             SHFL_CF_ACCESS_ATTR_WRITE;
+
+       /* this is at least required for Posix hosts */
+       if (iattr->ia_valid & ATTR_SIZE)
+               params.create_flags |= SHFL_CF_ACCESS_WRITE;
+
+       err = vboxsf_create_at_dentry(dentry, &params);
+       if (err || params.result != SHFL_FILE_EXISTS)
+               return err ? err : -ENOENT;
+
+#define mode_set(r) ((iattr->ia_mode & (S_##r)) ? SHFL_UNIX_##r : 0)
+
+       /*
+        * Setting the file size and setting the other attributes has to
+        * be handled separately.
+        */
+       if (iattr->ia_valid & (ATTR_MODE | ATTR_ATIME | ATTR_MTIME)) {
+               if (iattr->ia_valid & ATTR_MODE) {
+                       info.attr.mode = mode_set(IRUSR);
+                       info.attr.mode |= mode_set(IWUSR);
+                       info.attr.mode |= mode_set(IXUSR);
+                       info.attr.mode |= mode_set(IRGRP);
+                       info.attr.mode |= mode_set(IWGRP);
+                       info.attr.mode |= mode_set(IXGRP);
+                       info.attr.mode |= mode_set(IROTH);
+                       info.attr.mode |= mode_set(IWOTH);
+                       info.attr.mode |= mode_set(IXOTH);
+
+                       if (iattr->ia_mode & S_IFDIR)
+                               info.attr.mode |= SHFL_TYPE_DIRECTORY;
+                       else
+                               info.attr.mode |= SHFL_TYPE_FILE;
+               }
+
+               if (iattr->ia_valid & ATTR_ATIME)
+                       info.access_time.ns_relative_to_unix_epoch =
+                                           timespec64_to_ns(&iattr->ia_atime);
+
+               if (iattr->ia_valid & ATTR_MTIME)
+                       info.modification_time.ns_relative_to_unix_epoch =
+                                           timespec64_to_ns(&iattr->ia_mtime);
+
+               /*
+                * Ignore ctime (inode change time) as it can't be set
+                * from userland anyway.
+                */
+
+               buf_len = sizeof(info);
+               err = vboxsf_fsinfo(sbi->root, params.handle,
+                                   SHFL_INFO_SET | SHFL_INFO_FILE, &buf_len,
+                                   &info);
+               if (err) {
+                       vboxsf_close(sbi->root, params.handle);
+                       return err;
+               }
+
+               /* the host may have given us different attr then requested */
+               sf_i->force_restat = 1;
+       }
+
+#undef mode_set
+
+       if (iattr->ia_valid & ATTR_SIZE) {
+               memset(&info, 0, sizeof(info));
+               info.size = iattr->ia_size;
+               buf_len = sizeof(info);
+               err = vboxsf_fsinfo(sbi->root, params.handle,
+                                   SHFL_INFO_SET | SHFL_INFO_SIZE, &buf_len,
+                                   &info);
+               if (err) {
+                       vboxsf_close(sbi->root, params.handle);
+                       return err;
+               }
+
+               /* the host may have given us different attr then requested */
+               sf_i->force_restat = 1;
+       }
+
+       vboxsf_close(sbi->root, params.handle);
+
+       /* Update the inode with what the host has actually given us. */
+       if (sf_i->force_restat)
+               vboxsf_inode_revalidate(dentry);
+
+       return 0;
+}
+
+/*
+ * [dentry] contains string encoded in coding system that corresponds
+ * to [sbi]->nls, we must convert it to UTF8 here.
+ * Returns a shfl_string allocated through __getname (must be freed using
+ * __putname), or an ERR_PTR on error.
+ */
+struct shfl_string *vboxsf_path_from_dentry(struct vboxsf_sbi *sbi,
+                                           struct dentry *dentry)
+{
+       struct shfl_string *shfl_path;
+       int path_len, out_len, nb;
+       char *buf, *path;
+       wchar_t uni;
+       u8 *out;
+
+       buf = __getname();
+       if (!buf)
+               return ERR_PTR(-ENOMEM);
+
+       path = dentry_path_raw(dentry, buf, PATH_MAX);
+       if (IS_ERR(path)) {
+               __putname(buf);
+               return (struct shfl_string *)path;
+       }
+       path_len = strlen(path);
+
+       if (sbi->nls) {
+               shfl_path = __getname();
+               if (!shfl_path) {
+                       __putname(buf);
+                       return ERR_PTR(-ENOMEM);
+               }
+
+               out = shfl_path->string.utf8;
+               out_len = PATH_MAX - SHFLSTRING_HEADER_SIZE - 1;
+
+               while (path_len) {
+                       nb = sbi->nls->char2uni(path, path_len, &uni);
+                       if (nb < 0) {
+                               __putname(shfl_path);
+                               __putname(buf);
+                               return ERR_PTR(-EINVAL);
+                       }
+                       path += nb;
+                       path_len -= nb;
+
+                       nb = utf32_to_utf8(uni, out, out_len);
+                       if (nb < 0) {
+                               __putname(shfl_path);
+                               __putname(buf);
+                               return ERR_PTR(-ENAMETOOLONG);
+                       }
+                       out += nb;
+                       out_len -= nb;
+               }
+               *out = 0;
+               shfl_path->length = out - shfl_path->string.utf8;
+               shfl_path->size = shfl_path->length + 1;
+               __putname(buf);
+       } else {
+               if ((SHFLSTRING_HEADER_SIZE + path_len + 1) > PATH_MAX) {
+                       __putname(buf);
+                       return ERR_PTR(-ENAMETOOLONG);
+               }
+               /*
+                * dentry_path stores the name at the end of buf, but the
+                * shfl_string string we return must be properly aligned.
+                */
+               shfl_path = (struct shfl_string *)buf;
+               memmove(shfl_path->string.utf8, path, path_len);
+               shfl_path->string.utf8[path_len] = 0;
+               shfl_path->length = path_len;
+               shfl_path->size = path_len + 1;
+       }
+
+       return shfl_path;
+}
+
+int vboxsf_nlscpy(struct vboxsf_sbi *sbi, char *name, size_t name_bound_len,
+                 const unsigned char *utf8_name, size_t utf8_len)
+{
+       const char *in;
+       char *out;
+       size_t out_len;
+       size_t out_bound_len;
+       size_t in_bound_len;
+
+       in = utf8_name;
+       in_bound_len = utf8_len;
+
+       out = name;
+       out_len = 0;
+       /* Reserve space for terminating 0 */
+       out_bound_len = name_bound_len - 1;
+
+       while (in_bound_len) {
+               int nb;
+               unicode_t uni;
+
+               nb = utf8_to_utf32(in, in_bound_len, &uni);
+               if (nb < 0)
+                       return -EINVAL;
+
+               in += nb;
+               in_bound_len -= nb;
+
+               nb = sbi->nls->uni2char(uni, out, out_bound_len);
+               if (nb < 0)
+                       return nb;
+
+               out += nb;
+               out_bound_len -= nb;
+               out_len += nb;
+       }
+
+       *out = 0;
+
+       return 0;
+}
+
+static struct vboxsf_dir_buf *vboxsf_dir_buf_alloc(struct list_head *list)
+{
+       struct vboxsf_dir_buf *b;
+
+       b = kmalloc(sizeof(*b), GFP_KERNEL);
+       if (!b)
+               return NULL;
+
+       b->buf = kmalloc(DIR_BUFFER_SIZE, GFP_KERNEL);
+       if (!b->buf) {
+               kfree(b);
+               return NULL;
+       }
+
+       b->entries = 0;
+       b->used = 0;
+       b->free = DIR_BUFFER_SIZE;
+       list_add(&b->head, list);
+
+       return b;
+}
+
+static void vboxsf_dir_buf_free(struct vboxsf_dir_buf *b)
+{
+       list_del(&b->head);
+       kfree(b->buf);
+       kfree(b);
+}
+
+struct vboxsf_dir_info *vboxsf_dir_info_alloc(void)
+{
+       struct vboxsf_dir_info *p;
+
+       p = kmalloc(sizeof(*p), GFP_KERNEL);
+       if (!p)
+               return NULL;
+
+       INIT_LIST_HEAD(&p->info_list);
+       return p;
+}
+
+void vboxsf_dir_info_free(struct vboxsf_dir_info *p)
+{
+       struct list_head *list, *pos, *tmp;
+
+       list = &p->info_list;
+       list_for_each_safe(pos, tmp, list) {
+               struct vboxsf_dir_buf *b;
+
+               b = list_entry(pos, struct vboxsf_dir_buf, head);
+               vboxsf_dir_buf_free(b);
+       }
+       kfree(p);
+}
+
+int vboxsf_dir_read_all(struct vboxsf_sbi *sbi, struct vboxsf_dir_info *sf_d,
+                       u64 handle)
+{
+       struct vboxsf_dir_buf *b;
+       u32 entries, size;
+       int err = 0;
+       void *buf;
+
+       /* vboxsf_dirinfo returns 1 on end of dir */
+       while (err == 0) {
+               b = vboxsf_dir_buf_alloc(&sf_d->info_list);
+               if (!b) {
+                       err = -ENOMEM;
+                       break;
+               }
+
+               buf = b->buf;
+               size = b->free;
+
+               err = vboxsf_dirinfo(sbi->root, handle, NULL, 0, 0,
+                                    &size, buf, &entries);
+               if (err < 0)
+                       break;
+
+               b->entries += entries;
+               b->free -= size;
+               b->used += size;
+       }
+
+       if (b && b->used == 0)
+               vboxsf_dir_buf_free(b);
+
+       /* -EILSEQ means the host could not translate a filename, ignore */
+       if (err > 0 || err == -EILSEQ)
+               err = 0;
+
+       return err;
+}
diff --git a/drivers/staging/vboxsf/vboxsf_wrappers.c b/drivers/staging/vboxsf/vboxsf_wrappers.c
new file mode 100644 (file)
index 0000000..bfc78a0
--- /dev/null
@@ -0,0 +1,371 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Wrapper functions for the shfl host calls.
+ *
+ * Copyright (C) 2006-2018 Oracle Corporation
+ */
+
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vbox_err.h>
+#include <linux/vbox_utils.h>
+#include "vfsmod.h"
+
+#define SHFL_REQUEST \
+       (VMMDEV_REQUESTOR_KERNEL | VMMDEV_REQUESTOR_USR_DRV_OTHER | \
+        VMMDEV_REQUESTOR_CON_DONT_KNOW | VMMDEV_REQUESTOR_TRUST_NOT_GIVEN)
+
+static u32 vboxsf_client_id;
+
+int vboxsf_connect(void)
+{
+       struct vbg_dev *gdev;
+       struct vmmdev_hgcm_service_location loc;
+       int err, vbox_status;
+
+       loc.type = VMMDEV_HGCM_LOC_LOCALHOST_EXISTING;
+       strcpy(loc.u.localhost.service_name, "VBoxSharedFolders");
+
+       gdev = vbg_get_gdev();
+       if (IS_ERR(gdev))
+               return -ENODEV; /* No guest-device */
+
+       err = vbg_hgcm_connect(gdev, SHFL_REQUEST, &loc,
+                              &vboxsf_client_id, &vbox_status);
+       vbg_put_gdev(gdev);
+
+       return err ? err : vbg_status_code_to_errno(vbox_status);
+}
+
+void vboxsf_disconnect(void)
+{
+       struct vbg_dev *gdev;
+       int vbox_status;
+
+       gdev = vbg_get_gdev();
+       if (IS_ERR(gdev))
+               return;   /* guest-device is gone, already disconnected */
+
+       vbg_hgcm_disconnect(gdev, SHFL_REQUEST, vboxsf_client_id, &vbox_status);
+       vbg_put_gdev(gdev);
+}
+
+static int vboxsf_call(u32 function, void *parms, u32 parm_count, int *status)
+{
+       struct vbg_dev *gdev;
+       int err, vbox_status;
+
+       gdev = vbg_get_gdev();
+       if (IS_ERR(gdev))
+               return -ESHUTDOWN; /* guest-dev removed underneath us */
+
+       err = vbg_hgcm_call(gdev, SHFL_REQUEST, vboxsf_client_id, function,
+                           U32_MAX, parms, parm_count, &vbox_status);
+       vbg_put_gdev(gdev);
+
+       if (err < 0)
+               return err;
+
+       if (status)
+               *status = vbox_status;
+
+       return vbg_status_code_to_errno(vbox_status);
+}
+
+int vboxsf_map_folder(struct shfl_string *folder_name, u32 *root)
+{
+       struct shfl_map_folder parms;
+       int err, status;
+
+       parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL;
+       parms.path.u.pointer.size = shfl_string_buf_size(folder_name);
+       parms.path.u.pointer.u.linear_addr = (uintptr_t)folder_name;
+
+       parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
+       parms.root.u.value32 = 0;
+
+       parms.delimiter.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
+       parms.delimiter.u.value32 = '/';
+
+       parms.case_sensitive.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
+       parms.case_sensitive.u.value32 = 1;
+
+       err = vboxsf_call(SHFL_FN_MAP_FOLDER, &parms, SHFL_CPARMS_MAP_FOLDER,
+                         &status);
+       if (err == -ENOSYS && status == VERR_NOT_IMPLEMENTED)
+               vbg_err("%s: Error host is too old\n", __func__);
+
+       *root = parms.root.u.value32;
+       return err;
+}
+
+int vboxsf_unmap_folder(u32 root)
+{
+       struct shfl_unmap_folder parms;
+
+       parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
+       parms.root.u.value32 = root;
+
+       return vboxsf_call(SHFL_FN_UNMAP_FOLDER, &parms,
+                          SHFL_CPARMS_UNMAP_FOLDER, NULL);
+}
+
+/**
+ * vboxsf_create - Create a new file or folder
+ * @root:         Root of the shared folder in which to create the file
+ * @parsed_path:  The path of the file or folder relative to the shared folder
+ * @param:        create_parms Parameters for file/folder creation.
+ *
+ * Create a new file or folder or open an existing one in a shared folder.
+ * Note this function always returns 0 / success unless an exceptional condition
+ * occurs - out of memory, invalid arguments, etc. If the file or folder could
+ * not be opened or created, create_parms->handle will be set to
+ * SHFL_HANDLE_NIL on return.  In this case the value in create_parms->result
+ * provides information as to why (e.g. SHFL_FILE_EXISTS), create_parms->result
+ * is also set on success as additional information.
+ *
+ * Returns:
+ * 0 or negative errno value.
+ */
+int vboxsf_create(u32 root, struct shfl_string *parsed_path,
+                 struct shfl_createparms *create_parms)
+{
+       struct shfl_create parms;
+
+       parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
+       parms.root.u.value32 = root;
+
+       parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL;
+       parms.path.u.pointer.size = shfl_string_buf_size(parsed_path);
+       parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path;
+
+       parms.parms.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL;
+       parms.parms.u.pointer.size = sizeof(struct shfl_createparms);
+       parms.parms.u.pointer.u.linear_addr = (uintptr_t)create_parms;
+
+       return vboxsf_call(SHFL_FN_CREATE, &parms, SHFL_CPARMS_CREATE, NULL);
+}
+
+int vboxsf_close(u32 root, u64 handle)
+{
+       struct shfl_close parms;
+
+       parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
+       parms.root.u.value32 = root;
+
+       parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT;
+       parms.handle.u.value64 = handle;
+
+       return vboxsf_call(SHFL_FN_CLOSE, &parms, SHFL_CPARMS_CLOSE, NULL);
+}
+
+int vboxsf_remove(u32 root, struct shfl_string *parsed_path, u32 flags)
+{
+       struct shfl_remove parms;
+
+       parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
+       parms.root.u.value32 = root;
+
+       parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN;
+       parms.path.u.pointer.size = shfl_string_buf_size(parsed_path);
+       parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path;
+
+       parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
+       parms.flags.u.value32 = flags;
+
+       return vboxsf_call(SHFL_FN_REMOVE, &parms, SHFL_CPARMS_REMOVE, NULL);
+}
+
+int vboxsf_rename(u32 root, struct shfl_string *src_path,
+                 struct shfl_string *dest_path, u32 flags)
+{
+       struct shfl_rename parms;
+
+       parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
+       parms.root.u.value32 = root;
+
+       parms.src.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN;
+       parms.src.u.pointer.size = shfl_string_buf_size(src_path);
+       parms.src.u.pointer.u.linear_addr = (uintptr_t)src_path;
+
+       parms.dest.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN;
+       parms.dest.u.pointer.size = shfl_string_buf_size(dest_path);
+       parms.dest.u.pointer.u.linear_addr = (uintptr_t)dest_path;
+
+       parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
+       parms.flags.u.value32 = flags;
+
+       return vboxsf_call(SHFL_FN_RENAME, &parms, SHFL_CPARMS_RENAME, NULL);
+}
+
+int vboxsf_read(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf)
+{
+       struct shfl_read parms;
+       int err;
+
+       parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
+       parms.root.u.value32 = root;
+
+       parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT;
+       parms.handle.u.value64 = handle;
+       parms.offset.type = VMMDEV_HGCM_PARM_TYPE_64BIT;
+       parms.offset.u.value64 = offset;
+       parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
+       parms.cb.u.value32 = *buf_len;
+       parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT;
+       parms.buffer.u.pointer.size = *buf_len;
+       parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf;
+
+       err = vboxsf_call(SHFL_FN_READ, &parms, SHFL_CPARMS_READ, NULL);
+
+       *buf_len = parms.cb.u.value32;
+       return err;
+}
+
+int vboxsf_write(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf)
+{
+       struct shfl_write parms;
+       int err;
+
+       parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
+       parms.root.u.value32 = root;
+
+       parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT;
+       parms.handle.u.value64 = handle;
+       parms.offset.type = VMMDEV_HGCM_PARM_TYPE_64BIT;
+       parms.offset.u.value64 = offset;
+       parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
+       parms.cb.u.value32 = *buf_len;
+       parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN;
+       parms.buffer.u.pointer.size = *buf_len;
+       parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf;
+
+       err = vboxsf_call(SHFL_FN_WRITE, &parms, SHFL_CPARMS_WRITE, NULL);
+
+       *buf_len = parms.cb.u.value32;
+       return err;
+}
+
+/* Returns 0 on success, 1 on end-of-dir, negative errno otherwise */
+int vboxsf_dirinfo(u32 root, u64 handle,
+                  struct shfl_string *parsed_path, u32 flags, u32 index,
+                  u32 *buf_len, struct shfl_dirinfo *buf, u32 *file_count)
+{
+       struct shfl_list parms;
+       int err, status;
+
+       parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
+       parms.root.u.value32 = root;
+
+       parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT;
+       parms.handle.u.value64 = handle;
+       parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
+       parms.flags.u.value32 = flags;
+       parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
+       parms.cb.u.value32 = *buf_len;
+       if (parsed_path) {
+               parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN;
+               parms.path.u.pointer.size = shfl_string_buf_size(parsed_path);
+               parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path;
+       } else {
+               parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_IN;
+               parms.path.u.pointer.size = 0;
+               parms.path.u.pointer.u.linear_addr = 0;
+       }
+
+       parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT;
+       parms.buffer.u.pointer.size = *buf_len;
+       parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf;
+
+       parms.resume_point.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
+       parms.resume_point.u.value32 = index;
+       parms.file_count.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
+       parms.file_count.u.value32 = 0; /* out parameter only */
+
+       err = vboxsf_call(SHFL_FN_LIST, &parms, SHFL_CPARMS_LIST, &status);
+       if (err == -ENODATA && status == VERR_NO_MORE_FILES)
+               err = 1;
+
+       *buf_len = parms.cb.u.value32;
+       *file_count = parms.file_count.u.value32;
+       return err;
+}
+
+int vboxsf_fsinfo(u32 root, u64 handle, u32 flags,
+                 u32 *buf_len, void *buf)
+{
+       struct shfl_information parms;
+       int err;
+
+       parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
+       parms.root.u.value32 = root;
+
+       parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT;
+       parms.handle.u.value64 = handle;
+       parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
+       parms.flags.u.value32 = flags;
+       parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
+       parms.cb.u.value32 = *buf_len;
+       parms.info.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL;
+       parms.info.u.pointer.size = *buf_len;
+       parms.info.u.pointer.u.linear_addr = (uintptr_t)buf;
+
+       err = vboxsf_call(SHFL_FN_INFORMATION, &parms, SHFL_CPARMS_INFORMATION,
+                         NULL);
+
+       *buf_len = parms.cb.u.value32;
+       return err;
+}
+
+int vboxsf_readlink(u32 root, struct shfl_string *parsed_path,
+                   u32 buf_len, u8 *buf)
+{
+       struct shfl_readLink parms;
+
+       parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
+       parms.root.u.value32 = root;
+
+       parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN;
+       parms.path.u.pointer.size = shfl_string_buf_size(parsed_path);
+       parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path;
+
+       parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT;
+       parms.buffer.u.pointer.size = buf_len;
+       parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf;
+
+       return vboxsf_call(SHFL_FN_READLINK, &parms, SHFL_CPARMS_READLINK,
+                          NULL);
+}
+
+int vboxsf_symlink(u32 root, struct shfl_string *new_path,
+                  struct shfl_string *old_path, struct shfl_fsobjinfo *buf)
+{
+       struct shfl_symlink parms;
+
+       parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
+       parms.root.u.value32 = root;
+
+       parms.new_path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN;
+       parms.new_path.u.pointer.size = shfl_string_buf_size(new_path);
+       parms.new_path.u.pointer.u.linear_addr = (uintptr_t)new_path;
+
+       parms.old_path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN;
+       parms.old_path.u.pointer.size = shfl_string_buf_size(old_path);
+       parms.old_path.u.pointer.u.linear_addr = (uintptr_t)old_path;
+
+       parms.info.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT;
+       parms.info.u.pointer.size = sizeof(struct shfl_fsobjinfo);
+       parms.info.u.pointer.u.linear_addr = (uintptr_t)buf;
+
+       return vboxsf_call(SHFL_FN_SYMLINK, &parms, SHFL_CPARMS_SYMLINK, NULL);
+}
+
+int vboxsf_set_utf8(void)
+{
+       return vboxsf_call(SHFL_FN_SET_UTF8, NULL, 0, NULL);
+}
+
+int vboxsf_set_symlinks(void)
+{
+       return vboxsf_call(SHFL_FN_SET_SYMLINKS, NULL, 0, NULL);
+}
diff --git a/drivers/staging/vboxsf/vfsmod.h b/drivers/staging/vboxsf/vfsmod.h
new file mode 100644 (file)
index 0000000..18f95b0
--- /dev/null
@@ -0,0 +1,137 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * VirtualBox Guest Shared Folders support: module header.
+ *
+ * Copyright (C) 2006-2018 Oracle Corporation
+ */
+
+#ifndef VFSMOD_H
+#define VFSMOD_H
+
+#include <linux/backing-dev.h>
+#include <linux/idr.h>
+#include "shfl_hostintf.h"
+
+#define DIR_BUFFER_SIZE SZ_16K
+
+/* The cast is to prevent assignment of void * to pointers of arbitrary type */
+#define VBOXSF_SBI(sb) ((struct vboxsf_sbi *)(sb)->s_fs_info)
+#define VBOXSF_I(i)    container_of(i, struct vboxsf_inode, vfs_inode)
+
+struct vboxsf_options {
+       unsigned long ttl;
+       kuid_t uid;
+       kgid_t gid;
+       bool dmode_set;
+       bool fmode_set;
+       umode_t dmode;
+       umode_t fmode;
+       umode_t dmask;
+       umode_t fmask;
+};
+
+struct vboxsf_fs_context {
+       struct vboxsf_options o;
+       char *nls_name;
+};
+
+/* per-shared folder information */
+struct vboxsf_sbi {
+       struct vboxsf_options o;
+       struct shfl_fsobjinfo root_info;
+       struct idr ino_idr;
+       spinlock_t ino_idr_lock; /* This protects ino_idr */
+       struct nls_table *nls;
+       u32 next_generation;
+       u32 root;
+       int bdi_id;
+};
+
+/* per-inode information */
+struct vboxsf_inode {
+       /* some information was changed, update data on next revalidate */
+       int force_restat;
+       /* list of open handles for this inode + lock protecting it */
+       struct list_head handle_list;
+       /* This mutex protects handle_list accesses */
+       struct mutex handle_list_mutex;
+       /* The VFS inode struct */
+       struct inode vfs_inode;
+};
+
+struct vboxsf_dir_info {
+       struct list_head info_list;
+};
+
+struct vboxsf_dir_buf {
+       size_t entries;
+       size_t free;
+       size_t used;
+       void *buf;
+       struct list_head head;
+};
+
+/* globals */
+extern const struct inode_operations vboxsf_dir_iops;
+extern const struct inode_operations vboxsf_lnk_iops;
+extern const struct inode_operations vboxsf_reg_iops;
+extern const struct file_operations vboxsf_dir_fops;
+extern const struct file_operations vboxsf_reg_fops;
+extern const struct address_space_operations vboxsf_reg_aops;
+extern const struct dentry_operations vboxsf_dentry_ops;
+
+/* from utils.c */
+struct inode *vboxsf_new_inode(struct super_block *sb);
+void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
+                      const struct shfl_fsobjinfo *info);
+int vboxsf_create_at_dentry(struct dentry *dentry,
+                           struct shfl_createparms *params);
+int vboxsf_stat(struct vboxsf_sbi *sbi, struct shfl_string *path,
+               struct shfl_fsobjinfo *info);
+int vboxsf_stat_dentry(struct dentry *dentry, struct shfl_fsobjinfo *info);
+int vboxsf_inode_revalidate(struct dentry *dentry);
+int vboxsf_getattr(const struct path *path, struct kstat *kstat,
+                  u32 request_mask, unsigned int query_flags);
+int vboxsf_setattr(struct dentry *dentry, struct iattr *iattr);
+struct shfl_string *vboxsf_path_from_dentry(struct vboxsf_sbi *sbi,
+                                           struct dentry *dentry);
+int vboxsf_nlscpy(struct vboxsf_sbi *sbi, char *name, size_t name_bound_len,
+                 const unsigned char *utf8_name, size_t utf8_len);
+struct vboxsf_dir_info *vboxsf_dir_info_alloc(void);
+void vboxsf_dir_info_free(struct vboxsf_dir_info *p);
+int vboxsf_dir_read_all(struct vboxsf_sbi *sbi, struct vboxsf_dir_info *sf_d,
+                       u64 handle);
+
+/* from vboxsf_wrappers.c */
+int vboxsf_connect(void);
+void vboxsf_disconnect(void);
+
+int vboxsf_create(u32 root, struct shfl_string *parsed_path,
+                 struct shfl_createparms *create_parms);
+
+int vboxsf_close(u32 root, u64 handle);
+int vboxsf_remove(u32 root, struct shfl_string *parsed_path, u32 flags);
+int vboxsf_rename(u32 root, struct shfl_string *src_path,
+                 struct shfl_string *dest_path, u32 flags);
+
+int vboxsf_read(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf);
+int vboxsf_write(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf);
+
+int vboxsf_dirinfo(u32 root, u64 handle,
+                  struct shfl_string *parsed_path, u32 flags, u32 index,
+                  u32 *buf_len, struct shfl_dirinfo *buf, u32 *file_count);
+int vboxsf_fsinfo(u32 root, u64 handle, u32 flags,
+                 u32 *buf_len, void *buf);
+
+int vboxsf_map_folder(struct shfl_string *folder_name, u32 *root);
+int vboxsf_unmap_folder(u32 root);
+
+int vboxsf_readlink(u32 root, struct shfl_string *parsed_path,
+                   u32 buf_len, u8 *buf);
+int vboxsf_symlink(u32 root, struct shfl_string *new_path,
+                  struct shfl_string *old_path, struct shfl_fsobjinfo *buf);
+
+int vboxsf_set_utf8(void);
+int vboxsf_set_symlinks(void);
+
+#endif
index eee1998c4b189179b6de81f2fa98717bb5395176..fac38c842ac50bce8f53441369f61fd8cd20a0bd 100644 (file)
@@ -469,10 +469,8 @@ static int prism2_connect(struct wiphy *wiphy, struct net_device *dev,
        /* Set the encryption - we only support wep */
        if (is_wep) {
                if (sme->key) {
-                       if (sme->key_idx >= NUM_WEPKEYS) {
-                               err = -EINVAL;
-                               goto exit;
-                       }
+                       if (sme->key_idx >= NUM_WEPKEYS)
+                               return -EINVAL;
 
                        result = prism2_domibset_uint32(wlandev,
                                DIDMIB_DOT11SMT_PRIVACYTABLE_WEPDEFAULTKEYID,
index c70caf4ea49012006c3a8ac754ff9e1c16399ec7..a2b5c796bbc4a5dfee4513bd93a6449e57d4dbc4 100644 (file)
@@ -1831,7 +1831,7 @@ static void cxgbit_fw4_ack(struct cxgbit_sock *csk, struct sk_buff *skb)
 
        while (credits) {
                struct sk_buff *p = cxgbit_sock_peek_wr(csk);
-               const u32 csum = (__force u32)p->csum;
+               u32 csum;
 
                if (unlikely(!p)) {
                        pr_err("csk 0x%p,%u, cr %u,%u+%u, empty.\n",
@@ -1840,6 +1840,7 @@ static void cxgbit_fw4_ack(struct cxgbit_sock *csk, struct sk_buff *skb)
                        break;
                }
 
+               csum = (__force u32)p->csum;
                if (unlikely(credits < csum)) {
                        pr_warn("csk 0x%p,%u, cr %u,%u+%u, < %u.\n",
                                csk,  csk->tid,
index 04bf2acd3800ded1e776c087f7e2145bf219553b..2d19f0e332b0157695c6e7e87fdc7a25ab3b59cd 100644 (file)
@@ -1074,27 +1074,6 @@ passthrough_parse_cdb(struct se_cmd *cmd,
        struct se_device *dev = cmd->se_dev;
        unsigned int size;
 
-       /*
-        * Clear a lun set in the cdb if the initiator talking to use spoke
-        * and old standards version, as we can't assume the underlying device
-        * won't choke up on it.
-        */
-       switch (cdb[0]) {
-       case READ_10: /* SBC - RDProtect */
-       case READ_12: /* SBC - RDProtect */
-       case READ_16: /* SBC - RDProtect */
-       case SEND_DIAGNOSTIC: /* SPC - SELF-TEST Code */
-       case VERIFY: /* SBC - VRProtect */
-       case VERIFY_16: /* SBC - VRProtect */
-       case WRITE_VERIFY: /* SBC - VRProtect */
-       case WRITE_VERIFY_12: /* SBC - VRProtect */
-       case MAINTENANCE_IN: /* SPC - Parameter Data Format for SA RTPG */
-               break;
-       default:
-               cdb[1] &= 0x1f; /* clear logical unit number */
-               break;
-       }
-
        /*
         * For REPORT LUNS we always need to emulate the response, for everything
         * else, pass it up.
index 391f39776c6ab8c6205ef0a122079887e53220ea..6b9865c786ba3b146143624295592a19629cae3f 100644 (file)
@@ -88,7 +88,7 @@ struct cpufreq_cooling_device {
        struct cpufreq_policy *policy;
        struct list_head node;
        struct time_in_idle *idle_time;
-       struct dev_pm_qos_request qos_req;
+       struct freq_qos_request qos_req;
 };
 
 static DEFINE_IDA(cpufreq_ida);
@@ -331,7 +331,7 @@ static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev,
 
        cpufreq_cdev->cpufreq_state = state;
 
-       return dev_pm_qos_update_request(&cpufreq_cdev->qos_req,
+       return freq_qos_update_request(&cpufreq_cdev->qos_req,
                                cpufreq_cdev->freq_table[state].frequency);
 }
 
@@ -615,9 +615,9 @@ __cpufreq_cooling_register(struct device_node *np,
                cooling_ops = &cpufreq_cooling_ops;
        }
 
-       ret = dev_pm_qos_add_request(dev, &cpufreq_cdev->qos_req,
-                                    DEV_PM_QOS_MAX_FREQUENCY,
-                                    cpufreq_cdev->freq_table[0].frequency);
+       ret = freq_qos_add_request(&policy->constraints,
+                                  &cpufreq_cdev->qos_req, FREQ_QOS_MAX,
+                                  cpufreq_cdev->freq_table[0].frequency);
        if (ret < 0) {
                pr_err("%s: Failed to add freq constraint (%d)\n", __func__,
                       ret);
@@ -637,7 +637,7 @@ __cpufreq_cooling_register(struct device_node *np,
        return cdev;
 
 remove_qos_req:
-       dev_pm_qos_remove_request(&cpufreq_cdev->qos_req);
+       freq_qos_remove_request(&cpufreq_cdev->qos_req);
 remove_ida:
        ida_simple_remove(&cpufreq_ida, cpufreq_cdev->id);
 free_table:
@@ -736,7 +736,7 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
        mutex_unlock(&cooling_list_lock);
 
        thermal_cooling_device_unregister(cdev);
-       dev_pm_qos_remove_request(&cpufreq_cdev->qos_req);
+       freq_qos_remove_request(&cpufreq_cdev->qos_req);
        ida_simple_remove(&cpufreq_ida, cpufreq_cdev->id);
        kfree(cpufreq_cdev->idle_time);
        kfree(cpufreq_cdev->freq_table);
index 61cd09cef943d3dc29630d39cf67fe151ce3c05b..6795851aac95bcbbdda27b4c1d0416cc189b26c8 100644 (file)
@@ -80,7 +80,6 @@ static void icl_nhi_lc_mailbox_cmd(struct tb_nhi *nhi, enum icl_lc_mailbox_cmd c
 {
        u32 data;
 
-       pci_read_config_dword(nhi->pdev, VS_CAP_19, &data);
        data = (cmd << VS_CAP_19_CMD_SHIFT) & VS_CAP_19_CMD_MASK;
        pci_write_config_dword(nhi->pdev, VS_CAP_19, data | VS_CAP_19_VALID);
 }
index 410bf1bceeee4f661850af632f49a11db672c5b8..5ea8db667e839449c13d6707495e1a0899aaee37 100644 (file)
@@ -896,12 +896,13 @@ int tb_dp_port_set_hops(struct tb_port *port, unsigned int video,
  */
 bool tb_dp_port_is_enabled(struct tb_port *port)
 {
-       u32 data;
+       u32 data[2];
 
-       if (tb_port_read(port, &data, TB_CFG_PORT, port->cap_adap, 1))
+       if (tb_port_read(port, data, TB_CFG_PORT, port->cap_adap,
+                        ARRAY_SIZE(data)))
                return false;
 
-       return !!(data & (TB_DP_VIDEO_EN | TB_DP_AUX_EN));
+       return !!(data[0] & (TB_DP_VIDEO_EN | TB_DP_AUX_EN));
 }
 
 /**
@@ -914,19 +915,21 @@ bool tb_dp_port_is_enabled(struct tb_port *port)
  */
 int tb_dp_port_enable(struct tb_port *port, bool enable)
 {
-       u32 data;
+       u32 data[2];
        int ret;
 
-       ret = tb_port_read(port, &data, TB_CFG_PORT, port->cap_adap, 1);
+       ret = tb_port_read(port, data, TB_CFG_PORT, port->cap_adap,
+                          ARRAY_SIZE(data));
        if (ret)
                return ret;
 
        if (enable)
-               data |= TB_DP_VIDEO_EN | TB_DP_AUX_EN;
+               data[0] |= TB_DP_VIDEO_EN | TB_DP_AUX_EN;
        else
-               data &= ~(TB_DP_VIDEO_EN | TB_DP_AUX_EN);
+               data[0] &= ~(TB_DP_VIDEO_EN | TB_DP_AUX_EN);
 
-       return tb_port_write(port, &data, TB_CFG_PORT, port->cap_adap, 1);
+       return tb_port_write(port, data, TB_CFG_PORT, port->cap_adap,
+                            ARRAY_SIZE(data));
 }
 
 /* switch utility functions */
@@ -1031,13 +1034,6 @@ static int tb_switch_set_authorized(struct tb_switch *sw, unsigned int val)
        if (sw->authorized)
                goto unlock;
 
-       /*
-        * Make sure there is no PCIe rescan ongoing when a new PCIe
-        * tunnel is created. Otherwise the PCIe rescan code might find
-        * the new tunnel too early.
-        */
-       pci_lock_rescan_remove();
-
        switch (val) {
        /* Approve switch */
        case 1:
@@ -1057,8 +1053,6 @@ static int tb_switch_set_authorized(struct tb_switch *sw, unsigned int val)
                break;
        }
 
-       pci_unlock_rescan_remove();
-
        if (!ret) {
                sw->authorized = val;
                /* Notify status change to the userspace */
index 02c5aff58a7408d3509f020b18f5a5cd93eac6c6..8df89e9cd2542d05dff25fc377b08d30a9efe5c5 100644 (file)
@@ -72,8 +72,8 @@ static int serial_8250_men_mcb_probe(struct mcb_device *mdev,
 {
        struct serial_8250_men_mcb_data *data;
        struct resource *mem;
-       unsigned int num_ports;
-       unsigned int i;
+       int num_ports;
+       int i;
        void __iomem *membase;
 
        mem = mcb_get_resource(mdev, IORESOURCE_MEM);
@@ -88,7 +88,7 @@ static int serial_8250_men_mcb_probe(struct mcb_device *mdev,
        dev_dbg(&mdev->dev, "found a 16z%03u with %u ports\n",
                mdev->id, num_ports);
 
-       if (num_ports == 0 || num_ports > 4) {
+       if (num_ports <= 0 || num_ports > 4) {
                dev_err(&mdev->dev, "unexpected number of ports: %u\n",
                        num_ports);
                return -ENODEV;
@@ -133,7 +133,7 @@ static int serial_8250_men_mcb_probe(struct mcb_device *mdev,
 
 static void serial_8250_men_mcb_remove(struct mcb_device *mdev)
 {
-       unsigned int num_ports, i;
+       int num_ports, i;
        struct serial_8250_men_mcb_data *data = mcb_get_drvdata(mdev);
 
        if (!data)
index 1109dc5a4c39a959848a9bc2c0ac2552fda87da8..c2123ef8d8a3320f11f1fa3b7b0363dc3886cd86 100644 (file)
@@ -166,7 +166,6 @@ static int cdns3_core_init_role(struct cdns3 *cdns)
                goto err;
 
        switch (cdns->dr_mode) {
-       case USB_DR_MODE_UNKNOWN:
        case USB_DR_MODE_OTG:
                ret = cdns3_hw_role_switch(cdns);
                if (ret)
@@ -182,6 +181,9 @@ static int cdns3_core_init_role(struct cdns3 *cdns)
                if (ret)
                        goto err;
                break;
+       default:
+               ret = -EINVAL;
+               goto err;
        }
 
        return ret;
index 2ca280f4c054124b48d0900c61fe9b47a131d9f6..4c1e755093039d0582ca30922d620009441aed0c 100644 (file)
@@ -1145,6 +1145,14 @@ static void cdns3_transfer_completed(struct cdns3_device *priv_dev,
                request = cdns3_next_request(&priv_ep->pending_req_list);
                priv_req = to_cdns3_request(request);
 
+               trb = priv_ep->trb_pool + priv_ep->dequeue;
+
+               /* Request was dequeued and TRB was changed to TRB_LINK. */
+               if (TRB_FIELD_TO_TYPE(trb->control) == TRB_LINK) {
+                       trace_cdns3_complete_trb(priv_ep, trb);
+                       cdns3_move_deq_to_next_trb(priv_req);
+               }
+
                /* Re-select endpoint. It could be changed by other CPU during
                 * handling usb_gadget_giveback_request.
                 */
@@ -2067,6 +2075,7 @@ int cdns3_gadget_ep_dequeue(struct usb_ep *ep,
        struct usb_request *req, *req_temp;
        struct cdns3_request *priv_req;
        struct cdns3_trb *link_trb;
+       u8 req_on_hw_ring = 0;
        unsigned long flags;
        int ret = 0;
 
@@ -2083,8 +2092,10 @@ int cdns3_gadget_ep_dequeue(struct usb_ep *ep,
 
        list_for_each_entry_safe(req, req_temp, &priv_ep->pending_req_list,
                                 list) {
-               if (request == req)
+               if (request == req) {
+                       req_on_hw_ring = 1;
                        goto found;
+               }
        }
 
        list_for_each_entry_safe(req, req_temp, &priv_ep->deferred_req_list,
@@ -2096,27 +2107,21 @@ int cdns3_gadget_ep_dequeue(struct usb_ep *ep,
        goto not_found;
 
 found:
-
-       if (priv_ep->wa1_trb == priv_req->trb)
-               cdns3_wa1_restore_cycle_bit(priv_ep);
-
        link_trb = priv_req->trb;
-       cdns3_move_deq_to_next_trb(priv_req);
-       cdns3_gadget_giveback(priv_ep, priv_req, -ECONNRESET);
-
-       /* Update ring */
-       request = cdns3_next_request(&priv_ep->deferred_req_list);
-       if (request) {
-               priv_req = to_cdns3_request(request);
 
+       /* Update ring only if removed request is on pending_req_list list */
+       if (req_on_hw_ring) {
                link_trb->buffer = TRB_BUFFER(priv_ep->trb_pool_dma +
                                              (priv_req->start_trb * TRB_SIZE));
                link_trb->control = (link_trb->control & TRB_CYCLE) |
-                                   TRB_TYPE(TRB_LINK) | TRB_CHAIN | TRB_TOGGLE;
-       } else {
-               priv_ep->flags |= EP_UPDATE_EP_TRBADDR;
+                                   TRB_TYPE(TRB_LINK) | TRB_CHAIN;
+
+               if (priv_ep->wa1_trb == priv_req->trb)
+                       cdns3_wa1_restore_cycle_bit(priv_ep);
        }
 
+       cdns3_gadget_giveback(priv_ep, priv_req, -ECONNRESET);
+
 not_found:
        spin_unlock_irqrestore(&priv_dev->lock, flags);
        return ret;
@@ -2324,8 +2329,6 @@ static void cdns3_gadget_config(struct cdns3_device *priv_dev)
        writel(USB_CONF_CLK2OFFDS | USB_CONF_L1DS, &regs->usb_conf);
 
        cdns3_configure_dmult(priv_dev, NULL);
-
-       cdns3_gadget_pullup(&priv_dev->gadget, 1);
 }
 
 /**
@@ -2340,9 +2343,35 @@ static int cdns3_gadget_udc_start(struct usb_gadget *gadget,
 {
        struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget);
        unsigned long flags;
+       enum usb_device_speed max_speed = driver->max_speed;
 
        spin_lock_irqsave(&priv_dev->lock, flags);
        priv_dev->gadget_driver = driver;
+
+       /* limit speed if necessary */
+       max_speed = min(driver->max_speed, gadget->max_speed);
+
+       switch (max_speed) {
+       case USB_SPEED_FULL:
+               writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);
+               writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
+               break;
+       case USB_SPEED_HIGH:
+               writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
+               break;
+       case USB_SPEED_SUPER:
+               break;
+       default:
+               dev_err(priv_dev->dev,
+                       "invalid maximum_speed parameter %d\n",
+                       max_speed);
+               /* fall through */
+       case USB_SPEED_UNKNOWN:
+               /* default to superspeed */
+               max_speed = USB_SPEED_SUPER;
+               break;
+       }
+
        cdns3_gadget_config(priv_dev);
        spin_unlock_irqrestore(&priv_dev->lock, flags);
        return 0;
@@ -2376,6 +2405,8 @@ static int cdns3_gadget_udc_stop(struct usb_gadget *gadget)
                writel(EP_CMD_EPRST, &priv_dev->regs->ep_cmd);
                readl_poll_timeout_atomic(&priv_dev->regs->ep_cmd, val,
                                          !(val & EP_CMD_EPRST), 1, 100);
+
+               priv_ep->flags &= ~EP_CLAIMED;
        }
 
        /* disable interrupt for device */
@@ -2570,12 +2601,7 @@ static int cdns3_gadget_start(struct cdns3 *cdns)
        /* Check the maximum_speed parameter */
        switch (max_speed) {
        case USB_SPEED_FULL:
-               writel(USB_CONF_SFORCE_FS, &priv_dev->regs->usb_conf);
-               writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
-               break;
        case USB_SPEED_HIGH:
-               writel(USB_CONF_USB3DIS, &priv_dev->regs->usb_conf);
-               break;
        case USB_SPEED_SUPER:
                break;
        default:
@@ -2708,8 +2734,6 @@ static int cdns3_gadget_suspend(struct cdns3 *cdns, bool do_wakeup)
        /* disable interrupt for device */
        writel(0, &priv_dev->regs->usb_ien);
 
-       cdns3_gadget_pullup(&priv_dev->gadget, 0);
-
        return 0;
 }
 
index b498a170b7e881f3e98f6ba860db27cb928f4fde..ae11810f882618c052e4d4315315380fa74e3f9e 100644 (file)
@@ -12,7 +12,6 @@
 #ifdef CONFIG_USB_CDNS3_HOST
 
 int cdns3_host_init(struct cdns3 *cdns);
-void cdns3_host_exit(struct cdns3 *cdns);
 
 #else
 
index 2733a8f71fcd6572634899324e5152538e00299d..ad788bf3fe4f6f8e9ac1865fd3d6c6ca518ba341 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/platform_device.h>
 #include "core.h"
 #include "drd.h"
+#include "host-export.h"
 
 static int __cdns3_host_init(struct cdns3 *cdns)
 {
index fb8bd60c83f487d67c1b1479dc2d1cf86d1a8bed..0d8e3f3804a3f87e8d8a29442f2db0a50c621ac7 100644 (file)
@@ -445,6 +445,7 @@ static void usblp_cleanup(struct usblp *usblp)
        kfree(usblp->readbuf);
        kfree(usblp->device_id_string);
        kfree(usblp->statusbuf);
+       usb_put_intf(usblp->intf);
        kfree(usblp);
 }
 
@@ -1113,7 +1114,7 @@ static int usblp_probe(struct usb_interface *intf,
        init_waitqueue_head(&usblp->wwait);
        init_usb_anchor(&usblp->urbs);
        usblp->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
-       usblp->intf = intf;
+       usblp->intf = usb_get_intf(intf);
 
        /* Malloc device ID string buffer to the largest expected length,
         * since we can re-query it on an ioctl and a dynamic string
@@ -1198,6 +1199,7 @@ abort:
        kfree(usblp->readbuf);
        kfree(usblp->statusbuf);
        kfree(usblp->device_id_string);
+       usb_put_intf(usblp->intf);
        kfree(usblp);
 abort_ret:
        return retval;
index 151a74a54386226c1f0fc6a134556151a5bd28dc..1ac1095bfeac8448ff7fae2179a033fb558bb6ff 100644 (file)
@@ -348,6 +348,11 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
 
        /* Validate the wMaxPacketSize field */
        maxp = usb_endpoint_maxp(&endpoint->desc);
+       if (maxp == 0) {
+               dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has wMaxPacketSize 0, skipping\n",
+                   cfgno, inum, asnum, d->bEndpointAddress);
+               goto skip_to_next_endpoint_or_interface_descriptor;
+       }
 
        /* Find the highest legal maxpacket size for this endpoint */
        i = 0;          /* additional transactions per microframe */
index 89abc6078703f218b48d4239ac60c0c11a1d71a3..556a876c7896251811288f99968f8636ecf310b6 100644 (file)
@@ -102,6 +102,7 @@ config USB_DWC3_MESON_G12A
        depends on ARCH_MESON || COMPILE_TEST
        default USB_DWC3
        select USB_ROLE_SWITCH
+       select REGMAP_MMIO
        help
          Support USB2/3 functionality in Amlogic G12A platforms.
         Say 'Y' or 'M' if you have one such device.
index 999ce5e84d3c934758855e5272d2c11f4d62a367..97d6ae3c4df2fc572f4fbae2f0d6aa9c513d1d88 100644 (file)
@@ -312,8 +312,7 @@ static void dwc3_frame_length_adjustment(struct dwc3 *dwc)
 
        reg = dwc3_readl(dwc->regs, DWC3_GFLADJ);
        dft = reg & DWC3_GFLADJ_30MHZ_MASK;
-       if (!dev_WARN_ONCE(dwc->dev, dft == dwc->fladj,
-           "request value same as default, ignoring\n")) {
+       if (dft != dwc->fladj) {
                reg &= ~DWC3_GFLADJ_30MHZ_MASK;
                reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | dwc->fladj;
                dwc3_writel(dwc->regs, DWC3_GFLADJ, reg);
index 5e8e18222f922c00a646063b91599be7100feb41..023f0357efd77eae3182aaf596120b8a8847fa8b 100644 (file)
@@ -258,7 +258,7 @@ static int dwc3_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
 
        ret = platform_device_add_properties(dwc->dwc3, p);
        if (ret < 0)
-               return ret;
+               goto err;
 
        ret = dwc3_pci_quirks(dwc);
        if (ret)
index 86dc1db788a9e5e02fa11b2564ed1c417f0b0d92..a9aba716bf80be70c3a8df033f8e468f59477560 100644 (file)
@@ -707,6 +707,12 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep)
 
                dwc3_gadget_giveback(dep, req, -ESHUTDOWN);
        }
+
+       while (!list_empty(&dep->cancelled_list)) {
+               req = next_request(&dep->cancelled_list);
+
+               dwc3_gadget_giveback(dep, req, -ESHUTDOWN);
+       }
 }
 
 /**
index d516e8d6cd7f939bd6c7bad09ded75bd40353d80..5ec54b69c29c58b1432b3c42b9d9bc58238db1d7 100644 (file)
@@ -2170,14 +2170,18 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev)
                        usb_ep_dequeue(cdev->gadget->ep0, cdev->os_desc_req);
 
                kfree(cdev->os_desc_req->buf);
+               cdev->os_desc_req->buf = NULL;
                usb_ep_free_request(cdev->gadget->ep0, cdev->os_desc_req);
+               cdev->os_desc_req = NULL;
        }
        if (cdev->req) {
                if (cdev->setup_pending)
                        usb_ep_dequeue(cdev->gadget->ep0, cdev->req);
 
                kfree(cdev->req->buf);
+               cdev->req->buf = NULL;
                usb_ep_free_request(cdev->gadget->ep0, cdev->req);
+               cdev->req = NULL;
        }
        cdev->next_string_id = 0;
        device_remove_file(&cdev->gadget->dev, &dev_attr_suspended);
index 02512994289463b43107c49871995816272db5f8..33852c2b29d1a5cdf7d04ed35b66873e138e2e1b 100644 (file)
@@ -61,6 +61,8 @@ struct gadget_info {
        bool use_os_desc;
        char b_vendor_code;
        char qw_sign[OS_STRING_QW_SIGN_LEN];
+       spinlock_t spinlock;
+       bool unbind;
 };
 
 static inline struct gadget_info *to_gadget_info(struct config_item *item)
@@ -1244,6 +1246,7 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
        int                             ret;
 
        /* the gi->lock is hold by the caller */
+       gi->unbind = 0;
        cdev->gadget = gadget;
        set_gadget_data(gadget, cdev);
        ret = composite_dev_prepare(composite, cdev);
@@ -1376,31 +1379,128 @@ static void configfs_composite_unbind(struct usb_gadget *gadget)
 {
        struct usb_composite_dev        *cdev;
        struct gadget_info              *gi;
+       unsigned long flags;
 
        /* the gi->lock is hold by the caller */
 
        cdev = get_gadget_data(gadget);
        gi = container_of(cdev, struct gadget_info, cdev);
+       spin_lock_irqsave(&gi->spinlock, flags);
+       gi->unbind = 1;
+       spin_unlock_irqrestore(&gi->spinlock, flags);
 
        kfree(otg_desc[0]);
        otg_desc[0] = NULL;
        purge_configs_funcs(gi);
        composite_dev_cleanup(cdev);
        usb_ep_autoconfig_reset(cdev->gadget);
+       spin_lock_irqsave(&gi->spinlock, flags);
        cdev->gadget = NULL;
        set_gadget_data(gadget, NULL);
+       spin_unlock_irqrestore(&gi->spinlock, flags);
+}
+
+static int configfs_composite_setup(struct usb_gadget *gadget,
+               const struct usb_ctrlrequest *ctrl)
+{
+       struct usb_composite_dev *cdev;
+       struct gadget_info *gi;
+       unsigned long flags;
+       int ret;
+
+       cdev = get_gadget_data(gadget);
+       if (!cdev)
+               return 0;
+
+       gi = container_of(cdev, struct gadget_info, cdev);
+       spin_lock_irqsave(&gi->spinlock, flags);
+       cdev = get_gadget_data(gadget);
+       if (!cdev || gi->unbind) {
+               spin_unlock_irqrestore(&gi->spinlock, flags);
+               return 0;
+       }
+
+       ret = composite_setup(gadget, ctrl);
+       spin_unlock_irqrestore(&gi->spinlock, flags);
+       return ret;
+}
+
+static void configfs_composite_disconnect(struct usb_gadget *gadget)
+{
+       struct usb_composite_dev *cdev;
+       struct gadget_info *gi;
+       unsigned long flags;
+
+       cdev = get_gadget_data(gadget);
+       if (!cdev)
+               return;
+
+       gi = container_of(cdev, struct gadget_info, cdev);
+       spin_lock_irqsave(&gi->spinlock, flags);
+       cdev = get_gadget_data(gadget);
+       if (!cdev || gi->unbind) {
+               spin_unlock_irqrestore(&gi->spinlock, flags);
+               return;
+       }
+
+       composite_disconnect(gadget);
+       spin_unlock_irqrestore(&gi->spinlock, flags);
+}
+
+static void configfs_composite_suspend(struct usb_gadget *gadget)
+{
+       struct usb_composite_dev *cdev;
+       struct gadget_info *gi;
+       unsigned long flags;
+
+       cdev = get_gadget_data(gadget);
+       if (!cdev)
+               return;
+
+       gi = container_of(cdev, struct gadget_info, cdev);
+       spin_lock_irqsave(&gi->spinlock, flags);
+       cdev = get_gadget_data(gadget);
+       if (!cdev || gi->unbind) {
+               spin_unlock_irqrestore(&gi->spinlock, flags);
+               return;
+       }
+
+       composite_suspend(gadget);
+       spin_unlock_irqrestore(&gi->spinlock, flags);
+}
+
+static void configfs_composite_resume(struct usb_gadget *gadget)
+{
+       struct usb_composite_dev *cdev;
+       struct gadget_info *gi;
+       unsigned long flags;
+
+       cdev = get_gadget_data(gadget);
+       if (!cdev)
+               return;
+
+       gi = container_of(cdev, struct gadget_info, cdev);
+       spin_lock_irqsave(&gi->spinlock, flags);
+       cdev = get_gadget_data(gadget);
+       if (!cdev || gi->unbind) {
+               spin_unlock_irqrestore(&gi->spinlock, flags);
+               return;
+       }
+
+       composite_resume(gadget);
+       spin_unlock_irqrestore(&gi->spinlock, flags);
 }
 
 static const struct usb_gadget_driver configfs_driver_template = {
        .bind           = configfs_composite_bind,
        .unbind         = configfs_composite_unbind,
 
-       .setup          = composite_setup,
-       .reset          = composite_disconnect,
-       .disconnect     = composite_disconnect,
+       .setup          = configfs_composite_setup,
+       .reset          = configfs_composite_disconnect,
+       .disconnect     = configfs_composite_disconnect,
 
-       .suspend        = composite_suspend,
-       .resume         = composite_resume,
+       .suspend        = configfs_composite_suspend,
+       .resume         = configfs_composite_resume,
 
        .max_speed      = USB_SPEED_SUPER,
        .driver = {
index 86ffc83078647b2ba1dfbfc6e796489af15c9192..1d0d8952a74bfa4a786c6966fff1bbcbc66438a7 100644 (file)
@@ -449,9 +449,11 @@ static void submit_request(struct usba_ep *ep, struct usba_request *req)
                next_fifo_transaction(ep, req);
                if (req->last_transaction) {
                        usba_ep_writel(ep, CTL_DIS, USBA_TX_PK_RDY);
-                       usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE);
+                       if (ep_is_control(ep))
+                               usba_ep_writel(ep, CTL_ENB, USBA_TX_COMPLETE);
                } else {
-                       usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
+                       if (ep_is_control(ep))
+                               usba_ep_writel(ep, CTL_DIS, USBA_TX_COMPLETE);
                        usba_ep_writel(ep, CTL_ENB, USBA_TX_PK_RDY);
                }
        }
index 92af8dc98c3dcd1d5f0c474293916636049d8332..51fa614b40794310e3216f5b086442d969b5b3be 100644 (file)
@@ -98,6 +98,17 @@ int usb_ep_enable(struct usb_ep *ep)
        if (ep->enabled)
                goto out;
 
+       /* UDC drivers can't handle endpoints with maxpacket size 0 */
+       if (usb_endpoint_maxp(ep->desc) == 0) {
+               /*
+                * We should log an error message here, but we can't call
+                * dev_err() because there's no way to find the gadget
+                * given only ep.
+                */
+               ret = -EINVAL;
+               goto out;
+       }
+
        ret = ep->ops->enable(ep, ep->desc);
        if (ret)
                goto out;
index 20141c3096f68ab4a2f51762dc0617715e473633..9a05863b28768a3e8fea85b376935baf961d36e9 100644 (file)
@@ -2576,7 +2576,7 @@ static int fsl_udc_remove(struct platform_device *pdev)
        dma_pool_destroy(udc_controller->td_pool);
        free_irq(udc_controller->irq, udc_controller);
        iounmap(dr_regs);
-       if (pdata->operating_mode == FSL_USB2_DR_DEVICE)
+       if (res && (pdata->operating_mode == FSL_USB2_DR_DEVICE))
                release_mem_region(res->start, resource_size(res));
 
        /* free udc --wait for the release() finished */
index 2b1f3cc7819bfb0b49a118a545486efaec024c2c..bf6c81e2f8cccf9e2d6644d728141e7991749de9 100644 (file)
@@ -1177,11 +1177,11 @@ static void udc_pop_fifo(struct lpc32xx_udc *udc, u8 *data, u32 bytes)
                        tmp = readl(USBD_RXDATA(udc->udp_baseaddr));
 
                        bl = bytes - n;
-                       if (bl > 3)
-                               bl = 3;
+                       if (bl > 4)
+                               bl = 4;
 
                        for (i = 0; i < bl; i++)
-                               data[n + i] = (u8) ((tmp >> (n * 8)) & 0xFF);
+                               data[n + i] = (u8) ((tmp >> (i * 8)) & 0xFF);
                }
                break;
 
index e098f16c01cb5dedef6e4084c33a7ec39f43acdc..33703140233aa592001eaeb64298b5f119da9b0a 100644 (file)
@@ -1544,10 +1544,10 @@ static void usb3_set_device_address(struct renesas_usb3 *usb3, u16 addr)
 static bool usb3_std_req_set_address(struct renesas_usb3 *usb3,
                                     struct usb_ctrlrequest *ctrl)
 {
-       if (ctrl->wValue >= 128)
+       if (le16_to_cpu(ctrl->wValue) >= 128)
                return true;    /* stall */
 
-       usb3_set_device_address(usb3, ctrl->wValue);
+       usb3_set_device_address(usb3, le16_to_cpu(ctrl->wValue));
        usb3_set_p0_con_for_no_data(usb3);
 
        return false;
@@ -1582,6 +1582,7 @@ static bool usb3_std_req_get_status(struct renesas_usb3 *usb3,
        struct renesas_usb3_ep *usb3_ep;
        int num;
        u16 status = 0;
+       __le16 tx_data;
 
        switch (ctrl->bRequestType & USB_RECIP_MASK) {
        case USB_RECIP_DEVICE:
@@ -1604,10 +1605,10 @@ static bool usb3_std_req_get_status(struct renesas_usb3 *usb3,
        }
 
        if (!stall) {
-               status = cpu_to_le16(status);
+               tx_data = cpu_to_le16(status);
                dev_dbg(usb3_to_dev(usb3), "get_status: req = %p\n",
                        usb_req_to_usb3_req(usb3->ep0_req));
-               usb3_pipe0_internal_xfer(usb3, &status, sizeof(status),
+               usb3_pipe0_internal_xfer(usb3, &tx_data, sizeof(tx_data),
                                         usb3_pipe0_get_status_completion);
        }
 
@@ -1772,7 +1773,7 @@ static bool usb3_std_req_set_sel(struct renesas_usb3 *usb3,
 static bool usb3_std_req_set_configuration(struct renesas_usb3 *usb3,
                                           struct usb_ctrlrequest *ctrl)
 {
-       if (ctrl->wValue > 0)
+       if (le16_to_cpu(ctrl->wValue) > 0)
                usb3_set_bit(usb3, USB_COM_CON_CONF, USB3_USB_COM_CON);
        else
                usb3_clear_bit(usb3, USB_COM_CON_CONF, USB3_USB_COM_CON);
index 7ba6afc7ef230ed69da605ce48e31cac4783a709..76c3f29562d2b9d2e3263f3d3dc1b45b92728140 100644 (file)
@@ -202,10 +202,10 @@ static void xhci_ring_dump_segment(struct seq_file *s,
                trb = &seg->trbs[i];
                dma = seg->dma + i * sizeof(*trb);
                seq_printf(s, "%pad: %s\n", &dma,
-                          xhci_decode_trb(trb->generic.field[0],
-                                          trb->generic.field[1],
-                                          trb->generic.field[2],
-                                          trb->generic.field[3]));
+                          xhci_decode_trb(le32_to_cpu(trb->generic.field[0]),
+                                          le32_to_cpu(trb->generic.field[1]),
+                                          le32_to_cpu(trb->generic.field[2]),
+                                          le32_to_cpu(trb->generic.field[3])));
        }
 }
 
@@ -263,10 +263,10 @@ static int xhci_slot_context_show(struct seq_file *s, void *unused)
        xhci = hcd_to_xhci(bus_to_hcd(dev->udev->bus));
        slot_ctx = xhci_get_slot_ctx(xhci, dev->out_ctx);
        seq_printf(s, "%pad: %s\n", &dev->out_ctx->dma,
-                  xhci_decode_slot_context(slot_ctx->dev_info,
-                                           slot_ctx->dev_info2,
-                                           slot_ctx->tt_info,
-                                           slot_ctx->dev_state));
+                  xhci_decode_slot_context(le32_to_cpu(slot_ctx->dev_info),
+                                           le32_to_cpu(slot_ctx->dev_info2),
+                                           le32_to_cpu(slot_ctx->tt_info),
+                                           le32_to_cpu(slot_ctx->dev_state)));
 
        return 0;
 }
@@ -286,10 +286,10 @@ static int xhci_endpoint_context_show(struct seq_file *s, void *unused)
                ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, dci);
                dma = dev->out_ctx->dma + dci * CTX_SIZE(xhci->hcc_params);
                seq_printf(s, "%pad: %s\n", &dma,
-                          xhci_decode_ep_context(ep_ctx->ep_info,
-                                                 ep_ctx->ep_info2,
-                                                 ep_ctx->deq,
-                                                 ep_ctx->tx_info));
+                          xhci_decode_ep_context(le32_to_cpu(ep_ctx->ep_info),
+                                                 le32_to_cpu(ep_ctx->ep_info2),
+                                                 le64_to_cpu(ep_ctx->deq),
+                                                 le32_to_cpu(ep_ctx->tx_info)));
        }
 
        return 0;
index 85ceb43e34056097fb63c8391a05c67a1acf80ed..e7aab31fd9a5a38b260e498947de7808259098d0 100644 (file)
@@ -3330,6 +3330,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                        if (xhci_urb_suitable_for_idt(urb)) {
                                memcpy(&send_addr, urb->transfer_buffer,
                                       trb_buff_len);
+                               le64_to_cpus(&send_addr);
                                field |= TRB_IDT;
                        }
                }
@@ -3475,6 +3476,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                if (xhci_urb_suitable_for_idt(urb)) {
                        memcpy(&addr, urb->transfer_buffer,
                               urb->transfer_buffer_length);
+                       le64_to_cpus(&addr);
                        field |= TRB_IDT;
                } else {
                        addr = (u64) urb->transfer_dma;
index 517ec3206f6eb0681075c75c2c432b27350b51df..6c17e3fe181a2113464d4120984ad1125405888c 100644 (file)
@@ -3071,6 +3071,48 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, unsigned int ep_index,
        }
 }
 
+static void xhci_endpoint_disable(struct usb_hcd *hcd,
+                                 struct usb_host_endpoint *host_ep)
+{
+       struct xhci_hcd         *xhci;
+       struct xhci_virt_device *vdev;
+       struct xhci_virt_ep     *ep;
+       struct usb_device       *udev;
+       unsigned long           flags;
+       unsigned int            ep_index;
+
+       xhci = hcd_to_xhci(hcd);
+rescan:
+       spin_lock_irqsave(&xhci->lock, flags);
+
+       udev = (struct usb_device *)host_ep->hcpriv;
+       if (!udev || !udev->slot_id)
+               goto done;
+
+       vdev = xhci->devs[udev->slot_id];
+       if (!vdev)
+               goto done;
+
+       ep_index = xhci_get_endpoint_index(&host_ep->desc);
+       ep = &vdev->eps[ep_index];
+       if (!ep)
+               goto done;
+
+       /* wait for hub_tt_work to finish clearing hub TT */
+       if (ep->ep_state & EP_CLEARING_TT) {
+               spin_unlock_irqrestore(&xhci->lock, flags);
+               schedule_timeout_uninterruptible(1);
+               goto rescan;
+       }
+
+       if (ep->ep_state)
+               xhci_dbg(xhci, "endpoint disable with ep_state 0x%x\n",
+                        ep->ep_state);
+done:
+       host_ep->hcpriv = NULL;
+       spin_unlock_irqrestore(&xhci->lock, flags);
+}
+
 /*
  * Called after usb core issues a clear halt control message.
  * The host side of the halt should already be cleared by a reset endpoint
@@ -5238,20 +5280,13 @@ static void xhci_clear_tt_buffer_complete(struct usb_hcd *hcd,
        unsigned int ep_index;
        unsigned long flags;
 
-       /*
-        * udev might be NULL if tt buffer is cleared during a failed device
-        * enumeration due to a halted control endpoint. Usb core might
-        * have allocated a new udev for the next enumeration attempt.
-        */
-
        xhci = hcd_to_xhci(hcd);
+
+       spin_lock_irqsave(&xhci->lock, flags);
        udev = (struct usb_device *)ep->hcpriv;
-       if (!udev)
-               return;
        slot_id = udev->slot_id;
        ep_index = xhci_get_endpoint_index(&ep->desc);
 
-       spin_lock_irqsave(&xhci->lock, flags);
        xhci->devs[slot_id]->eps[ep_index].ep_state &= ~EP_CLEARING_TT;
        xhci_ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
        spin_unlock_irqrestore(&xhci->lock, flags);
@@ -5288,6 +5323,7 @@ static const struct hc_driver xhci_hc_driver = {
        .free_streams =         xhci_free_streams,
        .add_endpoint =         xhci_add_endpoint,
        .drop_endpoint =        xhci_drop_endpoint,
+       .endpoint_disable =     xhci_endpoint_disable,
        .endpoint_reset =       xhci_endpoint_reset,
        .check_bandwidth =      xhci_check_bandwidth,
        .reset_bandwidth =      xhci_reset_bandwidth,
index f3108d85e768086293954e8a869b79d4a75901e2..8f86b4ebca898b32e572cba6006ca01ab414b2ea 100644 (file)
@@ -380,10 +380,7 @@ static int ld_usb_release(struct inode *inode, struct file *file)
                goto exit;
        }
 
-       if (mutex_lock_interruptible(&dev->mutex)) {
-               retval = -ERESTARTSYS;
-               goto exit;
-       }
+       mutex_lock(&dev->mutex);
 
        if (dev->open_count != 1) {
                retval = -ENODEV;
@@ -467,7 +464,7 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count,
 
        /* wait for data */
        spin_lock_irq(&dev->rbsl);
-       if (dev->ring_head == dev->ring_tail) {
+       while (dev->ring_head == dev->ring_tail) {
                dev->interrupt_in_done = 0;
                spin_unlock_irq(&dev->rbsl);
                if (file->f_flags & O_NONBLOCK) {
@@ -477,15 +474,20 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count,
                retval = wait_event_interruptible(dev->read_wait, dev->interrupt_in_done);
                if (retval < 0)
                        goto unlock_exit;
-       } else {
-               spin_unlock_irq(&dev->rbsl);
+
+               spin_lock_irq(&dev->rbsl);
        }
+       spin_unlock_irq(&dev->rbsl);
 
        /* actual_buffer contains actual_length + interrupt_in_buffer */
        actual_buffer = (size_t *)(dev->ring_buffer + dev->ring_tail * (sizeof(size_t)+dev->interrupt_in_endpoint_size));
+       if (*actual_buffer > dev->interrupt_in_endpoint_size) {
+               retval = -EIO;
+               goto unlock_exit;
+       }
        bytes_to_read = min(count, *actual_buffer);
        if (bytes_to_read < *actual_buffer)
-               dev_warn(&dev->intf->dev, "Read buffer overflow, %zd bytes dropped\n",
+               dev_warn(&dev->intf->dev, "Read buffer overflow, %zu bytes dropped\n",
                         *actual_buffer-bytes_to_read);
 
        /* copy one interrupt_in_buffer from ring_buffer into userspace */
@@ -493,11 +495,11 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count,
                retval = -EFAULT;
                goto unlock_exit;
        }
-       dev->ring_tail = (dev->ring_tail+1) % ring_buffer_size;
-
        retval = bytes_to_read;
 
        spin_lock_irq(&dev->rbsl);
+       dev->ring_tail = (dev->ring_tail + 1) % ring_buffer_size;
+
        if (dev->buffer_overflow) {
                dev->buffer_overflow = 0;
                spin_unlock_irq(&dev->rbsl);
@@ -560,8 +562,9 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer,
        /* write the data into interrupt_out_buffer from userspace */
        bytes_to_write = min(count, write_buffer_size*dev->interrupt_out_endpoint_size);
        if (bytes_to_write < count)
-               dev_warn(&dev->intf->dev, "Write buffer overflow, %zd bytes dropped\n", count-bytes_to_write);
-       dev_dbg(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n",
+               dev_warn(&dev->intf->dev, "Write buffer overflow, %zu bytes dropped\n",
+                       count - bytes_to_write);
+       dev_dbg(&dev->intf->dev, "%s: count = %zu, bytes_to_write = %zu\n",
                __func__, count, bytes_to_write);
 
        if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) {
@@ -578,7 +581,7 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer,
                                         1 << 8, 0,
                                         dev->interrupt_out_buffer,
                                         bytes_to_write,
-                                        USB_CTRL_SET_TIMEOUT * HZ);
+                                        USB_CTRL_SET_TIMEOUT);
                if (retval < 0)
                        dev_err(&dev->intf->dev,
                                "Couldn't submit HID_REQ_SET_REPORT %d\n",
@@ -693,10 +696,9 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id *
                dev_warn(&intf->dev, "Interrupt out endpoint not found (using control endpoint instead)\n");
 
        dev->interrupt_in_endpoint_size = usb_endpoint_maxp(dev->interrupt_in_endpoint);
-       dev->ring_buffer =
-               kmalloc_array(ring_buffer_size,
-                             sizeof(size_t) + dev->interrupt_in_endpoint_size,
-                             GFP_KERNEL);
+       dev->ring_buffer = kcalloc(ring_buffer_size,
+                       sizeof(size_t) + dev->interrupt_in_endpoint_size,
+                       GFP_KERNEL);
        if (!dev->ring_buffer)
                goto error;
        dev->interrupt_in_buffer = kmalloc(dev->interrupt_in_endpoint_size, GFP_KERNEL);
index 9d4c52a7ebe02254d32cdb13d1f6107790d6d759..23061f1526b4e03be818de50add926e982187ae2 100644 (file)
@@ -419,10 +419,7 @@ static int tower_release (struct inode *inode, struct file *file)
                goto exit;
        }
 
-       if (mutex_lock_interruptible(&dev->lock)) {
-               retval = -ERESTARTSYS;
-               goto exit;
-       }
+       mutex_lock(&dev->lock);
 
        if (dev->open_count != 1) {
                dev_dbg(&dev->udev->dev, "%s: device not opened exactly once\n",
@@ -881,7 +878,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
                                  get_version_reply,
                                  sizeof(*get_version_reply),
                                  1000);
-       if (result < sizeof(*get_version_reply)) {
+       if (result != sizeof(*get_version_reply)) {
                if (result >= 0)
                        result = -EIO;
                dev_err(idev, "get version request failed: %d\n", result);
index c3d5c1206eec808bb96d54ef5cc713219c39c93e..9dd02160cca97e9242aac125d104df80cd72e3e3 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/platform_device.h>
 
 #include "mtu3.h"
+#include "mtu3_dr.h"
 #include "mtu3_debug.h"
 #include "mtu3_trace.h"
 
index 4c3de777ef6cf691abd606d0b98081c6f10143ce..a3c30b609433bacca844f3d0c0c174c6301e0d51 100644 (file)
@@ -162,17 +162,17 @@ void usbhs_usbreq_get_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req)
        req->bRequest           = (val >> 8) & 0xFF;
        req->bRequestType       = (val >> 0) & 0xFF;
 
-       req->wValue     = usbhs_read(priv, USBVAL);
-       req->wIndex     = usbhs_read(priv, USBINDX);
-       req->wLength    = usbhs_read(priv, USBLENG);
+       req->wValue     = cpu_to_le16(usbhs_read(priv, USBVAL));
+       req->wIndex     = cpu_to_le16(usbhs_read(priv, USBINDX));
+       req->wLength    = cpu_to_le16(usbhs_read(priv, USBLENG));
 }
 
 void usbhs_usbreq_set_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req)
 {
        usbhs_write(priv, USBREQ,  (req->bRequest << 8) | req->bRequestType);
-       usbhs_write(priv, USBVAL,  req->wValue);
-       usbhs_write(priv, USBINDX, req->wIndex);
-       usbhs_write(priv, USBLENG, req->wLength);
+       usbhs_write(priv, USBVAL,  le16_to_cpu(req->wValue));
+       usbhs_write(priv, USBINDX, le16_to_cpu(req->wIndex));
+       usbhs_write(priv, USBLENG, le16_to_cpu(req->wLength));
 
        usbhs_bset(priv, DCPCTR, SUREQ, SUREQ);
 }
index e5ef56991dbac3a9607575ca7414e5c24bf11320..cd38d74b322320db3c9607f4ab30758d701949be 100644 (file)
@@ -265,7 +265,7 @@ static int usbhsg_recip_handler_std_set_device(struct usbhs_priv *priv,
        case USB_DEVICE_TEST_MODE:
                usbhsg_recip_handler_std_control_done(priv, uep, ctrl);
                udelay(100);
-               usbhs_sys_set_test_mode(priv, le16_to_cpu(ctrl->wIndex >> 8));
+               usbhs_sys_set_test_mode(priv, le16_to_cpu(ctrl->wIndex) >> 8);
                break;
        default:
                usbhsg_recip_handler_std_control_done(priv, uep, ctrl);
@@ -315,7 +315,7 @@ static void __usbhsg_recip_send_status(struct usbhsg_gpriv *gpriv,
        struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(dcp);
        struct device *dev = usbhsg_gpriv_to_dev(gpriv);
        struct usb_request *req;
-       unsigned short *buf;
+       __le16 *buf;
 
        /* alloc new usb_request for recip */
        req = usb_ep_alloc_request(&dcp->ep, GFP_ATOMIC);
index dd0ad67aa71e619907afdab6dc142a4335684e51..ef23acc9b9ce4bc8fe8ccb8197b42f69928a87b3 100644 (file)
@@ -776,7 +776,6 @@ static void ti_close(struct usb_serial_port *port)
        struct ti_port *tport;
        int port_number;
        int status;
-       int do_unlock;
        unsigned long flags;
 
        tdev = usb_get_serial_data(port->serial);
@@ -800,16 +799,13 @@ static void ti_close(struct usb_serial_port *port)
                        "%s - cannot send close port command, %d\n"
                                                        , __func__, status);
 
-       /* if mutex_lock is interrupted, continue anyway */
-       do_unlock = !mutex_lock_interruptible(&tdev->td_open_close_lock);
-       --tport->tp_tdev->td_open_port_count;
-       if (tport->tp_tdev->td_open_port_count <= 0) {
+       mutex_lock(&tdev->td_open_close_lock);
+       --tdev->td_open_port_count;
+       if (tdev->td_open_port_count == 0) {
                /* last port is closed, shut down interrupt urb */
                usb_kill_urb(port->serial->port[0]->interrupt_in_urb);
-               tport->tp_tdev->td_open_port_count = 0;
        }
-       if (do_unlock)
-               mutex_unlock(&tdev->td_open_close_lock);
+       mutex_unlock(&tdev->td_open_close_lock);
 }
 
 
index 79314d8c94a446b9378aa7d5ebcb9a533e31cf1e..ca3bd58f2025a9957742970122cacd997ba67085 100644 (file)
@@ -559,6 +559,10 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command,
 
        command_port = port->serial->port[COMMAND_PORT];
        command_info = usb_get_serial_port_data(command_port);
+
+       if (command_port->bulk_out_size < datasize + 1)
+               return -EIO;
+
        mutex_lock(&command_info->mutex);
        command_info->command_finished = false;
 
@@ -632,6 +636,7 @@ static void firm_setup_port(struct tty_struct *tty)
        struct device *dev = &port->dev;
        struct whiteheat_port_settings port_settings;
        unsigned int cflag = tty->termios.c_cflag;
+       speed_t baud;
 
        port_settings.port = port->port_number + 1;
 
@@ -692,11 +697,13 @@ static void firm_setup_port(struct tty_struct *tty)
        dev_dbg(dev, "%s - XON = %2x, XOFF = %2x\n", __func__, port_settings.xon, port_settings.xoff);
 
        /* get the baud rate wanted */
-       port_settings.baud = tty_get_baud_rate(tty);
-       dev_dbg(dev, "%s - baud rate = %d\n", __func__, port_settings.baud);
+       baud = tty_get_baud_rate(tty);
+       port_settings.baud = cpu_to_le32(baud);
+       dev_dbg(dev, "%s - baud rate = %u\n", __func__, baud);
 
        /* fixme: should set validated settings */
-       tty_encode_baud_rate(tty, port_settings.baud, port_settings.baud);
+       tty_encode_baud_rate(tty, baud, baud);
+
        /* handle any settings that aren't specified in the tty structure */
        port_settings.lloop = 0;
 
index 00398149cd8ddcf0985dd363d24d66415196cdd8..269e727a92f9c5bbe7c2825d988c06f0e640491c 100644 (file)
@@ -87,7 +87,7 @@ struct whiteheat_simple {
 
 struct whiteheat_port_settings {
        __u8    port;           /* port number (1 to N) */
-       __u32   baud;           /* any value 7 - 460800, firmware calculates
+       __le32  baud;           /* any value 7 - 460800, firmware calculates
                                   best fit; arrives little endian */
        __u8    bits;           /* 5, 6, 7, or 8 */
        __u8    stop;           /* 1 or 2, default 1 (2 = 1.5 if bits = 5) */
index 6737fab9495949c0187364cfce1e7469687da9fa..54a3c8195c969785a6ab2a359a2787f321cce553 100644 (file)
@@ -68,7 +68,6 @@ static const char* host_info(struct Scsi_Host *host)
 static int slave_alloc (struct scsi_device *sdev)
 {
        struct us_data *us = host_to_us(sdev->host);
-       int maxp;
 
        /*
         * Set the INQUIRY transfer length to 36.  We don't use any of
@@ -77,15 +76,6 @@ static int slave_alloc (struct scsi_device *sdev)
         */
        sdev->inquiry_len = 36;
 
-       /*
-        * USB has unusual scatter-gather requirements: the length of each
-        * scatterlist element except the last must be divisible by the
-        * Bulk maxpacket value.  Fortunately this value is always a
-        * power of 2.  Inform the block layer about this requirement.
-        */
-       maxp = usb_maxpacket(us->pusb_dev, us->recv_bulk_pipe, 0);
-       blk_queue_virt_boundary(sdev->request_queue, maxp - 1);
-
        /*
         * Some host controllers may have alignment requirements.
         * We'll play it safe by requiring 512-byte alignment always.
index bf80d6f81f587f4269b2bf7a96d74099f63e9d15..34538253f12cdf6d4213167543b24ed207267f78 100644 (file)
@@ -789,29 +789,9 @@ static int uas_slave_alloc(struct scsi_device *sdev)
 {
        struct uas_dev_info *devinfo =
                (struct uas_dev_info *)sdev->host->hostdata;
-       int maxp;
 
        sdev->hostdata = devinfo;
 
-       /*
-        * We have two requirements here. We must satisfy the requirements
-        * of the physical HC and the demands of the protocol, as we
-        * definitely want no additional memory allocation in this path
-        * ruling out using bounce buffers.
-        *
-        * For a transmission on USB to continue we must never send
-        * a package that is smaller than maxpacket. Hence the length of each
-         * scatterlist element except the last must be divisible by the
-         * Bulk maxpacket value.
-        * If the HC does not ensure that through SG,
-        * the upper layer must do that. We must assume nothing
-        * about the capabilities off the HC, so we use the most
-        * pessimistic requirement.
-        */
-
-       maxp = usb_maxpacket(devinfo->udev, devinfo->data_in_pipe, 0);
-       blk_queue_virt_boundary(sdev->request_queue, maxp - 1);
-
        /*
         * The protocol has no requirements on alignment in the strict sense.
         * Controllers may or may not have alignment restrictions.
index c3803785f6eff23a74c2225cd696a7a69ea1a757..0ae40a13a9fea89650c4200a359530dd7c954281 100644 (file)
@@ -147,7 +147,10 @@ static int vhci_send_cmd_submit(struct vhci_device *vdev)
                }
 
                kfree(iov);
+               /* This is only for isochronous case */
                kfree(iso_buffer);
+               iso_buffer = NULL;
+
                usbip_dbg_vhci_tx("send txdata\n");
 
                total_size += txsize;
index 96fddc1dafc3c4dffd62bf98df51e48a0598febc..d864277ea16f31627ca776769297788995840400 100644 (file)
@@ -1658,7 +1658,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
        struct bus_type *bus = NULL;
        int ret;
        bool resv_msi, msi_remap;
-       phys_addr_t resv_msi_base;
+       phys_addr_t resv_msi_base = 0;
        struct iommu_domain_geometry geo;
        LIST_HEAD(iova_copy);
        LIST_HEAD(group_resv_regions);
index 08ad0d1f04766fe10b8a5829628983ec09f0b561..a0a2d74967ef57eb72f73a3bb5367177421ed2d6 100644 (file)
@@ -852,6 +852,12 @@ static inline int xfer_kern(void *src, void *dst, size_t len)
        return 0;
 }
 
+static inline int kern_xfer(void *dst, void *src, size_t len)
+{
+       memcpy(dst, src, len);
+       return 0;
+}
+
 /**
  * vringh_init_kern - initialize a vringh for a kernelspace vring.
  * @vrh: the vringh to initialize.
@@ -958,7 +964,7 @@ EXPORT_SYMBOL(vringh_iov_pull_kern);
 ssize_t vringh_iov_push_kern(struct vringh_kiov *wiov,
                             const void *src, size_t len)
 {
-       return vringh_iov_xfer(wiov, (void *)src, len, xfer_kern);
+       return vringh_iov_xfer(wiov, (void *)src, len, kern_xfer);
 }
 EXPORT_SYMBOL(vringh_iov_push_kern);
 
index e1035a865fb945f0df23ecede70aafbc4b593a1b..45a6d895a7d7208ee26c1517e5bee5e1d25f65d7 100644 (file)
@@ -29,7 +29,7 @@ static inline void _transp(u32 d[], unsigned int i1, unsigned int i2,
 
 extern void c2p_unsupported(void);
 
-static inline u32 get_mask(unsigned int n)
+static __always_inline u32 get_mask(unsigned int n)
 {
        switch (n) {
        case 1:
@@ -57,7 +57,7 @@ static inline u32 get_mask(unsigned int n)
      *  Transpose operations on 8 32-bit words
      */
 
-static inline void transp8(u32 d[], unsigned int n, unsigned int m)
+static __always_inline void transp8(u32 d[], unsigned int n, unsigned int m)
 {
        u32 mask = get_mask(n);
 
@@ -99,7 +99,7 @@ static inline void transp8(u32 d[], unsigned int n, unsigned int m)
      *  Transpose operations on 4 32-bit words
      */
 
-static inline void transp4(u32 d[], unsigned int n, unsigned int m)
+static __always_inline void transp4(u32 d[], unsigned int n, unsigned int m)
 {
        u32 mask = get_mask(n);
 
@@ -126,7 +126,7 @@ static inline void transp4(u32 d[], unsigned int n, unsigned int m)
      *  Transpose operations on 4 32-bit words (reverse order)
      */
 
-static inline void transp4x(u32 d[], unsigned int n, unsigned int m)
+static __always_inline void transp4x(u32 d[], unsigned int n, unsigned int m)
 {
        u32 mask = get_mask(n);
 
index bdc08244a648dbf0ee58fe8b9dc4e5e36c15dcb8..a8041e451e9ec6ba9982069477520d5df00386c2 100644 (file)
@@ -1499,9 +1499,6 @@ static bool virtqueue_enable_cb_delayed_packed(struct virtqueue *_vq)
                 * counter first before updating event flags.
                 */
                virtio_wmb(vq->weak_barriers);
-       } else {
-               used_idx = vq->last_used_idx;
-               wrap_counter = vq->packed.used_wrap_counter;
        }
 
        if (vq->packed.event_flags_shadow == VRING_PACKED_EVENT_FLAG_DISABLE) {
@@ -1518,7 +1515,9 @@ static bool virtqueue_enable_cb_delayed_packed(struct virtqueue *_vq)
         */
        virtio_mb(vq->weak_barriers);
 
-       if (is_used_desc_packed(vq, used_idx, wrap_counter)) {
+       if (is_used_desc_packed(vq,
+                               vq->last_used_idx,
+                               vq->packed.used_wrap_counter)) {
                END_USE(vq);
                return false;
        }
index b0152fef4fc7e6ba2e292d67329bee2fa845760c..bc60e036627af60bc21b9bad3fdbeae6d742843a 100644 (file)
@@ -288,3 +288,4 @@ module_platform_driver(bd70528_wdt);
 MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
 MODULE_DESCRIPTION("BD70528 watchdog driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:bd70528-wdt");
index 9393be584e723a59156edb89550e9d9229124311..808eeb4779e4dbeb8f94985753d800ec32a15c0b 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/timer.h>
+#include <linux/compat.h>
 #include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/io.h>
@@ -473,6 +474,11 @@ static long cpwd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        return 0;
 }
 
+static long cpwd_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       return cpwd_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
+}
+
 static ssize_t cpwd_write(struct file *file, const char __user *buf,
                          size_t count, loff_t *ppos)
 {
@@ -497,7 +503,7 @@ static ssize_t cpwd_read(struct file *file, char __user *buffer,
 static const struct file_operations cpwd_fops = {
        .owner =                THIS_MODULE,
        .unlocked_ioctl =       cpwd_ioctl,
-       .compat_ioctl =         compat_ptr_ioctl,
+       .compat_ioctl =         cpwd_compat_ioctl,
        .open =                 cpwd_open,
        .write =                cpwd_write,
        .read =                 cpwd_read,
index 7ea5cf54e94a05de72accbf4ab2b28d046ecbf50..8ed89f032ebf29058c6f13ee0b9fb46a31a8588c 100644 (file)
@@ -99,8 +99,14 @@ static int imx_sc_wdt_set_pretimeout(struct watchdog_device *wdog,
 {
        struct arm_smccc_res res;
 
+       /*
+        * SCU firmware calculates pretimeout based on current time
+        * stamp instead of watchdog timeout stamp, need to convert
+        * the pretimeout to SCU firmware's timeout value.
+        */
        arm_smccc_smc(IMX_SIP_TIMER, IMX_SIP_TIMER_SET_PRETIME_WDOG,
-                     pretimeout * 1000, 0, 0, 0, 0, 0, &res);
+                     (wdog->timeout - pretimeout) * 1000, 0, 0, 0,
+                     0, 0, &res);
        if (res.a0)
                return -EACCES;
 
index d17c1a6ed7234c5f0a4581da6ab3f38fc957fe41..5a9ca10fbcfa0b862c6d3a3aebb860af7ddf6545 100644 (file)
@@ -89,8 +89,8 @@ static unsigned int meson_gxbb_wdt_get_timeleft(struct watchdog_device *wdt_dev)
 
        reg = readl(data->reg_base + GXBB_WDT_TCNT_REG);
 
-       return ((reg >> GXBB_WDT_TCNT_CNT_SHIFT) -
-               (reg & GXBB_WDT_TCNT_SETUP_MASK)) / 1000;
+       return ((reg & GXBB_WDT_TCNT_SETUP_MASK) -
+               (reg >> GXBB_WDT_TCNT_CNT_SHIFT)) / 1000;
 }
 
 static const struct watchdog_ops meson_gxbb_wdt_ops = {
index 2d3652004e39c52d6fc73a4c15b98bafa8652e6f..1213179f863c27405dca286393734a9c3e694111 100644 (file)
@@ -163,9 +163,17 @@ static int pm8916_wdt_probe(struct platform_device *pdev)
 
        irq = platform_get_irq(pdev, 0);
        if (irq > 0) {
-               if (devm_request_irq(dev, irq, pm8916_wdt_isr, 0, "pm8916_wdt",
-                                    wdt))
-                       irq = 0;
+               err = devm_request_irq(dev, irq, pm8916_wdt_isr, 0,
+                                      "pm8916_wdt", wdt);
+               if (err)
+                       return err;
+
+               wdt->wdev.info = &pm8916_wdt_pt_ident;
+       } else {
+               if (irq == -EPROBE_DEFER)
+                       return -EPROBE_DEFER;
+
+               wdt->wdev.info = &pm8916_wdt_ident;
        }
 
        /* Configure watchdog to hard-reset mode */
@@ -177,7 +185,6 @@ static int pm8916_wdt_probe(struct platform_device *pdev)
                return err;
        }
 
-       wdt->wdev.info = (irq > 0) ? &pm8916_wdt_pt_ident : &pm8916_wdt_ident,
        wdt->wdev.ops = &pm8916_wdt_ops,
        wdt->wdev.parent = dev;
        wdt->wdev.min_timeout = PM8916_WDT_MIN_TIMEOUT;
index bf7e3f23bba745528f863066c4d0be5224d8d2e1..670700cb1110692c2fc9e763f6ae028654a3d35a 100644 (file)
@@ -1761,6 +1761,7 @@ int btrfs_read_block_groups(struct btrfs_fs_info *info)
                        btrfs_err(info,
 "bg %llu is a mixed block group but filesystem hasn't enabled mixed block groups",
                                  cache->key.objectid);
+                       btrfs_put_block_group(cache);
                        ret = -EINVAL;
                        goto error;
                }
index 19d669d12ca15226237e698630d7514b65004a88..fe2b8765d9e6b4fc6e991028895580a7c5211426 100644 (file)
@@ -734,8 +734,6 @@ struct btrfs_fs_info {
        struct btrfs_workqueue *fixup_workers;
        struct btrfs_workqueue *delayed_workers;
 
-       /* the extent workers do delayed refs on the extent allocation tree */
-       struct btrfs_workqueue *extent_workers;
        struct task_struct *transaction_kthread;
        struct task_struct *cleaner_kthread;
        u32 thread_pool_size;
@@ -2489,8 +2487,7 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
                                     int nitems, bool use_global_rsv);
 void btrfs_subvolume_release_metadata(struct btrfs_fs_info *fs_info,
                                      struct btrfs_block_rsv *rsv);
-void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes,
-                                   bool qgroup_free);
+void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes);
 
 int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes);
 u64 btrfs_account_ro_block_groups_free_space(struct btrfs_space_info *sinfo);
index d949d7d2abed8489baa5318f5e56a0d1462fb5bd..db9f2c58eb4af481158bb8a635a5f6a7872d4877 100644 (file)
@@ -381,7 +381,6 @@ int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes)
 out_qgroup:
        btrfs_qgroup_free_meta_prealloc(root, qgroup_reserve);
 out_fail:
-       btrfs_inode_rsv_release(inode, true);
        if (delalloc_lock)
                mutex_unlock(&inode->delalloc_mutex);
        return ret;
@@ -418,7 +417,6 @@ void btrfs_delalloc_release_metadata(struct btrfs_inode *inode, u64 num_bytes,
  * btrfs_delalloc_release_extents - release our outstanding_extents
  * @inode: the inode to balance the reservation for.
  * @num_bytes: the number of bytes we originally reserved with
- * @qgroup_free: do we need to free qgroup meta reservation or convert them.
  *
  * When we reserve space we increase outstanding_extents for the extents we may
  * add.  Once we've set the range as delalloc or created our ordered extents we
@@ -426,8 +424,7 @@ void btrfs_delalloc_release_metadata(struct btrfs_inode *inode, u64 num_bytes,
  * temporarily tracked outstanding_extents.  This _must_ be used in conjunction
  * with btrfs_delalloc_reserve_metadata.
  */
-void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes,
-                                   bool qgroup_free)
+void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes)
 {
        struct btrfs_fs_info *fs_info = inode->root->fs_info;
        unsigned num_extents;
@@ -441,7 +438,7 @@ void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes,
        if (btrfs_is_testing(fs_info))
                return;
 
-       btrfs_inode_rsv_release(inode, qgroup_free);
+       btrfs_inode_rsv_release(inode, true);
 }
 
 /**
index 044981cf6df9149cd28d0f3c89cbe05b3be39e12..402b61bf345cd55dddd2efed7cf27576ef262a14 100644 (file)
@@ -2008,7 +2008,6 @@ static void btrfs_stop_all_workers(struct btrfs_fs_info *fs_info)
        btrfs_destroy_workqueue(fs_info->readahead_workers);
        btrfs_destroy_workqueue(fs_info->flush_workers);
        btrfs_destroy_workqueue(fs_info->qgroup_rescan_workers);
-       btrfs_destroy_workqueue(fs_info->extent_workers);
        /*
         * Now that all other work queues are destroyed, we can safely destroy
         * the queues used for metadata I/O, since tasks from those other work
@@ -2214,10 +2213,6 @@ static int btrfs_init_workqueues(struct btrfs_fs_info *fs_info,
                                      max_active, 2);
        fs_info->qgroup_rescan_workers =
                btrfs_alloc_workqueue(fs_info, "qgroup-rescan", flags, 1, 0);
-       fs_info->extent_workers =
-               btrfs_alloc_workqueue(fs_info, "extent-refs", flags,
-                                     min_t(u64, fs_devices->num_devices,
-                                           max_active), 8);
 
        if (!(fs_info->workers && fs_info->delalloc_workers &&
              fs_info->submit_workers && fs_info->flush_workers &&
@@ -2228,7 +2223,6 @@ static int btrfs_init_workqueues(struct btrfs_fs_info *fs_info,
              fs_info->endio_freespace_worker && fs_info->rmw_workers &&
              fs_info->caching_workers && fs_info->readahead_workers &&
              fs_info->fixup_workers && fs_info->delayed_workers &&
-             fs_info->extent_workers &&
              fs_info->qgroup_rescan_workers)) {
                return -ENOMEM;
        }
index 27e5b269e729f1de0404fd1811c563a93f47545f..435a502a32261071d3bd4ac4e24d75367a349bbb 100644 (file)
@@ -1692,7 +1692,7 @@ again:
                                    force_page_uptodate);
                if (ret) {
                        btrfs_delalloc_release_extents(BTRFS_I(inode),
-                                                      reserve_bytes, true);
+                                                      reserve_bytes);
                        break;
                }
 
@@ -1704,7 +1704,7 @@ again:
                        if (extents_locked == -EAGAIN)
                                goto again;
                        btrfs_delalloc_release_extents(BTRFS_I(inode),
-                                                      reserve_bytes, true);
+                                                      reserve_bytes);
                        ret = extents_locked;
                        break;
                }
@@ -1772,8 +1772,7 @@ again:
                else
                        free_extent_state(cached_state);
 
-               btrfs_delalloc_release_extents(BTRFS_I(inode), reserve_bytes,
-                                              true);
+               btrfs_delalloc_release_extents(BTRFS_I(inode), reserve_bytes);
                if (ret) {
                        btrfs_drop_pages(pages, num_pages);
                        break;
@@ -2068,25 +2067,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
        struct btrfs_trans_handle *trans;
        struct btrfs_log_ctx ctx;
        int ret = 0, err;
-       u64 len;
 
-       /*
-        * If the inode needs a full sync, make sure we use a full range to
-        * avoid log tree corruption, due to hole detection racing with ordered
-        * extent completion for adjacent ranges, and assertion failures during
-        * hole detection.
-        */
-       if (test_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
-                    &BTRFS_I(inode)->runtime_flags)) {
-               start = 0;
-               end = LLONG_MAX;
-       }
-
-       /*
-        * The range length can be represented by u64, we have to do the typecasts
-        * to avoid signed overflow if it's [0, LLONG_MAX] eg. from fsync()
-        */
-       len = (u64)end - (u64)start + 1;
        trace_btrfs_sync_file(file, datasync);
 
        btrfs_init_log_ctx(&ctx, inode);
@@ -2112,6 +2093,19 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 
        atomic_inc(&root->log_batch);
 
+       /*
+        * If the inode needs a full sync, make sure we use a full range to
+        * avoid log tree corruption, due to hole detection racing with ordered
+        * extent completion for adjacent ranges, and assertion failures during
+        * hole detection. Do this while holding the inode lock, to avoid races
+        * with other tasks.
+        */
+       if (test_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
+                    &BTRFS_I(inode)->runtime_flags)) {
+               start = 0;
+               end = LLONG_MAX;
+       }
+
        /*
         * Before we acquired the inode's lock, someone may have dirtied more
         * pages in the target range. We need to make sure that writeback for
@@ -2139,8 +2133,11 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
        /*
         * We have to do this here to avoid the priority inversion of waiting on
         * IO of a lower priority task while holding a transaction open.
+        *
+        * Also, the range length can be represented by u64, we have to do the
+        * typecasts to avoid signed overflow if it's [0, LLONG_MAX].
         */
-       ret = btrfs_wait_ordered_range(inode, start, len);
+       ret = btrfs_wait_ordered_range(inode, start, (u64)end - (u64)start + 1);
        if (ret) {
                up_write(&BTRFS_I(inode)->dio_sem);
                inode_unlock(inode);
index 63cad7865d751dd96f2e364fdbd6c92c967a7c6e..37345fb6191d774aff9b8b4fbf57301afab83e98 100644 (file)
@@ -501,13 +501,13 @@ again:
        ret = btrfs_prealloc_file_range_trans(inode, trans, 0, 0, prealloc,
                                              prealloc, prealloc, &alloc_hint);
        if (ret) {
-               btrfs_delalloc_release_extents(BTRFS_I(inode), prealloc, true);
+               btrfs_delalloc_release_extents(BTRFS_I(inode), prealloc);
                btrfs_delalloc_release_metadata(BTRFS_I(inode), prealloc, true);
                goto out_put;
        }
 
        ret = btrfs_write_out_ino_cache(root, trans, path, inode);
-       btrfs_delalloc_release_extents(BTRFS_I(inode), prealloc, false);
+       btrfs_delalloc_release_extents(BTRFS_I(inode), prealloc);
 out_put:
        iput(inode);
 out_release:
index 0f2754eaa05b67ec83858511eeb701d92191e439..c6dc4dd16cf77535b0745a4c0e133446b2e9c286 100644 (file)
@@ -474,6 +474,7 @@ static noinline int compress_file_range(struct async_chunk *async_chunk)
        u64 start = async_chunk->start;
        u64 end = async_chunk->end;
        u64 actual_end;
+       u64 i_size;
        int ret = 0;
        struct page **pages = NULL;
        unsigned long nr_pages;
@@ -488,7 +489,19 @@ static noinline int compress_file_range(struct async_chunk *async_chunk)
        inode_should_defrag(BTRFS_I(inode), start, end, end - start + 1,
                        SZ_16K);
 
-       actual_end = min_t(u64, i_size_read(inode), end + 1);
+       /*
+        * We need to save i_size before now because it could change in between
+        * us evaluating the size and assigning it.  This is because we lock and
+        * unlock the page in truncate and fallocate, and then modify the i_size
+        * later on.
+        *
+        * The barriers are to emulate READ_ONCE, remove that once i_size_read
+        * does that for us.
+        */
+       barrier();
+       i_size = i_size_read(inode);
+       barrier();
+       actual_end = min_t(u64, i_size, end + 1);
 again:
        will_compress = 0;
        nr_pages = (end >> PAGE_SHIFT) - (start >> PAGE_SHIFT) + 1;
@@ -2206,7 +2219,7 @@ again:
 
        ClearPageChecked(page);
        set_page_dirty(page);
-       btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE, false);
+       btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE);
 out:
        unlock_extent_cached(&BTRFS_I(inode)->io_tree, page_start, page_end,
                             &cached_state);
@@ -4951,7 +4964,7 @@ again:
        if (!page) {
                btrfs_delalloc_release_space(inode, data_reserved,
                                             block_start, blocksize, true);
-               btrfs_delalloc_release_extents(BTRFS_I(inode), blocksize, true);
+               btrfs_delalloc_release_extents(BTRFS_I(inode), blocksize);
                ret = -ENOMEM;
                goto out;
        }
@@ -5018,7 +5031,7 @@ out_unlock:
        if (ret)
                btrfs_delalloc_release_space(inode, data_reserved, block_start,
                                             blocksize, true);
-       btrfs_delalloc_release_extents(BTRFS_I(inode), blocksize, (ret != 0));
+       btrfs_delalloc_release_extents(BTRFS_I(inode), blocksize);
        unlock_page(page);
        put_page(page);
 out:
@@ -8709,7 +8722,7 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
                } else if (ret >= 0 && (size_t)ret < count)
                        btrfs_delalloc_release_space(inode, data_reserved,
                                        offset, count - (size_t)ret, true);
-               btrfs_delalloc_release_extents(BTRFS_I(inode), count, false);
+               btrfs_delalloc_release_extents(BTRFS_I(inode), count);
        }
 out:
        if (wakeup)
@@ -9059,7 +9072,7 @@ again:
        unlock_extent_cached(io_tree, page_start, page_end, &cached_state);
 
        if (!ret2) {
-               btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE, true);
+               btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE);
                sb_end_pagefault(inode->i_sb);
                extent_changeset_free(data_reserved);
                return VM_FAULT_LOCKED;
@@ -9068,7 +9081,7 @@ again:
 out_unlock:
        unlock_page(page);
 out:
-       btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE, (ret != 0));
+       btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE);
        btrfs_delalloc_release_space(inode, data_reserved, page_start,
                                     reserved_space, (ret != 0));
 out_noreserve:
index de730e56d3f5106ee97d7fa316ee5e855487d954..23272d9154f37720d105f2ca093fa4473229e024 100644 (file)
@@ -1360,8 +1360,7 @@ again:
                unlock_page(pages[i]);
                put_page(pages[i]);
        }
-       btrfs_delalloc_release_extents(BTRFS_I(inode), page_cnt << PAGE_SHIFT,
-                                      false);
+       btrfs_delalloc_release_extents(BTRFS_I(inode), page_cnt << PAGE_SHIFT);
        extent_changeset_free(data_reserved);
        return i_done;
 out:
@@ -1372,8 +1371,7 @@ out:
        btrfs_delalloc_release_space(inode, data_reserved,
                        start_index << PAGE_SHIFT,
                        page_cnt << PAGE_SHIFT, true);
-       btrfs_delalloc_release_extents(BTRFS_I(inode), page_cnt << PAGE_SHIFT,
-                                      true);
+       btrfs_delalloc_release_extents(BTRFS_I(inode), page_cnt << PAGE_SHIFT);
        extent_changeset_free(data_reserved);
        return ret;
 
@@ -4197,9 +4195,6 @@ static noinline long btrfs_ioctl_start_sync(struct btrfs_root *root,
        u64 transid;
        int ret;
 
-       btrfs_warn(root->fs_info,
-       "START_SYNC ioctl is deprecated and will be removed in kernel 5.7");
-
        trans = btrfs_attach_transaction_barrier(root);
        if (IS_ERR(trans)) {
                if (PTR_ERR(trans) != -ENOENT)
@@ -4227,9 +4222,6 @@ static noinline long btrfs_ioctl_wait_sync(struct btrfs_fs_info *fs_info,
 {
        u64 transid;
 
-       btrfs_warn(fs_info,
-               "WAIT_SYNC ioctl is deprecated and will be removed in kernel 5.7");
-
        if (argp) {
                if (copy_from_user(&transid, argp, sizeof(transid)))
                        return -EFAULT;
index c4bb69941c77c721a7b6c69bb11d83938bfb69d2..3ad151655eb88680b75cfbda5c8005daf3d5d05a 100644 (file)
@@ -3629,7 +3629,7 @@ int __btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes,
                return 0;
 
        BUG_ON(num_bytes != round_down(num_bytes, fs_info->nodesize));
-       trace_qgroup_meta_reserve(root, type, (s64)num_bytes);
+       trace_qgroup_meta_reserve(root, (s64)num_bytes, type);
        ret = qgroup_reserve(root, num_bytes, enforce, type);
        if (ret < 0)
                return ret;
@@ -3676,7 +3676,7 @@ void __btrfs_qgroup_free_meta(struct btrfs_root *root, int num_bytes,
         */
        num_bytes = sub_root_meta_rsv(root, num_bytes, type);
        BUG_ON(num_bytes != round_down(num_bytes, fs_info->nodesize));
-       trace_qgroup_meta_reserve(root, type, -(s64)num_bytes);
+       trace_qgroup_meta_reserve(root, -(s64)num_bytes, type);
        btrfs_qgroup_free_refroot(fs_info, root->root_key.objectid,
                                  num_bytes, type);
 }
index 00504657b60225f5c00346f16098609db679f90e..5cd42b66818cd4ab3b935b809de32aca91a3fefc 100644 (file)
@@ -3277,6 +3277,8 @@ static int relocate_file_extent_cluster(struct inode *inode,
                        if (!page) {
                                btrfs_delalloc_release_metadata(BTRFS_I(inode),
                                                        PAGE_SIZE, true);
+                               btrfs_delalloc_release_extents(BTRFS_I(inode),
+                                                       PAGE_SIZE);
                                ret = -ENOMEM;
                                goto out;
                        }
@@ -3297,7 +3299,7 @@ static int relocate_file_extent_cluster(struct inode *inode,
                                btrfs_delalloc_release_metadata(BTRFS_I(inode),
                                                        PAGE_SIZE, true);
                                btrfs_delalloc_release_extents(BTRFS_I(inode),
-                                                              PAGE_SIZE, true);
+                                                              PAGE_SIZE);
                                ret = -EIO;
                                goto out;
                        }
@@ -3326,7 +3328,7 @@ static int relocate_file_extent_cluster(struct inode *inode,
                        btrfs_delalloc_release_metadata(BTRFS_I(inode),
                                                         PAGE_SIZE, true);
                        btrfs_delalloc_release_extents(BTRFS_I(inode),
-                                                      PAGE_SIZE, true);
+                                                      PAGE_SIZE);
 
                        clear_extent_bits(&BTRFS_I(inode)->io_tree,
                                          page_start, page_end,
@@ -3342,8 +3344,7 @@ static int relocate_file_extent_cluster(struct inode *inode,
                put_page(page);
 
                index++;
-               btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE,
-                                              false);
+               btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE);
                balance_dirty_pages_ratelimited(inode->i_mapping);
                btrfs_throttle(fs_info);
        }
index 98dc092a905e34648664c6d5db4eb2395fb90fca..e8a4b0ebe97f14b6f116a618cd65d799acacc422 100644 (file)
@@ -893,6 +893,15 @@ static void wait_reserve_ticket(struct btrfs_fs_info *fs_info,
        while (ticket->bytes > 0 && ticket->error == 0) {
                ret = prepare_to_wait_event(&ticket->wait, &wait, TASK_KILLABLE);
                if (ret) {
+                       /*
+                        * Delete us from the list. After we unlock the space
+                        * info, we don't want the async reclaim job to reserve
+                        * space for this ticket. If that would happen, then the
+                        * ticket's task would not known that space was reserved
+                        * despite getting an error, resulting in a space leak
+                        * (bytes_may_use counter of our space_info).
+                        */
+                       list_del_init(&ticket->list);
                        ticket->error = -EINTR;
                        break;
                }
@@ -945,12 +954,24 @@ static int handle_reserve_ticket(struct btrfs_fs_info *fs_info,
        spin_lock(&space_info->lock);
        ret = ticket->error;
        if (ticket->bytes || ticket->error) {
+               /*
+                * Need to delete here for priority tickets. For regular tickets
+                * either the async reclaim job deletes the ticket from the list
+                * or we delete it ourselves at wait_reserve_ticket().
+                */
                list_del_init(&ticket->list);
                if (!ret)
                        ret = -ENOSPC;
        }
        spin_unlock(&space_info->lock);
        ASSERT(list_empty(&ticket->list));
+       /*
+        * Check that we can't have an error set if the reservation succeeded,
+        * as that would confuse tasks and lead them to error out without
+        * releasing reserved space (if an error happens the expectation is that
+        * space wasn't reserved at all).
+        */
+       ASSERT(!(ticket->bytes == 0 && ticket->error));
        return ret;
 }
 
index 43e488f5d06314645440318519e4021c7a4d1657..076d5b8014fb3091483e93c234cc6284521f74e3 100644 (file)
@@ -686,9 +686,7 @@ static void dev_item_err(const struct extent_buffer *eb, int slot,
 static int check_dev_item(struct extent_buffer *leaf,
                          struct btrfs_key *key, int slot)
 {
-       struct btrfs_fs_info *fs_info = leaf->fs_info;
        struct btrfs_dev_item *ditem;
-       u64 max_devid = max(BTRFS_MAX_DEVS(fs_info), BTRFS_MAX_DEVS_SYS_CHUNK);
 
        if (key->objectid != BTRFS_DEV_ITEMS_OBJECTID) {
                dev_item_err(leaf, slot,
@@ -696,12 +694,6 @@ static int check_dev_item(struct extent_buffer *leaf,
                             key->objectid, BTRFS_DEV_ITEMS_OBJECTID);
                return -EUCLEAN;
        }
-       if (key->offset > max_devid) {
-               dev_item_err(leaf, slot,
-                            "invalid devid: has=%llu expect=[0, %llu]",
-                            key->offset, max_devid);
-               return -EUCLEAN;
-       }
        ditem = btrfs_item_ptr(leaf, slot, struct btrfs_dev_item);
        if (btrfs_device_id(leaf, ditem) != key->offset) {
                dev_item_err(leaf, slot,
index bdfe4493e43a4f437d674d35173098d473092ff4..e04409f85063039d78c5d5385f7dcf0a920a4d71 100644 (file)
@@ -4967,6 +4967,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
        } else if (type & BTRFS_BLOCK_GROUP_SYSTEM) {
                max_stripe_size = SZ_32M;
                max_chunk_size = 2 * max_stripe_size;
+               devs_max = min_t(int, devs_max, BTRFS_MAX_DEVS_SYS_CHUNK);
        } else {
                btrfs_err(info, "invalid chunk type 0x%llx requested",
                       type);
index d3b9c9d5c1bd242170d671521d91ddb6cb90a0ac..f5a38910a82bfb94d71ceab28af196b3d0165c6f 100644 (file)
@@ -1058,6 +1058,11 @@ void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release)
 
        dout("__ceph_remove_cap %p from %p\n", cap, &ci->vfs_inode);
 
+       /* remove from inode's cap rbtree, and clear auth cap */
+       rb_erase(&cap->ci_node, &ci->i_caps);
+       if (ci->i_auth_cap == cap)
+               ci->i_auth_cap = NULL;
+
        /* remove from session list */
        spin_lock(&session->s_cap_lock);
        if (session->s_cap_iterator == cap) {
@@ -1091,11 +1096,6 @@ void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release)
 
        spin_unlock(&session->s_cap_lock);
 
-       /* remove from inode list */
-       rb_erase(&cap->ci_node, &ci->i_caps);
-       if (ci->i_auth_cap == cap)
-               ci->i_auth_cap = NULL;
-
        if (removed)
                ceph_put_cap(mdsc, cap);
 
index 4ca0b8ff9a7270c7479fa13920cce5570df8e1ee..d17a789fd856b45d6a2f8b201d85f3433321762e 100644 (file)
@@ -1553,36 +1553,37 @@ static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)
 {
        int valid = 0;
        struct dentry *parent;
-       struct inode *dir;
+       struct inode *dir, *inode;
 
        if (flags & LOOKUP_RCU) {
                parent = READ_ONCE(dentry->d_parent);
                dir = d_inode_rcu(parent);
                if (!dir)
                        return -ECHILD;
+               inode = d_inode_rcu(dentry);
        } else {
                parent = dget_parent(dentry);
                dir = d_inode(parent);
+               inode = d_inode(dentry);
        }
 
        dout("d_revalidate %p '%pd' inode %p offset %lld\n", dentry,
-            dentry, d_inode(dentry), ceph_dentry(dentry)->offset);
+            dentry, inode, ceph_dentry(dentry)->offset);
 
        /* always trust cached snapped dentries, snapdir dentry */
        if (ceph_snap(dir) != CEPH_NOSNAP) {
                dout("d_revalidate %p '%pd' inode %p is SNAPPED\n", dentry,
-                    dentry, d_inode(dentry));
+                    dentry, inode);
                valid = 1;
-       } else if (d_really_is_positive(dentry) &&
-                  ceph_snap(d_inode(dentry)) == CEPH_SNAPDIR) {
+       } else if (inode && ceph_snap(inode) == CEPH_SNAPDIR) {
                valid = 1;
        } else {
                valid = dentry_lease_is_valid(dentry, flags);
                if (valid == -ECHILD)
                        return valid;
                if (valid || dir_lease_is_valid(dir, dentry)) {
-                       if (d_really_is_positive(dentry))
-                               valid = ceph_is_any_caps(d_inode(dentry));
+                       if (inode)
+                               valid = ceph_is_any_caps(inode);
                        else
                                valid = 1;
                }
index d277f71abe0b8e653ef0e439782c2ee930388bbf..bd77adb64bfd9812d25e0f0b92c0fb55689a9d7c 100644 (file)
@@ -462,6 +462,9 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
                err = ceph_security_init_secctx(dentry, mode, &as_ctx);
                if (err < 0)
                        goto out_ctx;
+       } else if (!d_in_lookup(dentry)) {
+               /* If it's not being looked up, it's negative */
+               return -ENOENT;
        }
 
        /* do the open */
@@ -1956,10 +1959,18 @@ static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off,
        if (ceph_test_mount_opt(src_fsc, NOCOPYFROM))
                return -EOPNOTSUPP;
 
+       /*
+        * Striped file layouts require that we copy partial objects, but the
+        * OSD copy-from operation only supports full-object copies.  Limit
+        * this to non-striped file layouts for now.
+        */
        if ((src_ci->i_layout.stripe_unit != dst_ci->i_layout.stripe_unit) ||
-           (src_ci->i_layout.stripe_count != dst_ci->i_layout.stripe_count) ||
-           (src_ci->i_layout.object_size != dst_ci->i_layout.object_size))
+           (src_ci->i_layout.stripe_count != 1) ||
+           (dst_ci->i_layout.stripe_count != 1) ||
+           (src_ci->i_layout.object_size != dst_ci->i_layout.object_size)) {
+               dout("Invalid src/dst files layout\n");
                return -EOPNOTSUPP;
+       }
 
        if (len < src_ci->i_layout.object_size)
                return -EOPNOTSUPP; /* no remote copy will be done */
index 9f135624ae476a23ab610cff33d173646e111724..c07407586ce873f236a1cf61d0ea48efa27590c4 100644 (file)
@@ -1434,6 +1434,7 @@ retry_lookup:
                dout(" final dn %p\n", dn);
        } else if ((req->r_op == CEPH_MDS_OP_LOOKUPSNAP ||
                    req->r_op == CEPH_MDS_OP_MKSNAP) &&
+                  test_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags) &&
                   !test_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags)) {
                struct inode *dir = req->r_parent;
 
index edfd643a8205ec3222daaec8f0374d4549bba1f3..b47f43fc2d688113c5dbcbf3e28bb18e1712e9f7 100644 (file)
@@ -268,6 +268,7 @@ static int parse_fsopt_token(char *c, void *private)
                }
                break;
        case Opt_fscache_uniq:
+#ifdef CONFIG_CEPH_FSCACHE
                kfree(fsopt->fscache_uniq);
                fsopt->fscache_uniq = kstrndup(argstr[0].from,
                                               argstr[0].to-argstr[0].from,
@@ -276,7 +277,10 @@ static int parse_fsopt_token(char *c, void *private)
                        return -ENOMEM;
                fsopt->flags |= CEPH_MOUNT_OPT_FSCACHE;
                break;
-               /* misc */
+#else
+               pr_err("fscache support is disabled\n");
+               return -EINVAL;
+#endif
        case Opt_wsize:
                if (intval < (int)PAGE_SIZE || intval > CEPH_MAX_WRITE_SIZE)
                        return -EINVAL;
@@ -353,10 +357,15 @@ static int parse_fsopt_token(char *c, void *private)
                fsopt->flags &= ~CEPH_MOUNT_OPT_INO32;
                break;
        case Opt_fscache:
+#ifdef CONFIG_CEPH_FSCACHE
                fsopt->flags |= CEPH_MOUNT_OPT_FSCACHE;
                kfree(fsopt->fscache_uniq);
                fsopt->fscache_uniq = NULL;
                break;
+#else
+               pr_err("fscache support is disabled\n");
+               return -EINVAL;
+#endif
        case Opt_nofscache:
                fsopt->flags &= ~CEPH_MOUNT_OPT_FSCACHE;
                kfree(fsopt->fscache_uniq);
index c049c7b3aa87a51d48e4d5afe6231c87bee1a910..1a135d1b85bd8c3dca017660d1c786a4d4578280 100644 (file)
@@ -169,7 +169,13 @@ cifs_read_super(struct super_block *sb)
        else
                sb->s_maxbytes = MAX_NON_LFS;
 
-       /* Some very old servers like DOS and OS/2 used 2 second granularity */
+       /*
+        * Some very old servers like DOS and OS/2 used 2 second granularity
+        * (while all current servers use 100ns granularity - see MS-DTYP)
+        * but 1 second is the maximum allowed granularity for the VFS
+        * so for old servers set time granularity to 1 second while for
+        * everything else (current servers) set it to 100ns.
+        */
        if ((tcon->ses->server->vals->protocol_id == SMB10_PROT_ID) &&
            ((tcon->ses->capabilities &
              tcon->ses->server->vals->cap_nt_find) == 0) &&
index 50dfd9049370dfc56bdd503f3b2b6c84e354e510..d78bfcc191560804b694b965a381b21f7b5962f2 100644 (file)
@@ -1391,6 +1391,11 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file);
 struct cifsInodeInfo {
        bool can_cache_brlcks;
        struct list_head llist; /* locks helb by this inode */
+       /*
+        * NOTE: Some code paths call down_read(lock_sem) twice, so
+        * we must always use use cifs_down_write() instead of down_write()
+        * for this semaphore to avoid deadlocks.
+        */
        struct rw_semaphore lock_sem;   /* protect the fields above */
        /* BB add in lists for dirty pages i.e. write caching info for oplock */
        struct list_head openFileList;
index e53e9f62b87b7b043f11010877ab59c5937c7014..fe597d3d52088366615c5ec5d295ee7218f4d9ed 100644 (file)
@@ -170,6 +170,7 @@ extern int cifs_unlock_range(struct cifsFileInfo *cfile,
                             struct file_lock *flock, const unsigned int xid);
 extern int cifs_push_mandatory_locks(struct cifsFileInfo *cfile);
 
+extern void cifs_down_write(struct rw_semaphore *sem);
 extern struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid,
                                              struct file *file,
                                              struct tcon_link *tlink,
index a64dfa95a925acaefa19ddc027ff2c454ada96a8..ccaa8bad336f9d7e2b67cb1364a4ca4b6f1718d4 100644 (file)
@@ -564,9 +564,11 @@ cifs_reconnect(struct TCP_Server_Info *server)
        spin_lock(&GlobalMid_Lock);
        list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
                mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
+               kref_get(&mid_entry->refcount);
                if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
                        mid_entry->mid_state = MID_RETRY_NEEDED;
                list_move(&mid_entry->qhead, &retry_list);
+               mid_entry->mid_flags |= MID_DELETED;
        }
        spin_unlock(&GlobalMid_Lock);
        mutex_unlock(&server->srv_mutex);
@@ -576,6 +578,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
                mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
                list_del_init(&mid_entry->qhead);
                mid_entry->callback(mid_entry);
+               cifs_mid_q_entry_release(mid_entry);
        }
 
        if (cifs_rdma_enabled(server)) {
@@ -895,8 +898,10 @@ dequeue_mid(struct mid_q_entry *mid, bool malformed)
        if (mid->mid_flags & MID_DELETED)
                printk_once(KERN_WARNING
                            "trying to dequeue a deleted mid\n");
-       else
+       else {
                list_del_init(&mid->qhead);
+               mid->mid_flags |= MID_DELETED;
+       }
        spin_unlock(&GlobalMid_Lock);
 }
 
@@ -966,8 +971,10 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server)
                list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
                        mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
                        cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
+                       kref_get(&mid_entry->refcount);
                        mid_entry->mid_state = MID_SHUTDOWN;
                        list_move(&mid_entry->qhead, &dispose_list);
+                       mid_entry->mid_flags |= MID_DELETED;
                }
                spin_unlock(&GlobalMid_Lock);
 
@@ -977,6 +984,7 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server)
                        cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
                        list_del_init(&mid_entry->qhead);
                        mid_entry->callback(mid_entry);
+                       cifs_mid_q_entry_release(mid_entry);
                }
                /* 1/8th of sec is more than enough time for them to exit */
                msleep(125);
@@ -3882,8 +3890,12 @@ generic_ip_connect(struct TCP_Server_Info *server)
 
        rc = socket->ops->connect(socket, saddr, slen,
                                  server->noblockcnt ? O_NONBLOCK : 0);
-
-       if (rc == -EINPROGRESS)
+       /*
+        * When mounting SMB root file systems, we do not want to block in
+        * connect. Otherwise bail out and then let cifs_reconnect() perform
+        * reconnect failover - if possible.
+        */
+       if (server->noblockcnt && rc == -EINPROGRESS)
                rc = 0;
        if (rc < 0) {
                cifs_dbg(FYI, "Error %d connecting to server\n", rc);
index 5ad15de2bb4f950cf88d72f3d15b3b3132e72bcd..fa7b0fa72bb360d7133b13b05788e1e591faf547 100644 (file)
@@ -281,6 +281,13 @@ cifs_has_mand_locks(struct cifsInodeInfo *cinode)
        return has_locks;
 }
 
+void
+cifs_down_write(struct rw_semaphore *sem)
+{
+       while (!down_write_trylock(sem))
+               msleep(10);
+}
+
 struct cifsFileInfo *
 cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
                  struct tcon_link *tlink, __u32 oplock)
@@ -306,7 +313,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
        INIT_LIST_HEAD(&fdlocks->locks);
        fdlocks->cfile = cfile;
        cfile->llist = fdlocks;
-       down_write(&cinode->lock_sem);
+       cifs_down_write(&cinode->lock_sem);
        list_add(&fdlocks->llist, &cinode->llist);
        up_write(&cinode->lock_sem);
 
@@ -405,10 +412,11 @@ void _cifsFileInfo_put(struct cifsFileInfo *cifs_file, bool wait_oplock_handler)
        bool oplock_break_cancelled;
 
        spin_lock(&tcon->open_file_lock);
-
+       spin_lock(&cifsi->open_file_lock);
        spin_lock(&cifs_file->file_info_lock);
        if (--cifs_file->count > 0) {
                spin_unlock(&cifs_file->file_info_lock);
+               spin_unlock(&cifsi->open_file_lock);
                spin_unlock(&tcon->open_file_lock);
                return;
        }
@@ -421,9 +429,7 @@ void _cifsFileInfo_put(struct cifsFileInfo *cifs_file, bool wait_oplock_handler)
        cifs_add_pending_open_locked(&fid, cifs_file->tlink, &open);
 
        /* remove it from the lists */
-       spin_lock(&cifsi->open_file_lock);
        list_del(&cifs_file->flist);
-       spin_unlock(&cifsi->open_file_lock);
        list_del(&cifs_file->tlist);
        atomic_dec(&tcon->num_local_opens);
 
@@ -440,6 +446,7 @@ void _cifsFileInfo_put(struct cifsFileInfo *cifs_file, bool wait_oplock_handler)
                cifs_set_oplock_level(cifsi, 0);
        }
 
+       spin_unlock(&cifsi->open_file_lock);
        spin_unlock(&tcon->open_file_lock);
 
        oplock_break_cancelled = wait_oplock_handler ?
@@ -464,7 +471,7 @@ void _cifsFileInfo_put(struct cifsFileInfo *cifs_file, bool wait_oplock_handler)
         * Delete any outstanding lock records. We'll lose them when the file
         * is closed anyway.
         */
-       down_write(&cifsi->lock_sem);
+       cifs_down_write(&cifsi->lock_sem);
        list_for_each_entry_safe(li, tmp, &cifs_file->llist->locks, llist) {
                list_del(&li->llist);
                cifs_del_lock_waiters(li);
@@ -1027,7 +1034,7 @@ static void
 cifs_lock_add(struct cifsFileInfo *cfile, struct cifsLockInfo *lock)
 {
        struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
-       down_write(&cinode->lock_sem);
+       cifs_down_write(&cinode->lock_sem);
        list_add_tail(&lock->llist, &cfile->llist->locks);
        up_write(&cinode->lock_sem);
 }
@@ -1049,7 +1056,7 @@ cifs_lock_add_if(struct cifsFileInfo *cfile, struct cifsLockInfo *lock,
 
 try_again:
        exist = false;
-       down_write(&cinode->lock_sem);
+       cifs_down_write(&cinode->lock_sem);
 
        exist = cifs_find_lock_conflict(cfile, lock->offset, lock->length,
                                        lock->type, lock->flags, &conf_lock,
@@ -1072,7 +1079,7 @@ try_again:
                                        (lock->blist.next == &lock->blist));
                if (!rc)
                        goto try_again;
-               down_write(&cinode->lock_sem);
+               cifs_down_write(&cinode->lock_sem);
                list_del_init(&lock->blist);
        }
 
@@ -1125,7 +1132,7 @@ cifs_posix_lock_set(struct file *file, struct file_lock *flock)
                return rc;
 
 try_again:
-       down_write(&cinode->lock_sem);
+       cifs_down_write(&cinode->lock_sem);
        if (!cinode->can_cache_brlcks) {
                up_write(&cinode->lock_sem);
                return rc;
@@ -1331,7 +1338,7 @@ cifs_push_locks(struct cifsFileInfo *cfile)
        int rc = 0;
 
        /* we are going to update can_cache_brlcks here - need a write access */
-       down_write(&cinode->lock_sem);
+       cifs_down_write(&cinode->lock_sem);
        if (!cinode->can_cache_brlcks) {
                up_write(&cinode->lock_sem);
                return rc;
@@ -1522,7 +1529,7 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
        if (!buf)
                return -ENOMEM;
 
-       down_write(&cinode->lock_sem);
+       cifs_down_write(&cinode->lock_sem);
        for (i = 0; i < 2; i++) {
                cur = buf;
                num = 0;
index 5dcc95b38310b63fabbf5b0404cbfb9776615798..df9377828e2f435bdb32339f48c2ad08ac9bdd32 100644 (file)
@@ -2475,9 +2475,9 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
                        rc = tcon->ses->server->ops->flush(xid, tcon, &wfile->fid);
                        cifsFileInfo_put(wfile);
                        if (rc)
-                               return rc;
+                               goto cifs_setattr_exit;
                } else if (rc != -EBADF)
-                       return rc;
+                       goto cifs_setattr_exit;
                else
                        rc = 0;
        }
index b7421a0963195137474d9e3a15075796743c6157..514810694c0f5a7b48bfa6139401beb8c40c68cf 100644 (file)
@@ -171,6 +171,9 @@ cifs_get_next_mid(struct TCP_Server_Info *server)
        /* we do not want to loop forever */
        last_mid = cur_mid;
        cur_mid++;
+       /* avoid 0xFFFF MID */
+       if (cur_mid == 0xffff)
+               cur_mid++;
 
        /*
         * This nested loop looks more expensive than it is.
index e6a1fc72018fd1821f8499a70eebe6edd7400bdc..8b0b512c57920cebd5a022c2357a31e376cf87ed 100644 (file)
@@ -145,7 +145,7 @@ smb2_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
 
        cur = buf;
 
-       down_write(&cinode->lock_sem);
+       cifs_down_write(&cinode->lock_sem);
        list_for_each_entry_safe(li, tmp, &cfile->llist->locks, llist) {
                if (flock->fl_start > li->offset ||
                    (flock->fl_start + length) <
index 4c092259646740da18a7e3be2b31d1647320aaa4..cd55af9b7cc5aca5669fb53018efb0ea29494bff 100644 (file)
@@ -4084,6 +4084,7 @@ free_pages:
 
        kfree(dw->ppages);
        cifs_small_buf_release(dw->buf);
+       kfree(dw);
 }
 
 
@@ -4157,7 +4158,7 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid,
                dw->server = server;
                dw->ppages = pages;
                dw->len = len;
-               queue_work(cifsiod_wq, &dw->decrypt);
+               queue_work(decrypt_wq, &dw->decrypt);
                *num_mids = 0; /* worker thread takes care of finding mid */
                return -1;
        }
index ea735d59c36e106e7f8ada92486941948eaa9528..0abfde6d0b0511e26484c19a359cfe52c346bd93 100644 (file)
@@ -838,6 +838,7 @@ struct create_durable_handle_reconnect_v2 {
        struct create_context ccontext;
        __u8   Name[8];
        struct durable_reconnect_context_v2 dcontext;
+       __u8   Pad[4];
 } __packed;
 
 /* See MS-SMB2 2.2.13.2.5 */
index 308ad0f495e10d513f9219e92d8ade62558337f6..ca3de62688d6e8fab18504ef09cc4be5ac9c709a 100644 (file)
@@ -86,22 +86,8 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
 
 static void _cifs_mid_q_entry_release(struct kref *refcount)
 {
-       struct mid_q_entry *mid = container_of(refcount, struct mid_q_entry,
-                                              refcount);
-
-       mempool_free(mid, cifs_mid_poolp);
-}
-
-void cifs_mid_q_entry_release(struct mid_q_entry *midEntry)
-{
-       spin_lock(&GlobalMid_Lock);
-       kref_put(&midEntry->refcount, _cifs_mid_q_entry_release);
-       spin_unlock(&GlobalMid_Lock);
-}
-
-void
-DeleteMidQEntry(struct mid_q_entry *midEntry)
-{
+       struct mid_q_entry *midEntry =
+                       container_of(refcount, struct mid_q_entry, refcount);
 #ifdef CONFIG_CIFS_STATS2
        __le16 command = midEntry->server->vals->lock_cmd;
        __u16 smb_cmd = le16_to_cpu(midEntry->command);
@@ -166,6 +152,19 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
                }
        }
 #endif
+
+       mempool_free(midEntry, cifs_mid_poolp);
+}
+
+void cifs_mid_q_entry_release(struct mid_q_entry *midEntry)
+{
+       spin_lock(&GlobalMid_Lock);
+       kref_put(&midEntry->refcount, _cifs_mid_q_entry_release);
+       spin_unlock(&GlobalMid_Lock);
+}
+
+void DeleteMidQEntry(struct mid_q_entry *midEntry)
+{
        cifs_mid_q_entry_release(midEntry);
 }
 
@@ -173,8 +172,10 @@ void
 cifs_delete_mid(struct mid_q_entry *mid)
 {
        spin_lock(&GlobalMid_Lock);
-       list_del_init(&mid->qhead);
-       mid->mid_flags |= MID_DELETED;
+       if (!(mid->mid_flags & MID_DELETED)) {
+               list_del_init(&mid->qhead);
+               mid->mid_flags |= MID_DELETED;
+       }
        spin_unlock(&GlobalMid_Lock);
 
        DeleteMidQEntry(mid);
@@ -872,7 +873,10 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
                rc = -EHOSTDOWN;
                break;
        default:
-               list_del_init(&mid->qhead);
+               if (!(mid->mid_flags & MID_DELETED)) {
+                       list_del_init(&mid->qhead);
+                       mid->mid_flags |= MID_DELETED;
+               }
                cifs_server_dbg(VFS, "%s: invalid mid state mid=%llu state=%d\n",
                         __func__, mid->mid, mid->mid_state);
                rc = -EIO;
index dc5dbf6a81d77bde5bcaad94cb2f4e37a6296ede..cb61467478ca81f973ad22a65296c8b41079ed56 100644 (file)
@@ -101,7 +101,7 @@ static int create_link(struct config_item *parent_item,
        }
        target_sd->s_links++;
        spin_unlock(&configfs_dirent_lock);
-       ret = configfs_get_target_path(item, item, body);
+       ret = configfs_get_target_path(parent_item, item, body);
        if (!ret)
                ret = configfs_create_link(target_sd, parent_item->ci_dentry,
                                           dentry, body);
index 6bf81f931de39e48bc2983a1c901b1a6643443f8..2cc43cd914eb8332e3c1ccbdcfafa2e6ce64baee 100644 (file)
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -220,10 +220,11 @@ static void *get_unlocked_entry(struct xa_state *xas, unsigned int order)
 
        for (;;) {
                entry = xas_find_conflict(xas);
+               if (!entry || WARN_ON_ONCE(!xa_is_value(entry)))
+                       return entry;
                if (dax_entry_order(entry) < order)
                        return XA_RETRY_ENTRY;
-               if (!entry || WARN_ON_ONCE(!xa_is_value(entry)) ||
-                               !dax_is_locked(entry))
+               if (!dax_is_locked(entry))
                        return entry;
 
                wq = dax_entry_waitqueue(xas, entry, &ewait.key);
index 8461a63220398024c2aef5d4795d2f2aadd4ebfa..335607b8c5c001ca35847c5ec22409ab04d83b05 100644 (file)
@@ -576,10 +576,13 @@ void wbc_attach_and_unlock_inode(struct writeback_control *wbc,
        spin_unlock(&inode->i_lock);
 
        /*
-        * A dying wb indicates that the memcg-blkcg mapping has changed
-        * and a new wb is already serving the memcg.  Switch immediately.
+        * A dying wb indicates that either the blkcg associated with the
+        * memcg changed or the associated memcg is dying.  In the first
+        * case, a replacement wb should already be available and we should
+        * refresh the wb immediately.  In the second case, trying to
+        * refresh will keep failing.
         */
-       if (unlikely(wb_dying(wbc->wb)))
+       if (unlikely(wb_dying(wbc->wb) && !css_is_dying(wbc->wb->memcg_css)))
                inode_switch_wbs(inode, wbc->wb_id);
 }
 EXPORT_SYMBOL_GPL(wbc_attach_and_unlock_inode);
index 6419a2b3510deada202d4ccd9a4ca3447f8baa07..3e8cebfb59b7b38155f89196d7b2f2b8e764810b 100644 (file)
@@ -5,6 +5,7 @@
 
 obj-$(CONFIG_FUSE_FS) += fuse.o
 obj-$(CONFIG_CUSE) += cuse.o
-obj-$(CONFIG_VIRTIO_FS) += virtio_fs.o
+obj-$(CONFIG_VIRTIO_FS) += virtiofs.o
 
 fuse-objs := dev.o dir.o file.o inode.o control.o xattr.o acl.o readdir.o
+virtiofs-y += virtio_fs.o
index dadd617d826c93825500679f33a524940c15c2e7..ed1abc9e33cfcc165442c11b435f36a294a892a2 100644 (file)
@@ -276,10 +276,12 @@ static void flush_bg_queue(struct fuse_conn *fc)
 void fuse_request_end(struct fuse_conn *fc, struct fuse_req *req)
 {
        struct fuse_iqueue *fiq = &fc->iq;
-       bool async = req->args->end;
+       bool async;
 
        if (test_and_set_bit(FR_FINISHED, &req->flags))
                goto put_request;
+
+       async = req->args->end;
        /*
         * test_and_set_bit() implies smp_mb() between bit
         * changing and below intr_entry check. Pairs with
index d572c900bb0f208c6a49a43b97ece1cb882687f7..54d638f9ba1caea3cbd8c539b73204cd60ed19ba 100644 (file)
@@ -405,7 +405,8 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
        else
                fuse_invalidate_entry_cache(entry);
 
-       fuse_advise_use_readdirplus(dir);
+       if (inode)
+               fuse_advise_use_readdirplus(dir);
        return newent;
 
  out_iput:
@@ -1521,6 +1522,19 @@ int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
                is_truncate = true;
        }
 
+       /* Flush dirty data/metadata before non-truncate SETATTR */
+       if (is_wb && S_ISREG(inode->i_mode) &&
+           attr->ia_valid &
+                       (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_MTIME_SET |
+                        ATTR_TIMES_SET)) {
+               err = write_inode_now(inode, true);
+               if (err)
+                       return err;
+
+               fuse_set_nowrite(inode);
+               fuse_release_nowrite(inode);
+       }
+
        if (is_truncate) {
                fuse_set_nowrite(inode);
                set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
index 0f0225686aeeb2acfbeff178bfd2434e4ea80795..db48a5cf862095160179b7d205c7c8cd8c046c24 100644 (file)
@@ -217,7 +217,7 @@ int fuse_open_common(struct inode *inode, struct file *file, bool isdir)
 {
        struct fuse_conn *fc = get_fuse_conn(inode);
        int err;
-       bool lock_inode = (file->f_flags & O_TRUNC) &&
+       bool is_wb_truncate = (file->f_flags & O_TRUNC) &&
                          fc->atomic_o_trunc &&
                          fc->writeback_cache;
 
@@ -225,16 +225,20 @@ int fuse_open_common(struct inode *inode, struct file *file, bool isdir)
        if (err)
                return err;
 
-       if (lock_inode)
+       if (is_wb_truncate) {
                inode_lock(inode);
+               fuse_set_nowrite(inode);
+       }
 
        err = fuse_do_open(fc, get_node_id(inode), file, isdir);
 
        if (!err)
                fuse_finish_open(inode, file);
 
-       if (lock_inode)
+       if (is_wb_truncate) {
+               fuse_release_nowrite(inode);
                inode_unlock(inode);
+       }
 
        return err;
 }
@@ -1997,7 +2001,7 @@ static int fuse_writepages_fill(struct page *page,
 
        if (!data->ff) {
                err = -EIO;
-               data->ff = fuse_write_file_get(fc, get_fuse_inode(inode));
+               data->ff = fuse_write_file_get(fc, fi);
                if (!data->ff)
                        goto out_unlock;
        }
@@ -2042,8 +2046,6 @@ static int fuse_writepages_fill(struct page *page,
         * under writeback, so we can release the page lock.
         */
        if (data->wpa == NULL) {
-               struct fuse_inode *fi = get_fuse_inode(inode);
-
                err = -ENOMEM;
                wpa = fuse_writepage_args_alloc();
                if (!wpa) {
index 956aeaf961ae12b8c52d55fb961f3c18af66293e..d148188cfca453499d46eb6eaa9d77b645474a5a 100644 (file)
@@ -479,6 +479,7 @@ struct fuse_fs_context {
        bool destroy:1;
        bool no_control:1;
        bool no_force_umount:1;
+       bool no_mount_options:1;
        unsigned int max_read;
        unsigned int blksize;
        const char *subtype;
@@ -713,6 +714,9 @@ struct fuse_conn {
        /** Do not allow MNT_FORCE umount */
        unsigned int no_force_umount:1;
 
+       /* Do not show mount options */
+       unsigned int no_mount_options:1;
+
        /** The number of requests waiting for completion */
        atomic_t num_waiting;
 
index e040e2a2b62102bdcfbae5b5cf92a1a60996c58d..16aec32f7f3d71767746a886a95e8dfd151d24de 100644 (file)
@@ -558,6 +558,9 @@ static int fuse_show_options(struct seq_file *m, struct dentry *root)
        struct super_block *sb = root->d_sb;
        struct fuse_conn *fc = get_fuse_conn_super(sb);
 
+       if (fc->no_mount_options)
+               return 0;
+
        seq_printf(m, ",user_id=%u", from_kuid_munged(fc->user_ns, fc->user_id));
        seq_printf(m, ",group_id=%u", from_kgid_munged(fc->user_ns, fc->group_id));
        if (fc->default_permissions)
@@ -1180,6 +1183,7 @@ int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
        fc->destroy = ctx->destroy;
        fc->no_control = ctx->no_control;
        fc->no_force_umount = ctx->no_force_umount;
+       fc->no_mount_options = ctx->no_mount_options;
 
        err = -ENOMEM;
        root = fuse_get_root_inode(sb, ctx->rootmode);
index 6af3f131e468ad3ee7bedffe41f4bb0b6b03e91c..a5c86048b96edb59f85986935206f2c53972a170 100644 (file)
@@ -30,6 +30,7 @@ struct virtio_fs_vq {
        struct virtqueue *vq;     /* protected by ->lock */
        struct work_struct done_work;
        struct list_head queued_reqs;
+       struct list_head end_reqs;      /* End these requests */
        struct delayed_work dispatch_work;
        struct fuse_dev *fud;
        bool connected;
@@ -54,6 +55,9 @@ struct virtio_fs_forget {
        struct list_head list;
 };
 
+static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq,
+                                struct fuse_req *req, bool in_flight);
+
 static inline struct virtio_fs_vq *vq_to_fsvq(struct virtqueue *vq)
 {
        struct virtio_fs *fs = vq->vdev->priv;
@@ -66,6 +70,19 @@ static inline struct fuse_pqueue *vq_to_fpq(struct virtqueue *vq)
        return &vq_to_fsvq(vq)->fud->pq;
 }
 
+/* Should be called with fsvq->lock held. */
+static inline void inc_in_flight_req(struct virtio_fs_vq *fsvq)
+{
+       fsvq->in_flight++;
+}
+
+/* Should be called with fsvq->lock held. */
+static inline void dec_in_flight_req(struct virtio_fs_vq *fsvq)
+{
+       WARN_ON(fsvq->in_flight <= 0);
+       fsvq->in_flight--;
+}
+
 static void release_virtio_fs_obj(struct kref *ref)
 {
        struct virtio_fs *vfs = container_of(ref, struct virtio_fs, refcount);
@@ -109,22 +126,6 @@ static void virtio_fs_drain_queue(struct virtio_fs_vq *fsvq)
        flush_delayed_work(&fsvq->dispatch_work);
 }
 
-static inline void drain_hiprio_queued_reqs(struct virtio_fs_vq *fsvq)
-{
-       struct virtio_fs_forget *forget;
-
-       spin_lock(&fsvq->lock);
-       while (1) {
-               forget = list_first_entry_or_null(&fsvq->queued_reqs,
-                                               struct virtio_fs_forget, list);
-               if (!forget)
-                       break;
-               list_del(&forget->list);
-               kfree(forget);
-       }
-       spin_unlock(&fsvq->lock);
-}
-
 static void virtio_fs_drain_all_queues(struct virtio_fs *fs)
 {
        struct virtio_fs_vq *fsvq;
@@ -132,9 +133,6 @@ static void virtio_fs_drain_all_queues(struct virtio_fs *fs)
 
        for (i = 0; i < fs->nvqs; i++) {
                fsvq = &fs->vqs[i];
-               if (i == VQ_HIPRIO)
-                       drain_hiprio_queued_reqs(fsvq);
-
                virtio_fs_drain_queue(fsvq);
        }
 }
@@ -253,14 +251,66 @@ static void virtio_fs_hiprio_done_work(struct work_struct *work)
 
                while ((req = virtqueue_get_buf(vq, &len)) != NULL) {
                        kfree(req);
-                       fsvq->in_flight--;
+                       dec_in_flight_req(fsvq);
                }
        } while (!virtqueue_enable_cb(vq) && likely(!virtqueue_is_broken(vq)));
        spin_unlock(&fsvq->lock);
 }
 
-static void virtio_fs_dummy_dispatch_work(struct work_struct *work)
+static void virtio_fs_request_dispatch_work(struct work_struct *work)
 {
+       struct fuse_req *req;
+       struct virtio_fs_vq *fsvq = container_of(work, struct virtio_fs_vq,
+                                                dispatch_work.work);
+       struct fuse_conn *fc = fsvq->fud->fc;
+       int ret;
+
+       pr_debug("virtio-fs: worker %s called.\n", __func__);
+       while (1) {
+               spin_lock(&fsvq->lock);
+               req = list_first_entry_or_null(&fsvq->end_reqs, struct fuse_req,
+                                              list);
+               if (!req) {
+                       spin_unlock(&fsvq->lock);
+                       break;
+               }
+
+               list_del_init(&req->list);
+               spin_unlock(&fsvq->lock);
+               fuse_request_end(fc, req);
+       }
+
+       /* Dispatch pending requests */
+       while (1) {
+               spin_lock(&fsvq->lock);
+               req = list_first_entry_or_null(&fsvq->queued_reqs,
+                                              struct fuse_req, list);
+               if (!req) {
+                       spin_unlock(&fsvq->lock);
+                       return;
+               }
+               list_del_init(&req->list);
+               spin_unlock(&fsvq->lock);
+
+               ret = virtio_fs_enqueue_req(fsvq, req, true);
+               if (ret < 0) {
+                       if (ret == -ENOMEM || ret == -ENOSPC) {
+                               spin_lock(&fsvq->lock);
+                               list_add_tail(&req->list, &fsvq->queued_reqs);
+                               schedule_delayed_work(&fsvq->dispatch_work,
+                                                     msecs_to_jiffies(1));
+                               spin_unlock(&fsvq->lock);
+                               return;
+                       }
+                       req->out.h.error = ret;
+                       spin_lock(&fsvq->lock);
+                       dec_in_flight_req(fsvq);
+                       spin_unlock(&fsvq->lock);
+                       pr_err("virtio-fs: virtio_fs_enqueue_req() failed %d\n",
+                              ret);
+                       fuse_request_end(fc, req);
+               }
+       }
 }
 
 static void virtio_fs_hiprio_dispatch_work(struct work_struct *work)
@@ -286,6 +336,7 @@ static void virtio_fs_hiprio_dispatch_work(struct work_struct *work)
 
                list_del(&forget->list);
                if (!fsvq->connected) {
+                       dec_in_flight_req(fsvq);
                        spin_unlock(&fsvq->lock);
                        kfree(forget);
                        continue;
@@ -307,13 +358,13 @@ static void virtio_fs_hiprio_dispatch_work(struct work_struct *work)
                        } else {
                                pr_debug("virtio-fs: Could not queue FORGET: err=%d. Dropping it.\n",
                                         ret);
+                               dec_in_flight_req(fsvq);
                                kfree(forget);
                        }
                        spin_unlock(&fsvq->lock);
                        return;
                }
 
-               fsvq->in_flight++;
                notify = virtqueue_kick_prepare(vq);
                spin_unlock(&fsvq->lock);
 
@@ -452,7 +503,7 @@ static void virtio_fs_requests_done_work(struct work_struct *work)
 
                fuse_request_end(fc, req);
                spin_lock(&fsvq->lock);
-               fsvq->in_flight--;
+               dec_in_flight_req(fsvq);
                spin_unlock(&fsvq->lock);
        }
 }
@@ -502,6 +553,7 @@ static int virtio_fs_setup_vqs(struct virtio_device *vdev,
        names[VQ_HIPRIO] = fs->vqs[VQ_HIPRIO].name;
        INIT_WORK(&fs->vqs[VQ_HIPRIO].done_work, virtio_fs_hiprio_done_work);
        INIT_LIST_HEAD(&fs->vqs[VQ_HIPRIO].queued_reqs);
+       INIT_LIST_HEAD(&fs->vqs[VQ_HIPRIO].end_reqs);
        INIT_DELAYED_WORK(&fs->vqs[VQ_HIPRIO].dispatch_work,
                        virtio_fs_hiprio_dispatch_work);
        spin_lock_init(&fs->vqs[VQ_HIPRIO].lock);
@@ -511,8 +563,9 @@ static int virtio_fs_setup_vqs(struct virtio_device *vdev,
                spin_lock_init(&fs->vqs[i].lock);
                INIT_WORK(&fs->vqs[i].done_work, virtio_fs_requests_done_work);
                INIT_DELAYED_WORK(&fs->vqs[i].dispatch_work,
-                                       virtio_fs_dummy_dispatch_work);
+                                 virtio_fs_request_dispatch_work);
                INIT_LIST_HEAD(&fs->vqs[i].queued_reqs);
+               INIT_LIST_HEAD(&fs->vqs[i].end_reqs);
                snprintf(fs->vqs[i].name, sizeof(fs->vqs[i].name),
                         "requests.%u", i - VQ_REQUEST);
                callbacks[i] = virtio_fs_vq_done;
@@ -708,6 +761,7 @@ __releases(fiq->lock)
                        list_add_tail(&forget->list, &fsvq->queued_reqs);
                        schedule_delayed_work(&fsvq->dispatch_work,
                                        msecs_to_jiffies(1));
+                       inc_in_flight_req(fsvq);
                } else {
                        pr_debug("virtio-fs: Could not queue FORGET: err=%d. Dropping it.\n",
                                 ret);
@@ -717,7 +771,7 @@ __releases(fiq->lock)
                goto out;
        }
 
-       fsvq->in_flight++;
+       inc_in_flight_req(fsvq);
        notify = virtqueue_kick_prepare(vq);
 
        spin_unlock(&fsvq->lock);
@@ -819,7 +873,7 @@ static unsigned int sg_init_fuse_args(struct scatterlist *sg,
 
 /* Add a request to a virtqueue and kick the device */
 static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq,
-                                struct fuse_req *req)
+                                struct fuse_req *req, bool in_flight)
 {
        /* requests need at least 4 elements */
        struct scatterlist *stack_sgs[6];
@@ -835,6 +889,7 @@ static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq,
        unsigned int i;
        int ret;
        bool notify;
+       struct fuse_pqueue *fpq;
 
        /* Does the sglist fit on the stack? */
        total_sgs = sg_count_fuse_req(req);
@@ -889,7 +944,17 @@ static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq,
                goto out;
        }
 
-       fsvq->in_flight++;
+       /* Request successfully sent. */
+       fpq = &fsvq->fud->pq;
+       spin_lock(&fpq->lock);
+       list_add_tail(&req->list, fpq->processing);
+       spin_unlock(&fpq->lock);
+       set_bit(FR_SENT, &req->flags);
+       /* matches barrier in request_wait_answer() */
+       smp_mb__after_atomic();
+
+       if (!in_flight)
+               inc_in_flight_req(fsvq);
        notify = virtqueue_kick_prepare(vq);
 
        spin_unlock(&fsvq->lock);
@@ -915,9 +980,8 @@ __releases(fiq->lock)
 {
        unsigned int queue_id = VQ_REQUEST; /* TODO multiqueue */
        struct virtio_fs *fs;
-       struct fuse_conn *fc;
        struct fuse_req *req;
-       struct fuse_pqueue *fpq;
+       struct virtio_fs_vq *fsvq;
        int ret;
 
        WARN_ON(list_empty(&fiq->pending));
@@ -928,44 +992,36 @@ __releases(fiq->lock)
        spin_unlock(&fiq->lock);
 
        fs = fiq->priv;
-       fc = fs->vqs[queue_id].fud->fc;
 
        pr_debug("%s: opcode %u unique %#llx nodeid %#llx in.len %u out.len %u\n",
                  __func__, req->in.h.opcode, req->in.h.unique,
                 req->in.h.nodeid, req->in.h.len,
                 fuse_len_args(req->args->out_numargs, req->args->out_args));
 
-       fpq = &fs->vqs[queue_id].fud->pq;
-       spin_lock(&fpq->lock);
-       if (!fpq->connected) {
-               spin_unlock(&fpq->lock);
-               req->out.h.error = -ENODEV;
-               pr_err("virtio-fs: %s disconnected\n", __func__);
-               fuse_request_end(fc, req);
-               return;
-       }
-       list_add_tail(&req->list, fpq->processing);
-       spin_unlock(&fpq->lock);
-       set_bit(FR_SENT, &req->flags);
-       /* matches barrier in request_wait_answer() */
-       smp_mb__after_atomic();
-
-retry:
-       ret = virtio_fs_enqueue_req(&fs->vqs[queue_id], req);
+       fsvq = &fs->vqs[queue_id];
+       ret = virtio_fs_enqueue_req(fsvq, req, false);
        if (ret < 0) {
                if (ret == -ENOMEM || ret == -ENOSPC) {
-                       /* Virtqueue full. Retry submission */
-                       /* TODO use completion instead of timeout */
-                       usleep_range(20, 30);
-                       goto retry;
+                       /*
+                        * Virtqueue full. Retry submission from worker
+                        * context as we might be holding fc->bg_lock.
+                        */
+                       spin_lock(&fsvq->lock);
+                       list_add_tail(&req->list, &fsvq->queued_reqs);
+                       inc_in_flight_req(fsvq);
+                       schedule_delayed_work(&fsvq->dispatch_work,
+                                               msecs_to_jiffies(1));
+                       spin_unlock(&fsvq->lock);
+                       return;
                }
                req->out.h.error = ret;
                pr_err("virtio-fs: virtio_fs_enqueue_req() failed %d\n", ret);
-               spin_lock(&fpq->lock);
-               clear_bit(FR_SENT, &req->flags);
-               list_del_init(&req->list);
-               spin_unlock(&fpq->lock);
-               fuse_request_end(fc, req);
+
+               /* Can't end request in submission context. Use a worker */
+               spin_lock(&fsvq->lock);
+               list_add_tail(&req->list, &fsvq->end_reqs);
+               schedule_delayed_work(&fsvq->dispatch_work, 0);
+               spin_unlock(&fsvq->lock);
                return;
        }
 }
@@ -992,6 +1048,7 @@ static int virtio_fs_fill_super(struct super_block *sb)
                .destroy = true,
                .no_control = true,
                .no_force_umount = true,
+               .no_mount_options = true,
        };
 
        mutex_lock(&virtio_fs_mutex);
index 681b44682b0db6a6016303ec515c291720e6ff32..18daf494abab9e2492ab12272358d151e5c5538a 100644 (file)
@@ -1540,17 +1540,23 @@ static int gfs2_init_fs_context(struct fs_context *fc)
 {
        struct gfs2_args *args;
 
-       args = kzalloc(sizeof(*args), GFP_KERNEL);
+       args = kmalloc(sizeof(*args), GFP_KERNEL);
        if (args == NULL)
                return -ENOMEM;
 
-       args->ar_quota = GFS2_QUOTA_DEFAULT;
-       args->ar_data = GFS2_DATA_DEFAULT;
-       args->ar_commit = 30;
-       args->ar_statfs_quantum = 30;
-       args->ar_quota_quantum = 60;
-       args->ar_errors = GFS2_ERRORS_DEFAULT;
+       if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE) {
+               struct gfs2_sbd *sdp = fc->root->d_sb->s_fs_info;
 
+               *args = sdp->sd_args;
+       } else {
+               memset(args, 0, sizeof(*args));
+               args->ar_quota = GFS2_QUOTA_DEFAULT;
+               args->ar_data = GFS2_DATA_DEFAULT;
+               args->ar_commit = 30;
+               args->ar_statfs_quantum = 30;
+               args->ar_quota_quantum = 60;
+               args->ar_errors = GFS2_ERRORS_DEFAULT;
+       }
        fc->fs_private = args;
        fc->ops = &gfs2_context_ops;
        return 0;
@@ -1600,6 +1606,7 @@ static int gfs2_meta_get_tree(struct fs_context *fc)
 }
 
 static const struct fs_context_operations gfs2_meta_context_ops = {
+       .free        = gfs2_fc_free,
        .get_tree    = gfs2_meta_get_tree,
 };
 
index 67dbe0201e0d46c334cb7ba17c2dfadd6cca3087..f9a38998f2fc515c94c4cc292e00450a55aaa912 100644 (file)
@@ -197,6 +197,7 @@ struct io_ring_ctx {
                unsigned                sq_entries;
                unsigned                sq_mask;
                unsigned                sq_thread_idle;
+               unsigned                cached_sq_dropped;
                struct io_uring_sqe     *sq_sqes;
 
                struct list_head        defer_list;
@@ -212,6 +213,7 @@ struct io_ring_ctx {
 
        struct {
                unsigned                cached_cq_tail;
+               atomic_t                cached_cq_overflow;
                unsigned                cq_entries;
                unsigned                cq_mask;
                struct wait_queue_head  cq_wait;
@@ -420,7 +422,8 @@ static struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
 static inline bool __io_sequence_defer(struct io_ring_ctx *ctx,
                                       struct io_kiocb *req)
 {
-       return req->sequence != ctx->cached_cq_tail + ctx->rings->sq_dropped;
+       return req->sequence != ctx->cached_cq_tail + ctx->cached_sq_dropped
+                                       + atomic_read(&ctx->cached_cq_overflow);
 }
 
 static inline bool io_sequence_defer(struct io_ring_ctx *ctx,
@@ -567,9 +570,8 @@ static void io_cqring_fill_event(struct io_ring_ctx *ctx, u64 ki_user_data,
                WRITE_ONCE(cqe->res, res);
                WRITE_ONCE(cqe->flags, 0);
        } else {
-               unsigned overflow = READ_ONCE(ctx->rings->cq_overflow);
-
-               WRITE_ONCE(ctx->rings->cq_overflow, overflow + 1);
+               WRITE_ONCE(ctx->rings->cq_overflow,
+                               atomic_inc_return(&ctx->cached_cq_overflow));
        }
 }
 
@@ -735,6 +737,14 @@ static unsigned io_cqring_events(struct io_rings *rings)
        return READ_ONCE(rings->cq.tail) - READ_ONCE(rings->cq.head);
 }
 
+static inline unsigned int io_sqring_entries(struct io_ring_ctx *ctx)
+{
+       struct io_rings *rings = ctx->rings;
+
+       /* make sure SQ entry isn't read before tail */
+       return smp_load_acquire(&rings->sq.tail) - ctx->cached_sq_head;
+}
+
 /*
  * Find and free completed poll iocbs
  */
@@ -864,19 +874,11 @@ static void io_iopoll_reap_events(struct io_ring_ctx *ctx)
        mutex_unlock(&ctx->uring_lock);
 }
 
-static int io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events,
-                          long min)
+static int __io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events,
+                           long min)
 {
-       int iters, ret = 0;
+       int iters = 0, ret = 0;
 
-       /*
-        * We disallow the app entering submit/complete with polling, but we
-        * still need to lock the ring to prevent racing with polled issue
-        * that got punted to a workqueue.
-        */
-       mutex_lock(&ctx->uring_lock);
-
-       iters = 0;
        do {
                int tmin = 0;
 
@@ -912,6 +914,21 @@ static int io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events,
                ret = 0;
        } while (min && !*nr_events && !need_resched());
 
+       return ret;
+}
+
+static int io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events,
+                          long min)
+{
+       int ret;
+
+       /*
+        * We disallow the app entering submit/complete with polling, but we
+        * still need to lock the ring to prevent racing with polled issue
+        * that got punted to a workqueue.
+        */
+       mutex_lock(&ctx->uring_lock);
+       ret = __io_iopoll_check(ctx, nr_events, min);
        mutex_unlock(&ctx->uring_lock);
        return ret;
 }
@@ -1107,6 +1124,7 @@ static int io_prep_rw(struct io_kiocb *req, const struct sqe_submit *s,
 
                kiocb->ki_flags |= IOCB_HIPRI;
                kiocb->ki_complete = io_complete_rw_iopoll;
+               req->result = 0;
        } else {
                if (kiocb->ki_flags & IOCB_HIPRI)
                        return -EINVAL;
@@ -1877,7 +1895,7 @@ static int io_poll_add(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 static enum hrtimer_restart io_timeout_fn(struct hrtimer *timer)
 {
        struct io_ring_ctx *ctx;
-       struct io_kiocb *req;
+       struct io_kiocb *req, *prev;
        unsigned long flags;
 
        req = container_of(timer, struct io_kiocb, timeout.timer);
@@ -1885,6 +1903,15 @@ static enum hrtimer_restart io_timeout_fn(struct hrtimer *timer)
        atomic_inc(&ctx->cq_timeouts);
 
        spin_lock_irqsave(&ctx->completion_lock, flags);
+       /*
+        * Adjust the reqs sequence before the current one because it
+        * will consume a slot in the cq_ring and the the cq_tail pointer
+        * will be increased, otherwise other timeout reqs may return in
+        * advance without waiting for enough wait_nr.
+        */
+       prev = req;
+       list_for_each_entry_continue_reverse(prev, &ctx->timeout_list, list)
+               prev->sequence++;
        list_del(&req->list);
 
        io_cqring_fill_event(ctx, req->user_data, -ETIME);
@@ -1903,6 +1930,7 @@ static int io_timeout(struct io_kiocb *req, const struct io_uring_sqe *sqe)
        struct io_ring_ctx *ctx = req->ctx;
        struct list_head *entry;
        struct timespec64 ts;
+       unsigned span = 0;
 
        if (unlikely(ctx->flags & IORING_SETUP_IOPOLL))
                return -EINVAL;
@@ -1951,9 +1979,17 @@ static int io_timeout(struct io_kiocb *req, const struct io_uring_sqe *sqe)
                if (ctx->cached_sq_head < nxt_sq_head)
                        tmp += UINT_MAX;
 
-               if (tmp >= tmp_nxt)
+               if (tmp > tmp_nxt)
                        break;
+
+               /*
+                * Sequence of reqs after the insert one and itself should
+                * be adjusted because each timeout req consumes a slot.
+                */
+               span++;
+               nxt->sequence++;
        }
+       req->sequence -= span;
        list_add(&req->list, entry);
        spin_unlock_irq(&ctx->completion_lock);
 
@@ -2292,11 +2328,11 @@ static int io_req_set_file(struct io_ring_ctx *ctx, const struct sqe_submit *s,
 }
 
 static int __io_queue_sqe(struct io_ring_ctx *ctx, struct io_kiocb *req,
-                       struct sqe_submit *s, bool force_nonblock)
+                       struct sqe_submit *s)
 {
        int ret;
 
-       ret = __io_submit_sqe(ctx, req, s, force_nonblock);
+       ret = __io_submit_sqe(ctx, req, s, true);
 
        /*
         * We async punt it if the file wasn't marked NOWAIT, or if the file
@@ -2343,7 +2379,7 @@ static int __io_queue_sqe(struct io_ring_ctx *ctx, struct io_kiocb *req,
 }
 
 static int io_queue_sqe(struct io_ring_ctx *ctx, struct io_kiocb *req,
-                       struct sqe_submit *s, bool force_nonblock)
+                       struct sqe_submit *s)
 {
        int ret;
 
@@ -2356,18 +2392,17 @@ static int io_queue_sqe(struct io_ring_ctx *ctx, struct io_kiocb *req,
                return 0;
        }
 
-       return __io_queue_sqe(ctx, req, s, force_nonblock);
+       return __io_queue_sqe(ctx, req, s);
 }
 
 static int io_queue_link_head(struct io_ring_ctx *ctx, struct io_kiocb *req,
-                             struct sqe_submit *s, struct io_kiocb *shadow,
-                             bool force_nonblock)
+                             struct sqe_submit *s, struct io_kiocb *shadow)
 {
        int ret;
        int need_submit = false;
 
        if (!shadow)
-               return io_queue_sqe(ctx, req, s, force_nonblock);
+               return io_queue_sqe(ctx, req, s);
 
        /*
         * Mark the first IO in link list as DRAIN, let all the following
@@ -2379,6 +2414,7 @@ static int io_queue_link_head(struct io_ring_ctx *ctx, struct io_kiocb *req,
        if (ret) {
                if (ret != -EIOCBQUEUED) {
                        io_free_req(req);
+                       __io_free_req(shadow);
                        io_cqring_add_event(ctx, s->sqe->user_data, ret);
                        return 0;
                }
@@ -2396,7 +2432,7 @@ static int io_queue_link_head(struct io_ring_ctx *ctx, struct io_kiocb *req,
        spin_unlock_irq(&ctx->completion_lock);
 
        if (need_submit)
-               return __io_queue_sqe(ctx, req, s, force_nonblock);
+               return __io_queue_sqe(ctx, req, s);
 
        return 0;
 }
@@ -2404,8 +2440,7 @@ static int io_queue_link_head(struct io_ring_ctx *ctx, struct io_kiocb *req,
 #define SQE_VALID_FLAGS        (IOSQE_FIXED_FILE|IOSQE_IO_DRAIN|IOSQE_IO_LINK)
 
 static void io_submit_sqe(struct io_ring_ctx *ctx, struct sqe_submit *s,
-                         struct io_submit_state *state, struct io_kiocb **link,
-                         bool force_nonblock)
+                         struct io_submit_state *state, struct io_kiocb **link)
 {
        struct io_uring_sqe *sqe_copy;
        struct io_kiocb *req;
@@ -2432,6 +2467,8 @@ err:
                return;
        }
 
+       req->user_data = s->sqe->user_data;
+
        /*
         * If we already have a head request, queue this one for async
         * submittal once the head completes. If we don't have a head but
@@ -2458,7 +2495,7 @@ err:
                INIT_LIST_HEAD(&req->link_list);
                *link = req;
        } else {
-               io_queue_sqe(ctx, req, s, force_nonblock);
+               io_queue_sqe(ctx, req, s);
        }
 }
 
@@ -2538,12 +2575,13 @@ static bool io_get_sqring(struct io_ring_ctx *ctx, struct sqe_submit *s)
 
        /* drop invalid entries */
        ctx->cached_sq_head++;
-       rings->sq_dropped++;
+       ctx->cached_sq_dropped++;
+       WRITE_ONCE(rings->sq_dropped, ctx->cached_sq_dropped);
        return false;
 }
 
-static int io_submit_sqes(struct io_ring_ctx *ctx, struct sqe_submit *sqes,
-                         unsigned int nr, bool has_user, bool mm_fault)
+static int io_submit_sqes(struct io_ring_ctx *ctx, unsigned int nr,
+                         bool has_user, bool mm_fault)
 {
        struct io_submit_state state, *statep = NULL;
        struct io_kiocb *link = NULL;
@@ -2557,19 +2595,23 @@ static int io_submit_sqes(struct io_ring_ctx *ctx, struct sqe_submit *sqes,
        }
 
        for (i = 0; i < nr; i++) {
+               struct sqe_submit s;
+
+               if (!io_get_sqring(ctx, &s))
+                       break;
+
                /*
                 * If previous wasn't linked and we have a linked command,
                 * that's the end of the chain. Submit the previous link.
                 */
                if (!prev_was_link && link) {
-                       io_queue_link_head(ctx, link, &link->submit, shadow_req,
-                                               true);
+                       io_queue_link_head(ctx, link, &link->submit, shadow_req);
                        link = NULL;
                        shadow_req = NULL;
                }
-               prev_was_link = (sqes[i].sqe->flags & IOSQE_IO_LINK) != 0;
+               prev_was_link = (s.sqe->flags & IOSQE_IO_LINK) != 0;
 
-               if (link && (sqes[i].sqe->flags & IOSQE_IO_DRAIN)) {
+               if (link && (s.sqe->flags & IOSQE_IO_DRAIN)) {
                        if (!shadow_req) {
                                shadow_req = io_get_req(ctx, NULL);
                                if (unlikely(!shadow_req))
@@ -2577,24 +2619,24 @@ static int io_submit_sqes(struct io_ring_ctx *ctx, struct sqe_submit *sqes,
                                shadow_req->flags |= (REQ_F_IO_DRAIN | REQ_F_SHADOW_DRAIN);
                                refcount_dec(&shadow_req->refs);
                        }
-                       shadow_req->sequence = sqes[i].sequence;
+                       shadow_req->sequence = s.sequence;
                }
 
 out:
                if (unlikely(mm_fault)) {
-                       io_cqring_add_event(ctx, sqes[i].sqe->user_data,
+                       io_cqring_add_event(ctx, s.sqe->user_data,
                                                -EFAULT);
                } else {
-                       sqes[i].has_user = has_user;
-                       sqes[i].needs_lock = true;
-                       sqes[i].needs_fixed_file = true;
-                       io_submit_sqe(ctx, &sqes[i], statep, &link, true);
+                       s.has_user = has_user;
+                       s.needs_lock = true;
+                       s.needs_fixed_file = true;
+                       io_submit_sqe(ctx, &s, statep, &link);
                        submitted++;
                }
        }
 
        if (link)
-               io_queue_link_head(ctx, link, &link->submit, shadow_req, true);
+               io_queue_link_head(ctx, link, &link->submit, shadow_req);
        if (statep)
                io_submit_state_end(&state);
 
@@ -2603,7 +2645,6 @@ out:
 
 static int io_sq_thread(void *data)
 {
-       struct sqe_submit sqes[IO_IOPOLL_BATCH];
        struct io_ring_ctx *ctx = data;
        struct mm_struct *cur_mm = NULL;
        mm_segment_t old_fs;
@@ -2618,14 +2659,27 @@ static int io_sq_thread(void *data)
 
        timeout = inflight = 0;
        while (!kthread_should_park()) {
-               bool all_fixed, mm_fault = false;
-               int i;
+               bool mm_fault = false;
+               unsigned int to_submit;
 
                if (inflight) {
                        unsigned nr_events = 0;
 
                        if (ctx->flags & IORING_SETUP_IOPOLL) {
-                               io_iopoll_check(ctx, &nr_events, 0);
+                               /*
+                                * inflight is the count of the maximum possible
+                                * entries we submitted, but it can be smaller
+                                * if we dropped some of them. If we don't have
+                                * poll entries available, then we know that we
+                                * have nothing left to poll for. Reset the
+                                * inflight count to zero in that case.
+                                */
+                               mutex_lock(&ctx->uring_lock);
+                               if (!list_empty(&ctx->poll_list))
+                                       __io_iopoll_check(ctx, &nr_events, 0);
+                               else
+                                       inflight = 0;
+                               mutex_unlock(&ctx->uring_lock);
                        } else {
                                /*
                                 * Normal IO, just pretend everything completed.
@@ -2639,7 +2693,8 @@ static int io_sq_thread(void *data)
                                timeout = jiffies + ctx->sq_thread_idle;
                }
 
-               if (!io_get_sqring(ctx, &sqes[0])) {
+               to_submit = io_sqring_entries(ctx);
+               if (!to_submit) {
                        /*
                         * We're polling. If we're within the defined idle
                         * period, then let us spin without work before going
@@ -2670,7 +2725,8 @@ static int io_sq_thread(void *data)
                        /* make sure to read SQ tail after writing flags */
                        smp_mb();
 
-                       if (!io_get_sqring(ctx, &sqes[0])) {
+                       to_submit = io_sqring_entries(ctx);
+                       if (!to_submit) {
                                if (kthread_should_park()) {
                                        finish_wait(&ctx->sqo_wait, &wait);
                                        break;
@@ -2688,19 +2744,8 @@ static int io_sq_thread(void *data)
                        ctx->rings->sq_flags &= ~IORING_SQ_NEED_WAKEUP;
                }
 
-               i = 0;
-               all_fixed = true;
-               do {
-                       if (all_fixed && io_sqe_needs_user(sqes[i].sqe))
-                               all_fixed = false;
-
-                       i++;
-                       if (i == ARRAY_SIZE(sqes))
-                               break;
-               } while (io_get_sqring(ctx, &sqes[i]));
-
                /* Unless all new commands are FIXED regions, grab mm */
-               if (!all_fixed && !cur_mm) {
+               if (!cur_mm) {
                        mm_fault = !mmget_not_zero(ctx->sqo_mm);
                        if (!mm_fault) {
                                use_mm(ctx->sqo_mm);
@@ -2708,8 +2753,9 @@ static int io_sq_thread(void *data)
                        }
                }
 
-               inflight += io_submit_sqes(ctx, sqes, i, cur_mm != NULL,
-                                               mm_fault);
+               to_submit = min(to_submit, ctx->sq_entries);
+               inflight += io_submit_sqes(ctx, to_submit, cur_mm != NULL,
+                                          mm_fault);
 
                /* Commit SQ ring head once we've consumed all SQEs */
                io_commit_sqring(ctx);
@@ -2726,8 +2772,7 @@ static int io_sq_thread(void *data)
        return 0;
 }
 
-static int io_ring_submit(struct io_ring_ctx *ctx, unsigned int to_submit,
-                         bool block_for_last)
+static int io_ring_submit(struct io_ring_ctx *ctx, unsigned int to_submit)
 {
        struct io_submit_state state, *statep = NULL;
        struct io_kiocb *link = NULL;
@@ -2741,7 +2786,6 @@ static int io_ring_submit(struct io_ring_ctx *ctx, unsigned int to_submit,
        }
 
        for (i = 0; i < to_submit; i++) {
-               bool force_nonblock = true;
                struct sqe_submit s;
 
                if (!io_get_sqring(ctx, &s))
@@ -2752,8 +2796,7 @@ static int io_ring_submit(struct io_ring_ctx *ctx, unsigned int to_submit,
                 * that's the end of the chain. Submit the previous link.
                 */
                if (!prev_was_link && link) {
-                       io_queue_link_head(ctx, link, &link->submit, shadow_req,
-                                               force_nonblock);
+                       io_queue_link_head(ctx, link, &link->submit, shadow_req);
                        link = NULL;
                        shadow_req = NULL;
                }
@@ -2775,27 +2818,16 @@ out:
                s.needs_lock = false;
                s.needs_fixed_file = false;
                submit++;
-
-               /*
-                * The caller will block for events after submit, submit the
-                * last IO non-blocking. This is either the only IO it's
-                * submitting, or it already submitted the previous ones. This
-                * improves performance by avoiding an async punt that we don't
-                * need to do.
-                */
-               if (block_for_last && submit == to_submit)
-                       force_nonblock = false;
-
-               io_submit_sqe(ctx, &s, statep, &link, force_nonblock);
+               io_submit_sqe(ctx, &s, statep, &link);
        }
-       io_commit_sqring(ctx);
 
        if (link)
-               io_queue_link_head(ctx, link, &link->submit, shadow_req,
-                                       !block_for_last);
+               io_queue_link_head(ctx, link, &link->submit, shadow_req);
        if (statep)
                io_submit_state_end(statep);
 
+       io_commit_sqring(ctx);
+
        return submit;
 }
 
@@ -3636,21 +3668,10 @@ SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit,
                        wake_up(&ctx->sqo_wait);
                submitted = to_submit;
        } else if (to_submit) {
-               bool block_for_last = false;
-
                to_submit = min(to_submit, ctx->sq_entries);
 
-               /*
-                * Allow last submission to block in a series, IFF the caller
-                * asked to wait for events and we don't currently have
-                * enough. This potentially avoids an async punt.
-                */
-               if (to_submit == min_complete &&
-                   io_cqring_events(ctx->rings) < min_complete)
-                       block_for_last = true;
-
                mutex_lock(&ctx->uring_lock);
-               submitted = io_ring_submit(ctx, to_submit, block_for_last);
+               submitted = io_ring_submit(ctx, to_submit);
                mutex_unlock(&ctx->uring_lock);
        }
        if (flags & IORING_ENTER_GETEVENTS) {
@@ -3809,10 +3830,6 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p)
        if (ret)
                goto err;
 
-       ret = io_uring_get_fd(ctx);
-       if (ret < 0)
-               goto err;
-
        memset(&p->sq_off, 0, sizeof(p->sq_off));
        p->sq_off.head = offsetof(struct io_rings, sq.head);
        p->sq_off.tail = offsetof(struct io_rings, sq.tail);
@@ -3830,6 +3847,14 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p)
        p->cq_off.overflow = offsetof(struct io_rings, cq_overflow);
        p->cq_off.cqes = offsetof(struct io_rings, cqes);
 
+       /*
+        * Install ring fd as the very last thing, so we don't risk someone
+        * having closed it before we finish setup
+        */
+       ret = io_uring_get_fd(ctx);
+       if (ret < 0)
+               goto err;
+
        p->features = IORING_FEAT_SINGLE_MMAP;
        return ret;
 err:
index 071b90a45933a4b95c176e8042a29130e07a71f1..af549d70ec507e3f8deb920c3a93509bd59a5ed2 100644 (file)
@@ -53,6 +53,16 @@ nfs4_is_valid_delegation(const struct nfs_delegation *delegation,
        return false;
 }
 
+struct nfs_delegation *nfs4_get_valid_delegation(const struct inode *inode)
+{
+       struct nfs_delegation *delegation;
+
+       delegation = rcu_dereference(NFS_I(inode)->delegation);
+       if (nfs4_is_valid_delegation(delegation, 0))
+               return delegation;
+       return NULL;
+}
+
 static int
 nfs4_do_check_delegation(struct inode *inode, fmode_t flags, bool mark)
 {
@@ -1181,7 +1191,7 @@ bool nfs4_refresh_delegation_stateid(nfs4_stateid *dst, struct inode *inode)
        if (delegation != NULL &&
            nfs4_stateid_match_other(dst, &delegation->stateid)) {
                dst->seqid = delegation->stateid.seqid;
-               return ret;
+               ret = true;
        }
        rcu_read_unlock();
 out:
index 9eb87ae4c98276632ab799e5b66487df9cdcd3e4..8b14d441e699bc472a4a4c60c5e969384aca0233 100644 (file)
@@ -68,6 +68,7 @@ int nfs4_lock_delegation_recall(struct file_lock *fl, struct nfs4_state *state,
 bool nfs4_copy_delegation_stateid(struct inode *inode, fmode_t flags, nfs4_stateid *dst, const struct cred **cred);
 bool nfs4_refresh_delegation_stateid(nfs4_stateid *dst, struct inode *inode);
 
+struct nfs_delegation *nfs4_get_valid_delegation(const struct inode *inode);
 void nfs_mark_delegation_referenced(struct nfs_delegation *delegation);
 int nfs4_have_delegation(struct inode *inode, fmode_t flags);
 int nfs4_check_delegation(struct inode *inode, fmode_t flags);
index ab8ca20fd5790a9e0d129b3a4d7f3a397a1dd9e2..caacf5e7f5e1568474feb57f6e4d85aa19efdc8b 100644 (file)
@@ -1440,8 +1440,6 @@ static int can_open_delegated(struct nfs_delegation *delegation, fmode_t fmode,
                return 0;
        if ((delegation->type & fmode) != fmode)
                return 0;
-       if (test_bit(NFS_DELEGATION_RETURNING, &delegation->flags))
-               return 0;
        switch (claim) {
        case NFS4_OPEN_CLAIM_NULL:
        case NFS4_OPEN_CLAIM_FH:
@@ -1810,7 +1808,6 @@ static void nfs4_return_incompatible_delegation(struct inode *inode, fmode_t fmo
 static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
 {
        struct nfs4_state *state = opendata->state;
-       struct nfs_inode *nfsi = NFS_I(state->inode);
        struct nfs_delegation *delegation;
        int open_mode = opendata->o_arg.open_flags;
        fmode_t fmode = opendata->o_arg.fmode;
@@ -1827,7 +1824,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
                }
                spin_unlock(&state->owner->so_lock);
                rcu_read_lock();
-               delegation = rcu_dereference(nfsi->delegation);
+               delegation = nfs4_get_valid_delegation(state->inode);
                if (!can_open_delegated(delegation, fmode, claim)) {
                        rcu_read_unlock();
                        break;
@@ -2371,7 +2368,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
                                        data->o_arg.open_flags, claim))
                        goto out_no_action;
                rcu_read_lock();
-               delegation = rcu_dereference(NFS_I(data->state->inode)->delegation);
+               delegation = nfs4_get_valid_delegation(data->state->inode);
                if (can_open_delegated(delegation, data->o_arg.fmode, claim))
                        goto unlock_no_action;
                rcu_read_unlock();
index 53939bf9d7d260f1ebfb1da514973a76a92322b3..9876db52913a4fda2a67ecf746a553bd0728eea1 100644 (file)
@@ -2098,53 +2098,89 @@ static int ocfs2_is_io_unaligned(struct inode *inode, size_t count, loff_t pos)
        return 0;
 }
 
-static int ocfs2_prepare_inode_for_refcount(struct inode *inode,
-                                           struct file *file,
-                                           loff_t pos, size_t count,
-                                           int *meta_level)
+static int ocfs2_inode_lock_for_extent_tree(struct inode *inode,
+                                           struct buffer_head **di_bh,
+                                           int meta_level,
+                                           int overwrite_io,
+                                           int write_sem,
+                                           int wait)
 {
-       int ret;
-       struct buffer_head *di_bh = NULL;
-       u32 cpos = pos >> OCFS2_SB(inode->i_sb)->s_clustersize_bits;
-       u32 clusters =
-               ocfs2_clusters_for_bytes(inode->i_sb, pos + count) - cpos;
+       int ret = 0;
 
-       ret = ocfs2_inode_lock(inode, &di_bh, 1);
-       if (ret) {
-               mlog_errno(ret);
+       if (wait)
+               ret = ocfs2_inode_lock(inode, NULL, meta_level);
+       else
+               ret = ocfs2_try_inode_lock(inode,
+                       overwrite_io ? NULL : di_bh, meta_level);
+       if (ret < 0)
                goto out;
+
+       if (wait) {
+               if (write_sem)
+                       down_write(&OCFS2_I(inode)->ip_alloc_sem);
+               else
+                       down_read(&OCFS2_I(inode)->ip_alloc_sem);
+       } else {
+               if (write_sem)
+                       ret = down_write_trylock(&OCFS2_I(inode)->ip_alloc_sem);
+               else
+                       ret = down_read_trylock(&OCFS2_I(inode)->ip_alloc_sem);
+
+               if (!ret) {
+                       ret = -EAGAIN;
+                       goto out_unlock;
+               }
        }
 
-       *meta_level = 1;
+       return ret;
 
-       ret = ocfs2_refcount_cow(inode, di_bh, cpos, clusters, UINT_MAX);
-       if (ret)
-               mlog_errno(ret);
+out_unlock:
+       brelse(*di_bh);
+       ocfs2_inode_unlock(inode, meta_level);
 out:
-       brelse(di_bh);
        return ret;
 }
 
+static void ocfs2_inode_unlock_for_extent_tree(struct inode *inode,
+                                              struct buffer_head **di_bh,
+                                              int meta_level,
+                                              int write_sem)
+{
+       if (write_sem)
+               up_write(&OCFS2_I(inode)->ip_alloc_sem);
+       else
+               up_read(&OCFS2_I(inode)->ip_alloc_sem);
+
+       brelse(*di_bh);
+       *di_bh = NULL;
+
+       if (meta_level >= 0)
+               ocfs2_inode_unlock(inode, meta_level);
+}
+
 static int ocfs2_prepare_inode_for_write(struct file *file,
                                         loff_t pos, size_t count, int wait)
 {
        int ret = 0, meta_level = 0, overwrite_io = 0;
+       int write_sem = 0;
        struct dentry *dentry = file->f_path.dentry;
        struct inode *inode = d_inode(dentry);
        struct buffer_head *di_bh = NULL;
+       u32 cpos;
+       u32 clusters;
 
        /*
         * We start with a read level meta lock and only jump to an ex
         * if we need to make modifications here.
         */
        for(;;) {
-               if (wait)
-                       ret = ocfs2_inode_lock(inode, NULL, meta_level);
-               else
-                       ret = ocfs2_try_inode_lock(inode,
-                               overwrite_io ? NULL : &di_bh, meta_level);
+               ret = ocfs2_inode_lock_for_extent_tree(inode,
+                                                      &di_bh,
+                                                      meta_level,
+                                                      overwrite_io,
+                                                      write_sem,
+                                                      wait);
                if (ret < 0) {
-                       meta_level = -1;
                        if (ret != -EAGAIN)
                                mlog_errno(ret);
                        goto out;
@@ -2156,15 +2192,8 @@ static int ocfs2_prepare_inode_for_write(struct file *file,
                 */
                if (!wait && !overwrite_io) {
                        overwrite_io = 1;
-                       if (!down_read_trylock(&OCFS2_I(inode)->ip_alloc_sem)) {
-                               ret = -EAGAIN;
-                               goto out_unlock;
-                       }
 
                        ret = ocfs2_overwrite_io(inode, di_bh, pos, count);
-                       brelse(di_bh);
-                       di_bh = NULL;
-                       up_read(&OCFS2_I(inode)->ip_alloc_sem);
                        if (ret < 0) {
                                if (ret != -EAGAIN)
                                        mlog_errno(ret);
@@ -2183,7 +2212,10 @@ static int ocfs2_prepare_inode_for_write(struct file *file,
                 * set inode->i_size at the end of a write. */
                if (should_remove_suid(dentry)) {
                        if (meta_level == 0) {
-                               ocfs2_inode_unlock(inode, meta_level);
+                               ocfs2_inode_unlock_for_extent_tree(inode,
+                                                                  &di_bh,
+                                                                  meta_level,
+                                                                  write_sem);
                                meta_level = 1;
                                continue;
                        }
@@ -2197,18 +2229,32 @@ static int ocfs2_prepare_inode_for_write(struct file *file,
 
                ret = ocfs2_check_range_for_refcount(inode, pos, count);
                if (ret == 1) {
-                       ocfs2_inode_unlock(inode, meta_level);
-                       meta_level = -1;
-
-                       ret = ocfs2_prepare_inode_for_refcount(inode,
-                                                              file,
-                                                              pos,
-                                                              count,
-                                                              &meta_level);
+                       ocfs2_inode_unlock_for_extent_tree(inode,
+                                                          &di_bh,
+                                                          meta_level,
+                                                          write_sem);
+                       ret = ocfs2_inode_lock_for_extent_tree(inode,
+                                                              &di_bh,
+                                                              meta_level,
+                                                              overwrite_io,
+                                                              1,
+                                                              wait);
+                       write_sem = 1;
+                       if (ret < 0) {
+                               if (ret != -EAGAIN)
+                                       mlog_errno(ret);
+                               goto out;
+                       }
+
+                       cpos = pos >> OCFS2_SB(inode->i_sb)->s_clustersize_bits;
+                       clusters =
+                               ocfs2_clusters_for_bytes(inode->i_sb, pos + count) - cpos;
+                       ret = ocfs2_refcount_cow(inode, di_bh, cpos, clusters, UINT_MAX);
                }
 
                if (ret < 0) {
-                       mlog_errno(ret);
+                       if (ret != -EAGAIN)
+                               mlog_errno(ret);
                        goto out_unlock;
                }
 
@@ -2219,10 +2265,10 @@ out_unlock:
        trace_ocfs2_prepare_inode_for_write(OCFS2_I(inode)->ip_blkno,
                                            pos, count, wait);
 
-       brelse(di_bh);
-
-       if (meta_level >= 0)
-               ocfs2_inode_unlock(inode, meta_level);
+       ocfs2_inode_unlock_for_extent_tree(inode,
+                                          &di_bh,
+                                          meta_level,
+                                          write_sem);
 
 out:
        return ret;
index f936033cb9e6d57e0b965b5cb742ac868c10c463..47805172e73d80e4ee3c771a462b0c1840847a10 100644 (file)
@@ -232,8 +232,8 @@ struct acpi_processor {
        struct acpi_processor_limit limit;
        struct thermal_cooling_device *cdev;
        struct device *dev; /* Processor device. */
-       struct dev_pm_qos_request perflib_req;
-       struct dev_pm_qos_request thermal_req;
+       struct freq_qos_request perflib_req;
+       struct freq_qos_request thermal_req;
 };
 
 struct acpi_processor_errata {
@@ -302,8 +302,8 @@ static inline void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx
 #ifdef CONFIG_CPU_FREQ
 extern bool acpi_processor_cpufreq_init;
 void acpi_processor_ignore_ppc_init(void);
-void acpi_processor_ppc_init(int cpu);
-void acpi_processor_ppc_exit(int cpu);
+void acpi_processor_ppc_init(struct cpufreq_policy *policy);
+void acpi_processor_ppc_exit(struct cpufreq_policy *policy);
 void acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag);
 extern int acpi_processor_get_bios_limit(int cpu, unsigned int *limit);
 #else
@@ -311,11 +311,11 @@ static inline void acpi_processor_ignore_ppc_init(void)
 {
        return;
 }
-static inline void acpi_processor_ppc_init(int cpu)
+static inline void acpi_processor_ppc_init(struct cpufreq_policy *policy)
 {
        return;
 }
-static inline void acpi_processor_ppc_exit(int cpu)
+static inline void acpi_processor_ppc_exit(struct cpufreq_policy *policy)
 {
        return;
 }
@@ -431,14 +431,14 @@ static inline int acpi_processor_hotplug(struct acpi_processor *pr)
 int acpi_processor_get_limit_info(struct acpi_processor *pr);
 extern const struct thermal_cooling_device_ops processor_cooling_ops;
 #if defined(CONFIG_ACPI_CPU_FREQ_PSS) & defined(CONFIG_CPU_FREQ)
-void acpi_thermal_cpufreq_init(int cpu);
-void acpi_thermal_cpufreq_exit(int cpu);
+void acpi_thermal_cpufreq_init(struct cpufreq_policy *policy);
+void acpi_thermal_cpufreq_exit(struct cpufreq_policy *policy);
 #else
-static inline void acpi_thermal_cpufreq_init(int cpu)
+static inline void acpi_thermal_cpufreq_init(struct cpufreq_policy *policy)
 {
        return;
 }
-static inline void acpi_thermal_cpufreq_exit(int cpu)
+static inline void acpi_thermal_cpufreq_exit(struct cpufreq_policy *policy)
 {
        return;
 }
index e94b19782c92ff4f79ff75964a61b3b207fdda94..ce41032086193dfb98e9ad1b444624d0dee7a207 100644 (file)
@@ -25,13 +25,6 @@ static __always_inline int __arch_get_clock_mode(struct timekeeper *tk)
 }
 #endif /* __arch_get_clock_mode */
 
-#ifndef __arch_use_vsyscall
-static __always_inline int __arch_use_vsyscall(struct vdso_data *vdata)
-{
-       return 1;
-}
-#endif /* __arch_use_vsyscall */
-
 #ifndef __arch_update_vsyscall
 static __always_inline void __arch_update_vsyscall(struct vdso_data *vdata,
                                                   struct timekeeper *tk)
index 6748379a0b44764092c2331d7f864e5fcb7817ff..e34a7b7f848a65ec293593061317013f063f12d8 100644 (file)
@@ -44,7 +44,20 @@ struct drm_gem_shmem_object {
         */
        unsigned int pages_use_count;
 
+       /**
+        * @madv: State for madvise
+        *
+        * 0 is active/inuse.
+        * A negative value is the object is purged.
+        * Positive values are driver specific and not used by the helpers.
+        */
        int madv;
+
+       /**
+        * @madv_list: List entry for madvise tracking
+        *
+        * Typically used by drivers to track purgeable objects
+        */
        struct list_head madv_list;
 
        /**
index 5b79d253fb46e80e0319e16f5eb9d2edbb74b1f6..520235c20708b5089b623caf9459dfd9351a72c8 100644 (file)
@@ -13,7 +13,8 @@ struct drm_crtc;
 
 void drm_self_refresh_helper_alter_state(struct drm_atomic_state *state);
 void drm_self_refresh_helper_update_avg_times(struct drm_atomic_state *state,
-                                             unsigned int commit_time_ms);
+                                       unsigned int commit_time_ms,
+                                       unsigned int new_self_refresh_mask);
 
 int drm_self_refresh_helper_init(struct drm_crtc *crtc);
 void drm_self_refresh_helper_cleanup(struct drm_crtc *crtc);
index 57b4121c750ae768351900a8a3a6b4899e5628a1..684692a8ed76c82b760f2a0a51c8a9b3412a8b58 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <drm/spsc_queue.h>
 #include <linux/dma-fence.h>
+#include <linux/completion.h>
 
 #define MAX_WAIT_SCHED_ENTITY_Q_EMPTY msecs_to_jiffies(1000)
 
@@ -71,6 +72,7 @@ enum drm_sched_priority {
  * @last_scheduled: points to the finished fence of the last scheduled job.
  * @last_user: last group leader pushing a job into the entity.
  * @stopped: Marks the enity as removed from rq and destined for termination.
+ * @entity_idle: Signals when enityt is not in use
  *
  * Entities will emit jobs in order to their corresponding hardware
  * ring, and the scheduler will alternate between entities based on
@@ -94,6 +96,7 @@ struct drm_sched_entity {
        struct dma_fence                *last_scheduled;
        struct task_struct              *last_user;
        bool                            stopped;
+       struct completion               entity_idle;
 };
 
 /**
index 5b9d2233860654512da6ff5ec8bf56f2343ed722..3bf3835d0e866a261f10adcdd97730fd3955429f 100644 (file)
@@ -656,11 +656,11 @@ void bpf_map_put_with_uref(struct bpf_map *map);
 void bpf_map_put(struct bpf_map *map);
 int bpf_map_charge_memlock(struct bpf_map *map, u32 pages);
 void bpf_map_uncharge_memlock(struct bpf_map *map, u32 pages);
-int bpf_map_charge_init(struct bpf_map_memory *mem, size_t size);
+int bpf_map_charge_init(struct bpf_map_memory *mem, u64 size);
 void bpf_map_charge_finish(struct bpf_map_memory *mem);
 void bpf_map_charge_move(struct bpf_map_memory *dst,
                         struct bpf_map_memory *src);
-void *bpf_map_area_alloc(size_t size, int numa_node);
+void *bpf_map_area_alloc(u64 size, int numa_node);
 void bpf_map_area_free(void *base);
 void bpf_map_init_from_attr(struct bpf_map *map, union bpf_attr *attr);
 
index c57e88e85c41c6389774e49b6e37057aa2ba3b03..92d5fdc8154ee9f1e2ec38b8a78b9b486240bd24 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/completion.h>
 #include <linux/kobject.h>
 #include <linux/notifier.h>
+#include <linux/pm_qos.h>
 #include <linux/spinlock.h>
 #include <linux/sysfs.h>
 
@@ -76,8 +77,10 @@ struct cpufreq_policy {
        struct work_struct      update; /* if update_policy() needs to be
                                         * called, but you're in IRQ context */
 
-       struct dev_pm_qos_request *min_freq_req;
-       struct dev_pm_qos_request *max_freq_req;
+       struct freq_constraints constraints;
+       struct freq_qos_request *min_freq_req;
+       struct freq_qos_request *max_freq_req;
+
        struct cpufreq_frequency_table  *freq_table;
        enum cpufreq_table_sorting freq_table_sorted;
 
index 6c809440f31978228acb3f29762ccb6901fd8341..4cf02ecd67de7f61c84ec7c8db22d48cd900fb85 100644 (file)
@@ -204,6 +204,12 @@ static inline int ddebug_dyndbg_module_param_cb(char *param, char *val,
        do { if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); } while (0)
 #define dynamic_dev_dbg(dev, fmt, ...)                                 \
        do { if (0) dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__); } while (0)
+#define dynamic_hex_dump(prefix_str, prefix_type, rowsize,             \
+                        groupsize, buf, len, ascii)                    \
+       do { if (0)                                                     \
+               print_hex_dump(KERN_DEBUG, prefix_str, prefix_type,     \
+                               rowsize, groupsize, buf, len, ascii);   \
+       } while (0)
 #endif
 
 #endif
index bd3837022307ac34271054b4024f8ec6bab09e5a..d87acf62958e207f941080c251048c9215df834e 100644 (file)
@@ -1579,9 +1579,22 @@ char *efi_convert_cmdline(efi_system_table_t *sys_table_arg,
 efi_status_t efi_get_memory_map(efi_system_table_t *sys_table_arg,
                                struct efi_boot_memmap *map);
 
+efi_status_t efi_low_alloc_above(efi_system_table_t *sys_table_arg,
+                                unsigned long size, unsigned long align,
+                                unsigned long *addr, unsigned long min);
+
+static inline
 efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg,
                           unsigned long size, unsigned long align,
-                          unsigned long *addr);
+                          unsigned long *addr)
+{
+       /*
+        * Don't allocate at 0x0. It will confuse code that
+        * checks pointers against NULL. Skip the first 8
+        * bytes so we start at a nice even number.
+        */
+       return efi_low_alloc_above(sys_table_arg, size, align, addr, 0x8);
+}
 
 efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg,
                            unsigned long size, unsigned long align,
@@ -1592,7 +1605,8 @@ efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg,
                                 unsigned long image_size,
                                 unsigned long alloc_size,
                                 unsigned long preferred_addr,
-                                unsigned long alignment);
+                                unsigned long alignment,
+                                unsigned long min_addr);
 
 efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
                                  efi_loaded_image_t *image,
index 621158ecd2e2146c697e3ab7cc7b0a3dd6bbc714..941d075f03d684d20b3c1c27c3a6304324e185f5 100644 (file)
@@ -18,8 +18,6 @@ extern struct module __this_module;
 #define THIS_MODULE ((struct module *)0)
 #endif
 
-#define NS_SEPARATOR "."
-
 #ifdef CONFIG_MODVERSIONS
 /* Mark the CRC weak since genksyms apparently decides not to
  * generate a checksums for some symbols */
@@ -48,11 +46,11 @@ extern struct module __this_module;
  * absolute relocations that require runtime processing on relocatable
  * kernels.
  */
-#define __KSYMTAB_ENTRY_NS(sym, sec, ns)                               \
+#define __KSYMTAB_ENTRY_NS(sym, sec)                                   \
        __ADDRESSABLE(sym)                                              \
        asm("   .section \"___ksymtab" sec "+" #sym "\", \"a\"  \n"     \
            "   .balign 4                                       \n"     \
-           "__ksymtab_" #ns NS_SEPARATOR #sym ":               \n"     \
+           "__ksymtab_" #sym ":                                \n"     \
            "   .long   " #sym "- .                             \n"     \
            "   .long   __kstrtab_" #sym "- .                   \n"     \
            "   .long   __kstrtabns_" #sym "- .                 \n"     \
@@ -74,16 +72,14 @@ struct kernel_symbol {
        int namespace_offset;
 };
 #else
-#define __KSYMTAB_ENTRY_NS(sym, sec, ns)                               \
-       static const struct kernel_symbol __ksymtab_##sym##__##ns       \
-       asm("__ksymtab_" #ns NS_SEPARATOR #sym)                         \
+#define __KSYMTAB_ENTRY_NS(sym, sec)                                   \
+       static const struct kernel_symbol __ksymtab_##sym               \
        __attribute__((section("___ksymtab" sec "+" #sym), used))       \
        __aligned(sizeof(void *))                                       \
        = { (unsigned long)&sym, __kstrtab_##sym, __kstrtabns_##sym }
 
 #define __KSYMTAB_ENTRY(sym, sec)                                      \
        static const struct kernel_symbol __ksymtab_##sym               \
-       asm("__ksymtab_" #sym)                                          \
        __attribute__((section("___ksymtab" sec "+" #sym), used))       \
        __aligned(sizeof(void *))                                       \
        = { (unsigned long)&sym, __kstrtab_##sym, NULL }
@@ -115,7 +111,7 @@ struct kernel_symbol {
        static const char __kstrtabns_##sym[]                           \
        __attribute__((section("__ksymtab_strings"), used, aligned(1))) \
        = #ns;                                                          \
-       __KSYMTAB_ENTRY_NS(sym, sec, ns)
+       __KSYMTAB_ENTRY_NS(sym, sec)
 
 #define ___EXPORT_SYMBOL(sym, sec)                                     \
        ___export_symbol_common(sym, sec);                              \
index 2ce57645f3cd4a00d8d385b7e1a05296191df476..0367a75f873b6b28510155591f68077732e4638d 100644 (file)
@@ -1099,7 +1099,6 @@ static inline void bpf_get_prog_name(const struct bpf_prog *prog, char *sym)
 
 #endif /* CONFIG_BPF_JIT */
 
-void bpf_prog_kallsyms_del_subprogs(struct bpf_prog *fp);
 void bpf_prog_kallsyms_del_all(struct bpf_prog *fp);
 
 #define BPF_ANC                BIT(15)
index fb07b503dc453ddfe16c5f0f959d46be01ad55ba..61f2f6ff94673b0a74d2d7705d87373bfba74fe5 100644 (file)
@@ -325,6 +325,29 @@ static inline bool gfpflags_allow_blocking(const gfp_t gfp_flags)
        return !!(gfp_flags & __GFP_DIRECT_RECLAIM);
 }
 
+/**
+ * gfpflags_normal_context - is gfp_flags a normal sleepable context?
+ * @gfp_flags: gfp_flags to test
+ *
+ * Test whether @gfp_flags indicates that the allocation is from the
+ * %current context and allowed to sleep.
+ *
+ * An allocation being allowed to block doesn't mean it owns the %current
+ * context.  When direct reclaim path tries to allocate memory, the
+ * allocation context is nested inside whatever %current was doing at the
+ * time of the original allocation.  The nested allocation may be allowed
+ * to block but modifying anything %current owns can corrupt the outer
+ * context's expectations.
+ *
+ * %true result from this function indicates that the allocation context
+ * can sleep and use anything that's associated with %current.
+ */
+static inline bool gfpflags_normal_context(const gfp_t gfp_flags)
+{
+       return (gfp_flags & (__GFP_DIRECT_RECLAIM | __GFP_MEMALLOC)) ==
+               __GFP_DIRECT_RECLAIM;
+}
+
 #ifdef CONFIG_HIGHMEM
 #define OPT_ZONE_HIGHMEM ZONE_HIGHMEM
 #else
index 4ec8986e5dfb61c7f2fd47abd2563893bb4deaa0..ac6e946b6767bba3d6750fafb374e364af1191b8 100644 (file)
@@ -185,7 +185,7 @@ static inline void idr_preload_end(void)
  * is convenient for a "not found" value.
  */
 #define idr_for_each_entry(idr, entry, id)                     \
-       for (id = 0; ((entry) = idr_get_next(idr, &(id))) != NULL; ++id)
+       for (id = 0; ((entry) = idr_get_next(idr, &(id))) != NULL; id += 1U)
 
 /**
  * idr_for_each_entry_ul() - Iterate over an IDR's elements of a given type.
index 2e55e4cdbd8aaf2fb6f1e9220ba2a8f3d6285de5..a367ead4bf4bb16e0c41544335031f85aa2d61b3 100644 (file)
@@ -29,7 +29,6 @@ struct macvlan_dev {
        netdev_features_t       set_features;
        enum macvlan_mode       mode;
        u16                     flags;
-       int                     nest_level;
        unsigned int            macaddr_count;
 #ifdef CONFIG_NET_POLL_CONTROLLER
        struct netpoll          *netpoll;
index 06faa066496f92fd381ae093568d640d3dfd1a1f..ec7e4bd07f825539c21c74e87bd2f675a72fac9a 100644 (file)
@@ -223,6 +223,7 @@ struct team {
                atomic_t count_pending;
                struct delayed_work dw;
        } mcast_rejoin;
+       struct lock_class_key team_lock_key;
        long mode_priv[TEAM_MODE_PRIV_LONGS];
 };
 
index 244278d5c222d250816256ac455d868f415ecc99..b05e855f1ddd4f2ea1cb0282ad754a7a50f826fe 100644 (file)
@@ -182,7 +182,6 @@ struct vlan_dev_priv {
 #ifdef CONFIG_NET_POLL_CONTROLLER
        struct netpoll                          *netpoll;
 #endif
-       unsigned int                            nest_level;
 };
 
 static inline struct vlan_dev_priv *vlan_dev_priv(const struct net_device *dev)
@@ -221,11 +220,6 @@ extern void vlan_vids_del_by_dev(struct net_device *dev,
 
 extern bool vlan_uses_dev(const struct net_device *dev);
 
-static inline int vlan_get_encap_level(struct net_device *dev)
-{
-       BUG_ON(!is_vlan_dev(dev));
-       return vlan_dev_priv(dev)->nest_level;
-}
 #else
 static inline struct net_device *
 __vlan_find_dev_deep_rcu(struct net_device *real_dev,
@@ -295,11 +289,6 @@ static inline bool vlan_uses_dev(const struct net_device *dev)
 {
        return false;
 }
-static inline int vlan_get_encap_level(struct net_device *dev)
-{
-       BUG();
-       return 0;
-}
 #endif
 
 /**
index 138c50d5a3533d7ad0b2c8757e9fff08c9b1b388..0836fe232f975718532f89b5b6e23bf79f2272dc 100644 (file)
@@ -1545,9 +1545,8 @@ struct mlx5_ifc_extended_dest_format_bits {
 };
 
 union mlx5_ifc_dest_format_struct_flow_counter_list_auto_bits {
-       struct mlx5_ifc_dest_format_struct_bits dest_format_struct;
+       struct mlx5_ifc_extended_dest_format_bits extended_dest_format;
        struct mlx5_ifc_flow_counter_list_bits flow_counter_list;
-       u8         reserved_at_0[0x40];
 };
 
 struct mlx5_ifc_fte_match_param_bits {
index cc292273e6ba0c0ac56d38d16aa1f87d65730393..a2adf95b3f9c5e1e026a3d1db1cb7136c992ca83 100644 (file)
@@ -695,11 +695,6 @@ static inline void *kvcalloc(size_t n, size_t size, gfp_t flags)
 
 extern void kvfree(const void *addr);
 
-static inline atomic_t *compound_mapcount_ptr(struct page *page)
-{
-       return &page[1].compound_mapcount;
-}
-
 static inline int compound_mapcount(struct page *page)
 {
        VM_BUG_ON_PAGE(!PageCompound(page), page);
index 2222fa795284183344d603c5286fcfd8c40dffa3..270aa8fd2800b4234297fa7c27577705f8c24395 100644 (file)
@@ -221,6 +221,11 @@ struct page {
 #endif
 } _struct_page_alignment;
 
+static inline atomic_t *compound_mapcount_ptr(struct page *page)
+{
+       return &page[1].compound_mapcount;
+}
+
 /*
  * Used for sizing the vmemmap region on some architectures
  */
index 9eda1c31d1f77956ac3fc382be25ac44906e83bc..c20f190b4c189615c4eebaa84da6b89c1077f223 100644 (file)
@@ -925,6 +925,7 @@ struct dev_ifalias {
 struct devlink;
 struct tlsdev_ops;
 
+
 /*
  * This structure defines the management hooks for network devices.
  * The following hooks can be defined; unless noted otherwise, they are
@@ -1421,7 +1422,6 @@ struct net_device_ops {
        void                    (*ndo_dfwd_del_station)(struct net_device *pdev,
                                                        void *priv);
 
-       int                     (*ndo_get_lock_subclass)(struct net_device *dev);
        int                     (*ndo_set_tx_maxrate)(struct net_device *dev,
                                                      int queue_index,
                                                      u32 maxrate);
@@ -1649,6 +1649,8 @@ enum netdev_priv_flags {
  *     @perm_addr:             Permanent hw address
  *     @addr_assign_type:      Hw address assignment type
  *     @addr_len:              Hardware address length
+ *     @upper_level:           Maximum depth level of upper devices.
+ *     @lower_level:           Maximum depth level of lower devices.
  *     @neigh_priv_len:        Used in neigh_alloc()
  *     @dev_id:                Used to differentiate devices that share
  *                             the same link layer address
@@ -1758,9 +1760,13 @@ enum netdev_priv_flags {
  *     @phydev:        Physical device may attach itself
  *                     for hardware timestamping
  *     @sfp_bus:       attached &struct sfp_bus structure.
- *
- *     @qdisc_tx_busylock: lockdep class annotating Qdisc->busylock spinlock
- *     @qdisc_running_key: lockdep class annotating Qdisc->running seqcount
+ *     @qdisc_tx_busylock_key: lockdep class annotating Qdisc->busylock
+                               spinlock
+ *     @qdisc_running_key:     lockdep class annotating Qdisc->running seqcount
+ *     @qdisc_xmit_lock_key:   lockdep class annotating
+ *                             netdev_queue->_xmit_lock spinlock
+ *     @addr_list_lock_key:    lockdep class annotating
+ *                             net_device->addr_list_lock spinlock
  *
  *     @proto_down:    protocol port state information can be sent to the
  *                     switch driver and used to set the phys state of the
@@ -1875,6 +1881,8 @@ struct net_device {
        unsigned char           perm_addr[MAX_ADDR_LEN];
        unsigned char           addr_assign_type;
        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;
@@ -2045,8 +2053,10 @@ struct net_device {
 #endif
        struct phy_device       *phydev;
        struct sfp_bus          *sfp_bus;
-       struct lock_class_key   *qdisc_tx_busylock;
-       struct lock_class_key   *qdisc_running_key;
+       struct lock_class_key   qdisc_tx_busylock_key;
+       struct lock_class_key   qdisc_running_key;
+       struct lock_class_key   qdisc_xmit_lock_key;
+       struct lock_class_key   addr_list_lock_key;
        bool                    proto_down;
        unsigned                wol_enabled:1;
 };
@@ -2124,23 +2134,6 @@ static inline void netdev_for_each_tx_queue(struct net_device *dev,
                f(dev, &dev->_tx[i], arg);
 }
 
-#define netdev_lockdep_set_classes(dev)                                \
-{                                                              \
-       static struct lock_class_key qdisc_tx_busylock_key;     \
-       static struct lock_class_key qdisc_running_key;         \
-       static struct lock_class_key qdisc_xmit_lock_key;       \
-       static struct lock_class_key dev_addr_list_lock_key;    \
-       unsigned int i;                                         \
-                                                               \
-       (dev)->qdisc_tx_busylock = &qdisc_tx_busylock_key;      \
-       (dev)->qdisc_running_key = &qdisc_running_key;          \
-       lockdep_set_class(&(dev)->addr_list_lock,               \
-                         &dev_addr_list_lock_key);             \
-       for (i = 0; i < (dev)->num_tx_queues; i++)              \
-               lockdep_set_class(&(dev)->_tx[i]._xmit_lock,    \
-                                 &qdisc_xmit_lock_key);        \
-}
-
 u16 netdev_pick_tx(struct net_device *dev, struct sk_buff *skb,
                     struct net_device *sb_dev);
 struct netdev_queue *netdev_core_pick_tx(struct net_device *dev,
@@ -3139,6 +3132,7 @@ static inline void netif_stop_queue(struct net_device *dev)
 }
 
 void netif_tx_stop_all_queues(struct net_device *dev);
+void netdev_update_lockdep_key(struct net_device *dev);
 
 static inline bool netif_tx_queue_stopped(const struct netdev_queue *dev_queue)
 {
@@ -4056,16 +4050,6 @@ static inline void netif_addr_lock(struct net_device *dev)
        spin_lock(&dev->addr_list_lock);
 }
 
-static inline void netif_addr_lock_nested(struct net_device *dev)
-{
-       int subclass = SINGLE_DEPTH_NESTING;
-
-       if (dev->netdev_ops->ndo_get_lock_subclass)
-               subclass = dev->netdev_ops->ndo_get_lock_subclass(dev);
-
-       spin_lock_nested(&dev->addr_list_lock, subclass);
-}
-
 static inline void netif_addr_lock_bh(struct net_device *dev)
 {
        spin_lock_bh(&dev->addr_list_lock);
@@ -4329,6 +4313,16 @@ int netdev_master_upper_dev_link(struct net_device *dev,
                                 struct netlink_ext_ack *extack);
 void netdev_upper_dev_unlink(struct net_device *dev,
                             struct net_device *upper_dev);
+int netdev_adjacent_change_prepare(struct net_device *old_dev,
+                                  struct net_device *new_dev,
+                                  struct net_device *dev,
+                                  struct netlink_ext_ack *extack);
+void netdev_adjacent_change_commit(struct net_device *old_dev,
+                                  struct net_device *new_dev,
+                                  struct net_device *dev);
+void netdev_adjacent_change_abort(struct net_device *old_dev,
+                                 struct net_device *new_dev,
+                                 struct net_device *dev);
 void netdev_adjacent_rename_links(struct net_device *dev, char *oldname);
 void *netdev_lower_dev_get_private(struct net_device *dev,
                                   struct net_device *lower_dev);
@@ -4340,7 +4334,6 @@ void netdev_lower_state_changed(struct net_device *lower_dev,
 extern u8 netdev_rss_key[NETDEV_RSS_KEY_LEN] __read_mostly;
 void netdev_rss_key_fill(void *buffer, size_t len);
 
-int dev_get_nest_level(struct net_device *dev);
 int skb_checksum_help(struct sk_buff *skb);
 int skb_crc32c_csum_help(struct sk_buff *skb);
 int skb_csum_hwoffload_help(struct sk_buff *skb,
index f91cb8898ff0af60d751f7c026c7b9f852fe620b..1bf83c8fcaa77e31cd3acd8e2f16c54e6ea05bf5 100644 (file)
@@ -622,12 +622,28 @@ static inline int PageTransCompound(struct page *page)
  *
  * Unlike PageTransCompound, this is safe to be called only while
  * split_huge_pmd() cannot run from under us, like if protected by the
- * MMU notifier, otherwise it may result in page->_mapcount < 0 false
+ * MMU notifier, otherwise it may result in page->_mapcount check false
  * positives.
+ *
+ * We have to treat page cache THP differently since every subpage of it
+ * would get _mapcount inc'ed once it is PMD mapped.  But, it may be PTE
+ * mapped in the current process so comparing subpage's _mapcount to
+ * compound_mapcount to filter out PTE mapped case.
  */
 static inline int PageTransCompoundMap(struct page *page)
 {
-       return PageTransCompound(page) && atomic_read(&page->_mapcount) < 0;
+       struct page *head;
+
+       if (!PageTransCompound(page))
+               return 0;
+
+       if (PageAnon(page))
+               return atomic_read(&page->_mapcount) < 0;
+
+       head = compound_head(page);
+       /* File THP is PMD mapped and not PTE mapped */
+       return atomic_read(&page->_mapcount) ==
+              atomic_read(compound_mapcount_ptr(head));
 }
 
 /*
index 61448c19a132c29c92238e782330401ddf0fba17..68ccc5b1913b485ba940dc6fa283a6ec7c0a381d 100644 (file)
@@ -292,7 +292,7 @@ struct pmu {
         *  -EBUSY      -- @event is for this PMU but PMU temporarily unavailable
         *  -EINVAL     -- @event is for this PMU but @event is not valid
         *  -EOPNOTSUPP -- @event is for this PMU, @event is valid, but not supported
-        *  -EACCESS    -- @event is for this PMU, @event is valid, but no privilidges
+        *  -EACCES     -- @event is for this PMU, @event is valid, but no privileges
         *
         *  0           -- @event is for this PMU and valid
         *
index 6eaa53cef0bd228b8a0d7bb2b3938ff04c548f95..30e676b36b247a595c39e98d7c59bdaa7e6eb233 100644 (file)
@@ -51,7 +51,10 @@ struct sdma_script_start_addrs {
        /* End of v2 array */
        s32 zcanfd_2_mcu_addr;
        s32 zqspi_2_mcu_addr;
+       s32 mcu_2_ecspi_addr;
        /* End of v3 array */
+       s32 mcu_2_zqspi_addr;
+       /* End of v4 array */
 };
 
 /**
index 222c3e01397c17674ea6811aaefc330c3a3077a1..ebf5ef17cc2ae3f45a1ff5379c387e2d0bc9a089 100644 (file)
@@ -34,8 +34,6 @@ enum pm_qos_flags_status {
 #define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT    PM_QOS_LATENCY_ANY
 #define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS PM_QOS_LATENCY_ANY_NS
 #define PM_QOS_LATENCY_TOLERANCE_DEFAULT_VALUE 0
-#define PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE     0
-#define PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE     (-1)
 #define PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT (-1)
 
 #define PM_QOS_FLAG_NO_POWER_OFF       (1 << 0)
@@ -54,8 +52,6 @@ struct pm_qos_flags_request {
 enum dev_pm_qos_req_type {
        DEV_PM_QOS_RESUME_LATENCY = 1,
        DEV_PM_QOS_LATENCY_TOLERANCE,
-       DEV_PM_QOS_MIN_FREQUENCY,
-       DEV_PM_QOS_MAX_FREQUENCY,
        DEV_PM_QOS_FLAGS,
 };
 
@@ -97,14 +93,10 @@ struct pm_qos_flags {
 struct dev_pm_qos {
        struct pm_qos_constraints resume_latency;
        struct pm_qos_constraints latency_tolerance;
-       struct pm_qos_constraints min_frequency;
-       struct pm_qos_constraints max_frequency;
        struct pm_qos_flags flags;
        struct dev_pm_qos_request *resume_latency_req;
        struct dev_pm_qos_request *latency_tolerance_req;
        struct dev_pm_qos_request *flags_req;
-       struct dev_pm_qos_request *min_frequency_req;
-       struct dev_pm_qos_request *max_frequency_req;
 };
 
 /* Action requested to pm_qos_update_target */
@@ -199,10 +191,6 @@ static inline s32 dev_pm_qos_read_value(struct device *dev,
        switch (type) {
        case DEV_PM_QOS_RESUME_LATENCY:
                return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT;
-       case DEV_PM_QOS_MIN_FREQUENCY:
-               return PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE;
-       case DEV_PM_QOS_MAX_FREQUENCY:
-               return PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE;
        default:
                WARN_ON(1);
                return 0;
@@ -267,4 +255,48 @@ static inline s32 dev_pm_qos_raw_resume_latency(struct device *dev)
 }
 #endif
 
+#define FREQ_QOS_MIN_DEFAULT_VALUE     0
+#define FREQ_QOS_MAX_DEFAULT_VALUE     (-1)
+
+enum freq_qos_req_type {
+       FREQ_QOS_MIN = 1,
+       FREQ_QOS_MAX,
+};
+
+struct freq_constraints {
+       struct pm_qos_constraints min_freq;
+       struct blocking_notifier_head min_freq_notifiers;
+       struct pm_qos_constraints max_freq;
+       struct blocking_notifier_head max_freq_notifiers;
+};
+
+struct freq_qos_request {
+       enum freq_qos_req_type type;
+       struct plist_node pnode;
+       struct freq_constraints *qos;
+};
+
+static inline int freq_qos_request_active(struct freq_qos_request *req)
+{
+       return !IS_ERR_OR_NULL(req->qos);
+}
+
+void freq_constraints_init(struct freq_constraints *qos);
+
+s32 freq_qos_read_value(struct freq_constraints *qos,
+                       enum freq_qos_req_type type);
+
+int freq_qos_add_request(struct freq_constraints *qos,
+                        struct freq_qos_request *req,
+                        enum freq_qos_req_type type, s32 value);
+int freq_qos_update_request(struct freq_qos_request *req, s32 new_value);
+int freq_qos_remove_request(struct freq_qos_request *req);
+
+int freq_qos_add_notifier(struct freq_constraints *qos,
+                         enum freq_qos_req_type type,
+                         struct notifier_block *notifier);
+int freq_qos_remove_notifier(struct freq_constraints *qos,
+                            enum freq_qos_req_type type,
+                            struct notifier_block *notifier);
+
 #endif
index b5116013f27ef981bc1d5fcac8dd34831b60e04c..63e62372443a501d33d42e6333419004ae614b6f 100644 (file)
@@ -315,24 +315,6 @@ radix_tree_iter_lookup(const struct radix_tree_root *root,
        return radix_tree_next_chunk(root, iter, RADIX_TREE_ITER_CONTIG);
 }
 
-/**
- * radix_tree_iter_find - find a present entry
- * @root: radix tree root
- * @iter: iterator state
- * @index: start location
- *
- * This function returns the slot containing the entry with the lowest index
- * which is at least @index.  If @index is larger than any present entry, this
- * function returns NULL.  The @iter is updated to describe the entry found.
- */
-static inline void __rcu **
-radix_tree_iter_find(const struct radix_tree_root *root,
-                       struct radix_tree_iter *iter, unsigned long index)
-{
-       radix_tree_iter_init(iter, index);
-       return radix_tree_next_chunk(root, iter, 0);
-}
-
 /**
  * radix_tree_iter_retry - retry this chunk of the iteration
  * @iter:      iterator state
index 9326d671b6e6c1f038890954c557def61c567e2d..eaae6b4e9f24baa9aa873332e482206293bbc562 100644 (file)
@@ -7,7 +7,7 @@
 struct reset_controller_dev;
 
 /**
- * struct reset_control_ops
+ * struct reset_control_ops - reset controller driver callbacks
  *
  * @reset: for self-deasserting resets, does all necessary
  *         things to reset the device
@@ -33,7 +33,7 @@ struct of_phandle_args;
  * @provider: name of the reset controller device controlling this reset line
  * @index: ID of the reset controller in the reset controller device
  * @dev_id: name of the device associated with this reset line
- * @con_id name of the reset line (can be NULL)
+ * @con_id: name of the reset line (can be NULL)
  */
 struct reset_control_lookup {
        struct list_head list;
index e7793fc0fa932ee3e41d49756e75bf829a743452..eb597e8aa430bd485c0df9e2dd71cb59babd6751 100644 (file)
@@ -143,7 +143,7 @@ static inline int device_reset_optional(struct device *dev)
  * If this function is called more than once for the same reset_control it will
  * return -EBUSY.
  *
- * See reset_control_get_shared for details on shared references to
+ * See reset_control_get_shared() for details on shared references to
  * reset-controls.
  *
  * Use of id names is optional.
index a8d59d612d274bdb5df8cbd13245b35fc2e08908..9df7547afc0cb783883b5c5c7b32b2956a650d7a 100644 (file)
@@ -105,6 +105,7 @@ enum lockdown_reason {
        LOCKDOWN_NONE,
        LOCKDOWN_MODULE_SIGNATURE,
        LOCKDOWN_DEV_MEM,
+       LOCKDOWN_EFI_TEST,
        LOCKDOWN_KEXEC,
        LOCKDOWN_HIBERNATION,
        LOCKDOWN_PCI_ACCESS,
index 7914fdaf4226694652da46becdac5747dca97687..64a395c7f6895ce4dc439571de2eec8673b393e4 100644 (file)
@@ -1354,7 +1354,8 @@ static inline __u32 skb_get_hash_flowi6(struct sk_buff *skb, const struct flowi6
        return skb->hash;
 }
 
-__u32 skb_get_hash_perturb(const struct sk_buff *skb, u32 perturb);
+__u32 skb_get_hash_perturb(const struct sk_buff *skb,
+                          const siphash_key_t *perturb);
 
 static inline __u32 skb_get_hash_raw(const struct sk_buff *skb)
 {
@@ -1494,6 +1495,19 @@ static inline int skb_queue_empty(const struct sk_buff_head *list)
        return list->next == (const struct sk_buff *) list;
 }
 
+/**
+ *     skb_queue_empty_lockless - check if a queue is empty
+ *     @list: queue head
+ *
+ *     Returns true if the queue is empty, false otherwise.
+ *     This variant can be used in lockless contexts.
+ */
+static inline bool skb_queue_empty_lockless(const struct sk_buff_head *list)
+{
+       return READ_ONCE(list->next) == (const struct sk_buff *) list;
+}
+
+
 /**
  *     skb_queue_is_last - check if skb is the last entry in the queue
  *     @list: queue head
@@ -1847,9 +1861,11 @@ static inline void __skb_insert(struct sk_buff *newsk,
                                struct sk_buff *prev, struct sk_buff *next,
                                struct sk_buff_head *list)
 {
-       newsk->next = next;
-       newsk->prev = prev;
-       next->prev  = prev->next = newsk;
+       /* see skb_queue_empty_lockless() for the opposite READ_ONCE() */
+       WRITE_ONCE(newsk->next, next);
+       WRITE_ONCE(newsk->prev, prev);
+       WRITE_ONCE(next->prev, newsk);
+       WRITE_ONCE(prev->next, newsk);
        list->qlen++;
 }
 
@@ -1860,11 +1876,11 @@ static inline void __skb_queue_splice(const struct sk_buff_head *list,
        struct sk_buff *first = list->next;
        struct sk_buff *last = list->prev;
 
-       first->prev = prev;
-       prev->next = first;
+       WRITE_ONCE(first->prev, prev);
+       WRITE_ONCE(prev->next, first);
 
-       last->next = next;
-       next->prev = last;
+       WRITE_ONCE(last->next, next);
+       WRITE_ONCE(next->prev, last);
 }
 
 /**
@@ -2005,8 +2021,8 @@ static inline void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list)
        next       = skb->next;
        prev       = skb->prev;
        skb->next  = skb->prev = NULL;
-       next->prev = prev;
-       prev->next = next;
+       WRITE_ONCE(next->prev, prev);
+       WRITE_ONCE(prev->next, next);
 }
 
 /**
index e4b3fb4bb77c7004d9164c6ba85f3be37eea741f..ce7055259877b7f42a80a55508700d3dec5833e7 100644 (file)
@@ -139,6 +139,11 @@ static inline void sk_msg_apply_bytes(struct sk_psock *psock, u32 bytes)
        }
 }
 
+static inline u32 sk_msg_iter_dist(u32 start, u32 end)
+{
+       return end >= start ? end - start : end + (MAX_MSG_FRAGS - start);
+}
+
 #define sk_msg_iter_var_prev(var)                      \
        do {                                            \
                if (var == 0)                           \
@@ -198,9 +203,7 @@ static inline u32 sk_msg_elem_used(const struct sk_msg *msg)
        if (sk_msg_full(msg))
                return MAX_MSG_FRAGS;
 
-       return msg->sg.end >= msg->sg.start ?
-               msg->sg.end - msg->sg.start :
-               msg->sg.end + (MAX_MSG_FRAGS - msg->sg.start);
+       return sk_msg_iter_dist(msg->sg.start, msg->sg.end);
 }
 
 static inline struct scatterlist *sk_msg_elem(struct sk_msg *msg, int which)
index fc0bed59fc84ef8e6631d3c275853d52a46f84aa..4049d9755cf198bdda600a61485b36a888b9d879 100644 (file)
@@ -263,7 +263,7 @@ struct ucred {
 #define PF_MAX         AF_MAX
 
 /* Maximum queue length specifiable by listen.  */
-#define SOMAXCONN      128
+#define SOMAXCONN      4096
 
 /* Flags we can use with send/ and recv.
    Added those for 1003.1g not all are supported yet
index 87d27e13d8859742044849854288a7f5bec76dfe..d796058cdff2a82b0c65450f988f29683513cea8 100644 (file)
@@ -64,6 +64,11 @@ static inline int xprt_setup_backchannel(struct rpc_xprt *xprt,
        return 0;
 }
 
+static inline void xprt_destroy_backchannel(struct rpc_xprt *xprt,
+                                           unsigned int max_reqs)
+{
+}
+
 static inline bool svc_is_backchannel(const struct svc_rqst *rqstp)
 {
        return false;
index 5420817ed317ebf3642758dd950d3994458eb977..fa7ee503fb76326d181d844aad22700bd85bf7fa 100644 (file)
@@ -196,9 +196,9 @@ struct bin_attribute {
        .size   = _size,                                                \
 }
 
-#define __BIN_ATTR_WO(_name) {                                         \
+#define __BIN_ATTR_WO(_name, _size) {                                  \
        .attr   = { .name = __stringify(_name), .mode = 0200 },         \
-       .store  = _name##_store,                                        \
+       .write  = _name##_write,                                        \
        .size   = _size,                                                \
 }
 
index 4c7781f4b29b6491204cb14cd7ce829a0f867588..07875ccc7bb50e9ec44a1886e4649aa27be1a2f8 100644 (file)
@@ -48,7 +48,6 @@ struct virtio_vsock_sock {
 
 struct virtio_vsock_pkt {
        struct virtio_vsock_hdr hdr;
-       struct work_struct work;
        struct list_head list;
        /* socket refcnt not held, only use for cancellation */
        struct vsock_sock *vsk;
index f7fe45689142150231a74247f35811ce4dd77600..3d56b026bb9e77fd484f306c1ac614ee0c905a33 100644 (file)
@@ -159,7 +159,6 @@ struct slave {
        unsigned long target_last_arp_rx[BOND_MAX_ARP_TARGETS];
        s8     link;            /* one of BOND_LINK_XXXX */
        s8     link_new_state;  /* one of BOND_LINK_XXXX */
-       s8     new_link;
        u8     backup:1,   /* indicates backup slave. Value corresponds with
                              BOND_STATE_ACTIVE and BOND_STATE_BACKUP */
               inactive:1, /* indicates inactive slave */
@@ -203,7 +202,6 @@ struct bonding {
        struct   slave __rcu *primary_slave;
        struct   bond_up_slave __rcu *slave_arr; /* Array of usable slaves */
        bool     force_primary;
-       u32      nest_level;
        s32      slave_cnt; /* never change this value outside the attach/detach wrappers */
        int     (*recv_probe)(const struct sk_buff *, struct bonding *,
                              struct slave *);
@@ -239,6 +237,7 @@ struct bonding {
        struct   dentry *debug_dir;
 #endif /* CONFIG_DEBUG_FS */
        struct rtnl_link_stats64 bond_stats;
+       struct lock_class_key stats_lock_key;
 };
 
 #define bond_slave_get_rcu(dev) \
@@ -549,7 +548,7 @@ static inline void bond_propose_link_state(struct slave *slave, int state)
 
 static inline void bond_commit_link_state(struct slave *slave, bool notify)
 {
-       if (slave->link == slave->link_new_state)
+       if (slave->link_new_state == BOND_LINK_NOCHANGE)
                return;
 
        slave->link = slave->link_new_state;
index 127a5c4e369914814c3004d2701ebb5ae026ca95..86e028388badc46977bf6c05bd8f718d852c14a8 100644 (file)
@@ -122,7 +122,7 @@ static inline void skb_mark_napi_id(struct sk_buff *skb,
 static inline void sk_mark_napi_id(struct sock *sk, const struct sk_buff *skb)
 {
 #ifdef CONFIG_NET_RX_BUSY_POLL
-       sk->sk_napi_id = skb->napi_id;
+       WRITE_ONCE(sk->sk_napi_id, skb->napi_id);
 #endif
        sk_rx_queue_set(sk, skb);
 }
@@ -132,8 +132,8 @@ static inline void sk_mark_napi_id_once(struct sock *sk,
                                        const struct sk_buff *skb)
 {
 #ifdef CONFIG_NET_RX_BUSY_POLL
-       if (!sk->sk_napi_id)
-               sk->sk_napi_id = skb->napi_id;
+       if (!READ_ONCE(sk->sk_napi_id))
+               WRITE_ONCE(sk->sk_napi_id, skb->napi_id);
 #endif
 }
 
index 90bd210be06075818a8ba3213006e16eb610c602..5cd12276ae21a52006debcd846c85be1b04bf596 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <linux/types.h>
 #include <linux/in6.h>
+#include <linux/siphash.h>
 #include <uapi/linux/if_ether.h>
 
 /**
@@ -276,7 +277,7 @@ struct flow_keys_basic {
 struct flow_keys {
        struct flow_dissector_key_control control;
 #define FLOW_KEYS_HASH_START_FIELD basic
-       struct flow_dissector_key_basic basic;
+       struct flow_dissector_key_basic basic __aligned(SIPHASH_ALIGNMENT);
        struct flow_dissector_key_tags tags;
        struct flow_dissector_key_vlan vlan;
        struct flow_dissector_key_vlan cvlan;
index d126b5d2026155aa7311ea82ce609122c6da45e0..2ad85e68304142fc3193e8a2c4dc1cfb4cca821a 100644 (file)
@@ -69,7 +69,7 @@ struct fq {
        struct list_head backlogs;
        spinlock_t lock;
        u32 flows_cnt;
-       u32 perturbation;
+       siphash_key_t   perturbation;
        u32 limit;
        u32 memory_limit;
        u32 memory_usage;
index be40a4b327e3d1d51f15f29b45216b39e7d1f42e..38a9a3d1222b7d5238a1de7f226562bf0e57425e 100644 (file)
@@ -108,7 +108,7 @@ begin:
 
 static u32 fq_flow_idx(struct fq *fq, struct sk_buff *skb)
 {
-       u32 hash = skb_get_hash_perturb(skb, fq->perturbation);
+       u32 hash = skb_get_hash_perturb(skb, &fq->perturbation);
 
        return reciprocal_scale(hash, fq->flows_cnt);
 }
@@ -308,12 +308,12 @@ static int fq_init(struct fq *fq, int flows_cnt)
        INIT_LIST_HEAD(&fq->backlogs);
        spin_lock_init(&fq->lock);
        fq->flows_cnt = max_t(u32, flows_cnt, 1);
-       fq->perturbation = prandom_u32();
+       get_random_bytes(&fq->perturbation, sizeof(fq->perturbation));
        fq->quantum = 300;
        fq->limit = 8192;
        fq->memory_limit = 16 << 20; /* 16 MBytes */
 
-       fq->flows = kcalloc(fq->flows_cnt, sizeof(fq->flows[0]), GFP_KERNEL);
+       fq->flows = kvcalloc(fq->flows_cnt, sizeof(fq->flows[0]), GFP_KERNEL);
        if (!fq->flows)
                return -ENOMEM;
 
@@ -331,7 +331,7 @@ static void fq_reset(struct fq *fq,
        for (i = 0; i < fq->flows_cnt; i++)
                fq_flow_reset(fq, &fq->flows[i], free_func);
 
-       kfree(fq->flows);
+       kvfree(fq->flows);
        fq->flows = NULL;
 }
 
index 81643cf8a1c43ea5d7a61aba0722fd2c37e55f2c..c81444611a228e51413fd162a67b2bec44400012 100644 (file)
@@ -21,9 +21,13 @@ void hwbm_buf_free(struct hwbm_pool *bm_pool, void *buf);
 int hwbm_pool_refill(struct hwbm_pool *bm_pool, gfp_t gfp);
 int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num);
 #else
-void hwbm_buf_free(struct hwbm_pool *bm_pool, void *buf) {}
-int hwbm_pool_refill(struct hwbm_pool *bm_pool, gfp_t gfp) { return 0; }
-int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num)
+static inline void hwbm_buf_free(struct hwbm_pool *bm_pool, void *buf) {}
+
+static inline int hwbm_pool_refill(struct hwbm_pool *bm_pool, gfp_t gfp)
+{ return 0; }
+
+static inline int hwbm_pool_add(struct hwbm_pool *bm_pool,
+                               unsigned int buf_num)
 { return 0; }
 #endif /* CONFIG_HWBM */
 #endif /* _HWBM_H */
index 95bb77f95bcc37404c143f7176117c72c2023d27..a2c61c36dc4afc2c2e334eeb2174f9e5636a106e 100644 (file)
@@ -185,7 +185,7 @@ static inline struct sk_buff *ip_fraglist_next(struct ip_fraglist_iter *iter)
 }
 
 struct ip_frag_state {
-       struct iphdr    *iph;
+       bool            DF;
        unsigned int    hlen;
        unsigned int    ll_rs;
        unsigned int    mtu;
@@ -196,7 +196,7 @@ struct ip_frag_state {
 };
 
 void ip_frag_init(struct sk_buff *skb, unsigned int hlen, unsigned int ll_rs,
-                 unsigned int mtu, struct ip_frag_state *state);
+                 unsigned int mtu, bool DF, struct ip_frag_state *state);
 struct sk_buff *ip_frag_next(struct sk_buff *skb,
                             struct ip_frag_state *state);
 
index 3759167f91f5643ea5a192eb7e82ce3a34e9e91b..078887c8c586ad3fba436261462118ad9c47cc81 100644 (file)
@@ -889,6 +889,7 @@ struct netns_ipvs {
        struct delayed_work     defense_work;   /* Work handler */
        int                     drop_rate;
        int                     drop_counter;
+       int                     old_secure_tcp;
        atomic_t                dropentry;
        /* locks in ctl.c */
        spinlock_t              dropentry_lock;  /* drop entry handling */
index 50a67bd6a43413bf69e2ad7b7c27e8460b6fb152..b8452cc0e059f5db44c0084b899c35b56833c5cf 100644 (file)
@@ -439,8 +439,8 @@ static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
 {
        unsigned long now = jiffies;
        
-       if (neigh->used != now)
-               neigh->used = now;
+       if (READ_ONCE(neigh->used) != now)
+               WRITE_ONCE(neigh->used, now);
        if (!(neigh->nud_state&(NUD_CONNECTED|NUD_DELAY|NUD_PROBE)))
                return __neigh_event_send(neigh, skb);
        return 0;
index 4c2cd937869964301117bea84aeefd8174d641fd..c7e15a213ef2fe547b8dfc4c8e1638bd2b5b499b 100644 (file)
@@ -342,7 +342,7 @@ static inline struct net *read_pnet(const possible_net_t *pnet)
 #define __net_initconst        __initconst
 #endif
 
-int peernet2id_alloc(struct net *net, struct net *peer);
+int peernet2id_alloc(struct net *net, struct net *peer, gfp_t gfp);
 int peernet2id(struct net *net, struct net *peer);
 bool peernet_has_id(struct net *net, struct net *peer);
 struct net *get_net_ns_by_id(struct net *net, int id);
index 001d294edf57d85bb3424c3e5fa8a6b8b683dfe7..2d0275f13bbfd57c47024fa822ecb4bdeb64b47d 100644 (file)
@@ -820,7 +820,8 @@ struct nft_expr_ops {
  */
 struct nft_expr {
        const struct nft_expr_ops       *ops;
-       unsigned char                   data[];
+       unsigned char                   data[]
+               __attribute__((aligned(__alignof__(u64))));
 };
 
 static inline void *nft_expr_priv(const struct nft_expr *expr)
index 637548d54b3ee9bdb0edd10a1667e81a40a6ef74..d80acda231ae276aba065458e598f04ca1eaee33 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/mutex.h>
 #include <linux/rwsem.h>
 #include <linux/atomic.h>
+#include <linux/hashtable.h>
 #include <net/gen_stats.h>
 #include <net/rtnetlink.h>
 #include <net/flow_offload.h>
@@ -362,6 +363,7 @@ struct tcf_proto {
        bool                    deleting;
        refcount_t              refcnt;
        struct rcu_head         rcu;
+       struct hlist_node       destroy_ht_node;
 };
 
 struct qdisc_skb_cb {
@@ -414,6 +416,8 @@ struct tcf_block {
                struct list_head filter_chain_list;
        } chain0;
        struct rcu_head rcu;
+       DECLARE_HASHTABLE(proto_destroy_ht, 7);
+       struct mutex proto_destroy_lock; /* Lock for proto_destroy hashtable. */
 };
 
 #ifdef CONFIG_PROVE_LOCKING
index f69b58bff7e5c69537444d99d68db5afc3abfa27..718e62fbe869db3ee7e8994bd1bfd559ab9c61c7 100644 (file)
@@ -954,8 +954,8 @@ static inline void sk_incoming_cpu_update(struct sock *sk)
 {
        int cpu = raw_smp_processor_id();
 
-       if (unlikely(sk->sk_incoming_cpu != cpu))
-               sk->sk_incoming_cpu = cpu;
+       if (unlikely(READ_ONCE(sk->sk_incoming_cpu) != cpu))
+               WRITE_ONCE(sk->sk_incoming_cpu, cpu);
 }
 
 static inline void sock_rps_record_flow_hash(__u32 hash)
@@ -2242,12 +2242,17 @@ struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp,
  * sk_page_frag - return an appropriate page_frag
  * @sk: socket
  *
- * If socket allocation mode allows current thread to sleep, it means its
- * safe to use the per task page_frag instead of the per socket one.
+ * Use the per task page_frag instead of the per socket one for
+ * optimization when we know that we're in the normal context and owns
+ * everything that's associated with %current.
+ *
+ * gfpflags_allow_blocking() isn't enough here as direct reclaim may nest
+ * inside other socket operations and end up recursing into sk_page_frag()
+ * while it's already in use.
  */
 static inline struct page_frag *sk_page_frag(struct sock *sk)
 {
-       if (gfpflags_allow_blocking(sk->sk_allocation))
+       if (gfpflags_normal_context(sk->sk_allocation))
                return &current->task_frag;
 
        return &sk->sk_frag;
@@ -2337,7 +2342,7 @@ static inline ktime_t sock_read_timestamp(struct sock *sk)
 
        return kt;
 #else
-       return sk->sk_stamp;
+       return READ_ONCE(sk->sk_stamp);
 #endif
 }
 
@@ -2348,7 +2353,7 @@ static inline void sock_write_timestamp(struct sock *sk, ktime_t kt)
        sk->sk_stamp = kt;
        write_sequnlock(&sk->sk_stamp_seq);
 #else
-       sk->sk_stamp = kt;
+       WRITE_ONCE(sk->sk_stamp, kt);
 #endif
 }
 
index c664e6dba0d177a80e90f4e543f55c610ddf3cf2..794e297483eabb5e0528ead88ed73b0b0a1ed9d4 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/socket.h>
 #include <linux/tcp.h>
 #include <linux/skmsg.h>
+#include <linux/mutex.h>
 #include <linux/netdevice.h>
 #include <linux/rcupdate.h>
 
@@ -269,6 +270,10 @@ struct tls_context {
 
        bool in_tcp_sendpages;
        bool pending_open_record_frags;
+
+       struct mutex tx_lock; /* protects partially_sent_* fields and
+                              * per-type TX fields
+                              */
        unsigned long flags;
 
        /* cache cold stuff */
index 335283dbe9b3d9ec8528ba6c7f11db63600060b5..373aadcfea21d302b878392bcf851ea93a6c6702 100644 (file)
@@ -197,6 +197,7 @@ struct vxlan_rdst {
        u8                       offloaded:1;
        __be32                   remote_vni;
        u32                      remote_ifindex;
+       struct net_device        *remote_dev;
        struct list_head         list;
        struct rcu_head          rcu;
        struct dst_cache         dst_cache;
index 6a47ba85c54c1109f32db61d700d81a23790474e..e7e733add99f80f68bd7cd4fd545c7322528bf18 100644 (file)
@@ -366,7 +366,7 @@ struct ib_tm_caps {
 
 struct ib_cq_init_attr {
        unsigned int    cqe;
-       int             comp_vector;
+       u32             comp_vector;
        u32             flags;
 };
 
index 985a5f583de4c7f10cf161267cd554999dad4bf8..31f76b6abf712463d4355c529be55e1519ed6dc7 100644 (file)
@@ -135,9 +135,9 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv,
                               struct link_info *li);
 
 #ifdef DEBUG
-inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv,
-                                 char *name,
-                                 struct asoc_simple_dai *dai)
+static inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv,
+                                        char *name,
+                                        struct asoc_simple_dai *dai)
 {
        struct device *dev = simple_priv_to_dev(priv);
 
@@ -167,7 +167,7 @@ inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv,
                dev_dbg(dev, "%s clk %luHz\n", name, clk_get_rate(dai->clk));
 }
 
-inline void asoc_simple_debug_info(struct asoc_simple_priv *priv)
+static inline void asoc_simple_debug_info(struct asoc_simple_priv *priv)
 {
        struct snd_soc_card *card = simple_priv_to_card(priv);
        struct device *dev = simple_priv_to_dev(priv);
index 5df604de4f11937679c628c967de885cbbf7634f..75ae1899452b9b0272a1934a9f1634998f24ab1a 100644 (file)
@@ -1688,6 +1688,7 @@ TRACE_EVENT(qgroup_update_reserve,
                __entry->qgid           = qgroup->qgroupid;
                __entry->cur_reserved   = qgroup->rsv.values[type];
                __entry->diff           = diff;
+               __entry->type           = type;
        ),
 
        TP_printk_btrfs("qgid=%llu type=%s cur_reserved=%llu diff=%lld",
@@ -1710,6 +1711,7 @@ TRACE_EVENT(qgroup_meta_reserve,
        TP_fast_assign_btrfs(root->fs_info,
                __entry->refroot        = root->root_key.objectid;
                __entry->diff           = diff;
+               __entry->type           = type;
        ),
 
        TP_printk_btrfs("refroot=%llu(%s) type=%s diff=%lld",
@@ -1726,7 +1728,6 @@ TRACE_EVENT(qgroup_meta_convert,
        TP_STRUCT__entry_btrfs(
                __field(        u64,    refroot                 )
                __field(        s64,    diff                    )
-               __field(        int,    type                    )
        ),
 
        TP_fast_assign_btrfs(root->fs_info,
index 1e988fdeba34d81c100361ee6803cd7a2f5a0eb1..6a6d2c7655ff12de469a309c5079bf3de1072305 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* SPDX-License-Identifier: ((GPL-2.0-only WITH Linux-syscall-note) OR BSD-3-Clause) */
 /*
  * linux/can.h
  *
index 0fb328d931485fdf32587a3f3d2ddcd0ff6fc940..dd2b925b09ac0f6cb01a7b5e374637e9423bff4b 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* SPDX-License-Identifier: ((GPL-2.0-only WITH Linux-syscall-note) OR BSD-3-Clause) */
 /*
  * linux/can/bcm.h
  *
index bfc4b5d22a5e601107b887c0913d89d94a7ee664..34633283de641a804da0b6096c64d043c86ea0f1 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* SPDX-License-Identifier: ((GPL-2.0-only WITH Linux-syscall-note) OR BSD-3-Clause) */
 /*
  * linux/can/error.h
  *
index 3aea5388c8e4782d86f4e18d05671251596b54b4..c2190bbe21d8dfc2c144164c35dce07152391c26 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* SPDX-License-Identifier: ((GPL-2.0-only WITH Linux-syscall-note) OR BSD-3-Clause) */
 /*
  * linux/can/gw.h
  *
index c32325342d309ec10e81f0e08afa396d039220c4..df6e821075c107d4fd2ca1ec0f387d8ac3d8cf8e 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
 /*
  * j1939.h
  *
index 1bc70d3a4d394f5baa726075d6f8e0aeaeb4719d..6f598b73839e0851437811abf52ce73678797b70 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
 /*
  * linux/can/netlink.h
  *
index be3b36e7ff61743a07c901fbc23b557c9df530da..6a11d308eb5ca70842713ccbed660b1fdcf34a68 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* SPDX-License-Identifier: ((GPL-2.0-only WITH Linux-syscall-note) OR BSD-3-Clause) */
 /*
  * linux/can/raw.h
  *
index 066812d118a2cf8fc05807a79549bc78856e71c3..4fa9d8777a07b440cdd2a577bd000f9d40d44574 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
 #ifndef _UAPI_CAN_VXCAN_H
 #define _UAPI_CAN_VXCAN_H
 
index 802b0377a49e55b7ecacc523f10efb5622c6f5f6..373cada8981595269d8142fdc5d331ec2902aceb 100644 (file)
  *
  * Protocol changelog:
  *
+ * 7.1:
+ *  - add the following messages:
+ *      FUSE_SETATTR, FUSE_SYMLINK, FUSE_MKNOD, FUSE_MKDIR, FUSE_UNLINK,
+ *      FUSE_RMDIR, FUSE_RENAME, FUSE_LINK, FUSE_OPEN, FUSE_READ, FUSE_WRITE,
+ *      FUSE_RELEASE, FUSE_FSYNC, FUSE_FLUSH, FUSE_SETXATTR, FUSE_GETXATTR,
+ *      FUSE_LISTXATTR, FUSE_REMOVEXATTR, FUSE_OPENDIR, FUSE_READDIR,
+ *      FUSE_RELEASEDIR
+ *  - add padding to messages to accommodate 32-bit servers on 64-bit kernels
+ *
+ * 7.2:
+ *  - add FOPEN_DIRECT_IO and FOPEN_KEEP_CACHE flags
+ *  - add FUSE_FSYNCDIR message
+ *
+ * 7.3:
+ *  - add FUSE_ACCESS message
+ *  - add FUSE_CREATE message
+ *  - add filehandle to fuse_setattr_in
+ *
+ * 7.4:
+ *  - add frsize to fuse_kstatfs
+ *  - clean up request size limit checking
+ *
+ * 7.5:
+ *  - add flags and max_write to fuse_init_out
+ *
+ * 7.6:
+ *  - add max_readahead to fuse_init_in and fuse_init_out
+ *
+ * 7.7:
+ *  - add FUSE_INTERRUPT message
+ *  - add POSIX file lock support
+ *
+ * 7.8:
+ *  - add lock_owner and flags fields to fuse_release_in
+ *  - add FUSE_BMAP message
+ *  - add FUSE_DESTROY message
+ *
  * 7.9:
  *  - new fuse_getattr_in input argument of GETATTR
  *  - add lk_flags in fuse_lk_in
index e168dc59e9a0d6c4b8b79242848c7db0a0b93337..d99b5a772698037a9a9fd51a3711a69393a166ef 100644 (file)
@@ -63,6 +63,7 @@ struct nvme_passthru_cmd64 {
        __u32   cdw14;
        __u32   cdw15;
        __u32   timeout_ms;
+       __u32   rsvd2;
        __u64   result;
 };
 
index 99335e1f4a275b1dbc86219a6dee7701b18fd624..25b4fa00bad1f4ccc22f7dfe708a95807415b151 100644 (file)
  *               sent when the child exits.
  * @stack:       Specify the location of the stack for the
  *               child process.
+ *               Note, @stack is expected to point to the
+ *               lowest address. The stack direction will be
+ *               determined by the kernel and set up
+ *               appropriately based on @stack_size.
  * @stack_size:  The size of the stack for the child process.
  * @tls:         If CLONE_SETTLS is set, the tls descriptor
  *               is set to tls.
index ddd8addcdb5c14ae5638d1f6d5f999a0adf2ca12..a3eaf08e7dd3a843e697583e03e474aec7199ac1 100644 (file)
@@ -1311,12 +1311,12 @@ static bool sysctl_is_valid_access(int off, int size, enum bpf_access_type type,
                return false;
 
        switch (off) {
-       case offsetof(struct bpf_sysctl, write):
+       case bpf_ctx_range(struct bpf_sysctl, write):
                if (type != BPF_READ)
                        return false;
                bpf_ctx_record_field_size(info, size_default);
                return bpf_ctx_narrow_access_ok(off, size, size_default);
-       case offsetof(struct bpf_sysctl, file_pos):
+       case bpf_ctx_range(struct bpf_sysctl, file_pos):
                if (type == BPF_READ) {
                        bpf_ctx_record_field_size(info, size_default);
                        return bpf_ctx_narrow_access_ok(off, size, size_default);
index 66088a9e9b9e220b9b823999d4cc9b022e203c5f..ef0e1e3e66f4a50308819a332812fa5e88488afe 100644 (file)
@@ -502,7 +502,7 @@ int bpf_remove_insns(struct bpf_prog *prog, u32 off, u32 cnt)
        return WARN_ON_ONCE(bpf_adj_branches(prog, off, off + cnt, off, false));
 }
 
-void bpf_prog_kallsyms_del_subprogs(struct bpf_prog *fp)
+static void bpf_prog_kallsyms_del_subprogs(struct bpf_prog *fp)
 {
        int i;
 
index d27f3b60ff6d30a753b7b92b9126629eaab2bf4d..3867864cdc2fbb833cd063f2ee05f754a376b0a6 100644 (file)
@@ -128,7 +128,7 @@ static int dev_map_init_map(struct bpf_dtab *dtab, union bpf_attr *attr)
 
                if (!dtab->n_buckets) /* Overflow check */
                        return -EINVAL;
-               cost += sizeof(struct hlist_head) * dtab->n_buckets;
+               cost += (u64) sizeof(struct hlist_head) * dtab->n_buckets;
        }
 
        /* if map size is larger than memlock limit, reject it */
@@ -719,6 +719,32 @@ const struct bpf_map_ops dev_map_hash_ops = {
        .map_check_btf = map_check_no_btf,
 };
 
+static void dev_map_hash_remove_netdev(struct bpf_dtab *dtab,
+                                      struct net_device *netdev)
+{
+       unsigned long flags;
+       u32 i;
+
+       spin_lock_irqsave(&dtab->index_lock, flags);
+       for (i = 0; i < dtab->n_buckets; i++) {
+               struct bpf_dtab_netdev *dev;
+               struct hlist_head *head;
+               struct hlist_node *next;
+
+               head = dev_map_index_hash(dtab, i);
+
+               hlist_for_each_entry_safe(dev, next, head, index_hlist) {
+                       if (netdev != dev->dev)
+                               continue;
+
+                       dtab->items--;
+                       hlist_del_rcu(&dev->index_hlist);
+                       call_rcu(&dev->rcu, __dev_map_entry_free);
+               }
+       }
+       spin_unlock_irqrestore(&dtab->index_lock, flags);
+}
+
 static int dev_map_notification(struct notifier_block *notifier,
                                ulong event, void *ptr)
 {
@@ -735,6 +761,11 @@ static int dev_map_notification(struct notifier_block *notifier,
                 */
                rcu_read_lock();
                list_for_each_entry_rcu(dtab, &dev_map_list, list) {
+                       if (dtab->map.map_type == BPF_MAP_TYPE_DEVMAP_HASH) {
+                               dev_map_hash_remove_netdev(dtab, netdev);
+                               continue;
+                       }
+
                        for (i = 0; i < dtab->map.max_entries; i++) {
                                struct bpf_dtab_netdev *dev, *odev;
 
index 82eabd4e38adda6e95f8113d9a7f9bb61b45ab00..ace1cfaa24b6b7d3490e422fb87528f6c1339beb 100644 (file)
@@ -126,7 +126,7 @@ static struct bpf_map *find_and_alloc_map(union bpf_attr *attr)
        return map;
 }
 
-void *bpf_map_area_alloc(size_t size, int numa_node)
+void *bpf_map_area_alloc(u64 size, int numa_node)
 {
        /* We really just want to fail instead of triggering OOM killer
         * under memory pressure, therefore we set __GFP_NORETRY to kmalloc,
@@ -141,6 +141,9 @@ void *bpf_map_area_alloc(size_t size, int numa_node)
        const gfp_t flags = __GFP_NOWARN | __GFP_ZERO;
        void *area;
 
+       if (size >= SIZE_MAX)
+               return NULL;
+
        if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) {
                area = kmalloc_node(size, GFP_USER | __GFP_NORETRY | flags,
                                    numa_node);
@@ -197,7 +200,7 @@ static void bpf_uncharge_memlock(struct user_struct *user, u32 pages)
                atomic_long_sub(pages, &user->locked_vm);
 }
 
-int bpf_map_charge_init(struct bpf_map_memory *mem, size_t size)
+int bpf_map_charge_init(struct bpf_map_memory *mem, u64 size)
 {
        u32 pages = round_up(size, PAGE_SIZE) >> PAGE_SHIFT;
        struct user_struct *user;
@@ -1326,24 +1329,32 @@ static void __bpf_prog_put_rcu(struct rcu_head *rcu)
 {
        struct bpf_prog_aux *aux = container_of(rcu, struct bpf_prog_aux, rcu);
 
+       kvfree(aux->func_info);
        free_used_maps(aux);
        bpf_prog_uncharge_memlock(aux->prog);
        security_bpf_prog_free(aux);
        bpf_prog_free(aux->prog);
 }
 
+static void __bpf_prog_put_noref(struct bpf_prog *prog, bool deferred)
+{
+       bpf_prog_kallsyms_del_all(prog);
+       btf_put(prog->aux->btf);
+       bpf_prog_free_linfo(prog);
+
+       if (deferred)
+               call_rcu(&prog->aux->rcu, __bpf_prog_put_rcu);
+       else
+               __bpf_prog_put_rcu(&prog->aux->rcu);
+}
+
 static void __bpf_prog_put(struct bpf_prog *prog, bool do_idr_lock)
 {
        if (atomic_dec_and_test(&prog->aux->refcnt)) {
                perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_UNLOAD, 0);
                /* bpf_prog_free_id() must be called first */
                bpf_prog_free_id(prog, do_idr_lock);
-               bpf_prog_kallsyms_del_all(prog);
-               btf_put(prog->aux->btf);
-               kvfree(prog->aux->func_info);
-               bpf_prog_free_linfo(prog);
-
-               call_rcu(&prog->aux->rcu, __bpf_prog_put_rcu);
+               __bpf_prog_put_noref(prog, true);
        }
 }
 
@@ -1741,11 +1752,12 @@ static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr)
        return err;
 
 free_used_maps:
-       bpf_prog_free_linfo(prog);
-       kvfree(prog->aux->func_info);
-       btf_put(prog->aux->btf);
-       bpf_prog_kallsyms_del_subprogs(prog);
-       free_used_maps(prog->aux);
+       /* In case we have subprogs, we need to wait for a grace
+        * period before we can tear down JIT memory since symbols
+        * are already exposed under kallsyms.
+        */
+       __bpf_prog_put_noref(prog, prog->aux->func_cnt);
+       return err;
 free_prog:
        bpf_prog_uncharge_memlock(prog);
 free_prog_sec:
index c52bc91f882b29e44ea8eb56fd0ba9889c6a86df..c87ee6412b36aa8f088844c42abc2b8aa70d2749 100644 (file)
@@ -798,7 +798,8 @@ static int generate_sched_domains(cpumask_var_t **domains,
                    cpumask_subset(cp->cpus_allowed, top_cpuset.effective_cpus))
                        continue;
 
-               if (is_sched_load_balance(cp))
+               if (is_sched_load_balance(cp) &&
+                   !cpumask_empty(cp->effective_cpus))
                        csa[csn++] = cp;
 
                /* skip @cp's subtree if not a partition root */
index 9ec0b0bfddbd69e25f6d5ed412b762aab2b9f528..aec8dba2bea40652c9a5128a8fc8956f7a27f30c 100644 (file)
@@ -5607,8 +5607,10 @@ static void perf_mmap_close(struct vm_area_struct *vma)
                perf_pmu_output_stop(event);
 
                /* now it's safe to free the pages */
-               atomic_long_sub(rb->aux_nr_pages, &mmap_user->locked_vm);
-               atomic64_sub(rb->aux_mmap_locked, &vma->vm_mm->pinned_vm);
+               if (!rb->aux_mmap_locked)
+                       atomic_long_sub(rb->aux_nr_pages, &mmap_user->locked_vm);
+               else
+                       atomic64_sub(rb->aux_mmap_locked, &vma->vm_mm->pinned_vm);
 
                /* this has to be the last one */
                rb_free_aux(rb);
@@ -6947,7 +6949,7 @@ static void __perf_event_output_stop(struct perf_event *event, void *data)
 static int __perf_pmu_output_stop(void *info)
 {
        struct perf_event *event = info;
-       struct pmu *pmu = event->pmu;
+       struct pmu *pmu = event->ctx->pmu;
        struct perf_cpu_context *cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
        struct remote_output ro = {
                .rb     = event->rb,
@@ -10633,7 +10635,7 @@ static int perf_copy_attr(struct perf_event_attr __user *uattr,
 
        attr->size = size;
 
-       if (attr->__reserved_1)
+       if (attr->__reserved_1 || attr->__reserved_2)
                return -EINVAL;
 
        if (attr->sample_type & ~(PERF_SAMPLE_MAX-1))
index bcdf5312521036486b7613e7499d7174e62526c6..55af6931c6ec3f8b817836c7fc78d56638f7de8c 100644 (file)
@@ -2561,7 +2561,35 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
        return 0;
 }
 
-static bool clone3_args_valid(const struct kernel_clone_args *kargs)
+/**
+ * clone3_stack_valid - check and prepare stack
+ * @kargs: kernel clone args
+ *
+ * Verify that the stack arguments userspace gave us are sane.
+ * In addition, set the stack direction for userspace since it's easy for us to
+ * determine.
+ */
+static inline bool clone3_stack_valid(struct kernel_clone_args *kargs)
+{
+       if (kargs->stack == 0) {
+               if (kargs->stack_size > 0)
+                       return false;
+       } else {
+               if (kargs->stack_size == 0)
+                       return false;
+
+               if (!access_ok((void __user *)kargs->stack, kargs->stack_size))
+                       return false;
+
+#if !defined(CONFIG_STACK_GROWSUP) && !defined(CONFIG_IA64)
+               kargs->stack += kargs->stack_size;
+#endif
+       }
+
+       return true;
+}
+
+static bool clone3_args_valid(struct kernel_clone_args *kargs)
 {
        /*
         * All lower bits of the flag word are taken.
@@ -2581,6 +2609,9 @@ static bool clone3_args_valid(const struct kernel_clone_args *kargs)
            kargs->exit_signal)
                return false;
 
+       if (!clone3_stack_valid(kargs))
+               return false;
+
        return true;
 }
 
index 132672b74e4b6784ac9f3c21c004c0d71b628b63..dd822fd8a7d5b7d308b997eccbd9c58410091b69 100644 (file)
@@ -51,7 +51,7 @@ EXPORT_SYMBOL_GPL(irqchip_fwnode_ops);
  * @type:      Type of irqchip_fwnode. See linux/irqdomain.h
  * @name:      Optional user provided domain name
  * @id:                Optional user provided id if name != NULL
- * @data:      Optional user-provided data
+ * @pa:                Optional user-provided physical address
  *
  * Allocate a struct irqchip_fwid, and return a poiner to the embedded
  * fwnode_handle (or NULL on failure).
index 9568a2fe7c116155f6c6c2c4a3220cd58f78a32b..04e83fdfbe80c016d986adae9fe2fd36bc2ca8d7 100644 (file)
@@ -650,3 +650,243 @@ static int __init pm_qos_power_init(void)
 }
 
 late_initcall(pm_qos_power_init);
+
+/* Definitions related to the frequency QoS below. */
+
+/**
+ * freq_constraints_init - Initialize frequency QoS constraints.
+ * @qos: Frequency QoS constraints to initialize.
+ */
+void freq_constraints_init(struct freq_constraints *qos)
+{
+       struct pm_qos_constraints *c;
+
+       c = &qos->min_freq;
+       plist_head_init(&c->list);
+       c->target_value = FREQ_QOS_MIN_DEFAULT_VALUE;
+       c->default_value = FREQ_QOS_MIN_DEFAULT_VALUE;
+       c->no_constraint_value = FREQ_QOS_MIN_DEFAULT_VALUE;
+       c->type = PM_QOS_MAX;
+       c->notifiers = &qos->min_freq_notifiers;
+       BLOCKING_INIT_NOTIFIER_HEAD(c->notifiers);
+
+       c = &qos->max_freq;
+       plist_head_init(&c->list);
+       c->target_value = FREQ_QOS_MAX_DEFAULT_VALUE;
+       c->default_value = FREQ_QOS_MAX_DEFAULT_VALUE;
+       c->no_constraint_value = FREQ_QOS_MAX_DEFAULT_VALUE;
+       c->type = PM_QOS_MIN;
+       c->notifiers = &qos->max_freq_notifiers;
+       BLOCKING_INIT_NOTIFIER_HEAD(c->notifiers);
+}
+
+/**
+ * freq_qos_read_value - Get frequency QoS constraint for a given list.
+ * @qos: Constraints to evaluate.
+ * @type: QoS request type.
+ */
+s32 freq_qos_read_value(struct freq_constraints *qos,
+                       enum freq_qos_req_type type)
+{
+       s32 ret;
+
+       switch (type) {
+       case FREQ_QOS_MIN:
+               ret = IS_ERR_OR_NULL(qos) ?
+                       FREQ_QOS_MIN_DEFAULT_VALUE :
+                       pm_qos_read_value(&qos->min_freq);
+               break;
+       case FREQ_QOS_MAX:
+               ret = IS_ERR_OR_NULL(qos) ?
+                       FREQ_QOS_MAX_DEFAULT_VALUE :
+                       pm_qos_read_value(&qos->max_freq);
+               break;
+       default:
+               WARN_ON(1);
+               ret = 0;
+       }
+
+       return ret;
+}
+
+/**
+ * freq_qos_apply - Add/modify/remove frequency QoS request.
+ * @req: Constraint request to apply.
+ * @action: Action to perform (add/update/remove).
+ * @value: Value to assign to the QoS request.
+ */
+static int freq_qos_apply(struct freq_qos_request *req,
+                         enum pm_qos_req_action action, s32 value)
+{
+       int ret;
+
+       switch(req->type) {
+       case FREQ_QOS_MIN:
+               ret = pm_qos_update_target(&req->qos->min_freq, &req->pnode,
+                                          action, value);
+               break;
+       case FREQ_QOS_MAX:
+               ret = pm_qos_update_target(&req->qos->max_freq, &req->pnode,
+                                          action, value);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+/**
+ * freq_qos_add_request - Insert new frequency QoS request into a given list.
+ * @qos: Constraints to update.
+ * @req: Preallocated request object.
+ * @type: Request type.
+ * @value: Request value.
+ *
+ * Insert a new entry into the @qos list of requests, recompute the effective
+ * QoS constraint value for that list and initialize the @req object.  The
+ * caller needs to save that object for later use in updates and removal.
+ *
+ * Return 1 if the effective constraint value has changed, 0 if the effective
+ * constraint value has not changed, or a negative error code on failures.
+ */
+int freq_qos_add_request(struct freq_constraints *qos,
+                        struct freq_qos_request *req,
+                        enum freq_qos_req_type type, s32 value)
+{
+       int ret;
+
+       if (IS_ERR_OR_NULL(qos) || !req)
+               return -EINVAL;
+
+       if (WARN(freq_qos_request_active(req),
+                "%s() called for active request\n", __func__))
+               return -EINVAL;
+
+       req->qos = qos;
+       req->type = type;
+       ret = freq_qos_apply(req, PM_QOS_ADD_REQ, value);
+       if (ret < 0) {
+               req->qos = NULL;
+               req->type = 0;
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(freq_qos_add_request);
+
+/**
+ * freq_qos_update_request - Modify existing frequency QoS request.
+ * @req: Request to modify.
+ * @new_value: New request value.
+ *
+ * Update an existing frequency QoS request along with the effective constraint
+ * value for the list of requests it belongs to.
+ *
+ * Return 1 if the effective constraint value has changed, 0 if the effective
+ * constraint value has not changed, or a negative error code on failures.
+ */
+int freq_qos_update_request(struct freq_qos_request *req, s32 new_value)
+{
+       if (!req)
+               return -EINVAL;
+
+       if (WARN(!freq_qos_request_active(req),
+                "%s() called for unknown object\n", __func__))
+               return -EINVAL;
+
+       if (req->pnode.prio == new_value)
+               return 0;
+
+       return freq_qos_apply(req, PM_QOS_UPDATE_REQ, new_value);
+}
+EXPORT_SYMBOL_GPL(freq_qos_update_request);
+
+/**
+ * freq_qos_remove_request - Remove frequency QoS request from its list.
+ * @req: Request to remove.
+ *
+ * Remove the given frequency QoS request from the list of constraints it
+ * belongs to and recompute the effective constraint value for that list.
+ *
+ * Return 1 if the effective constraint value has changed, 0 if the effective
+ * constraint value has not changed, or a negative error code on failures.
+ */
+int freq_qos_remove_request(struct freq_qos_request *req)
+{
+       if (!req)
+               return -EINVAL;
+
+       if (WARN(!freq_qos_request_active(req),
+                "%s() called for unknown object\n", __func__))
+               return -EINVAL;
+
+       return freq_qos_apply(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
+}
+EXPORT_SYMBOL_GPL(freq_qos_remove_request);
+
+/**
+ * freq_qos_add_notifier - Add frequency QoS change notifier.
+ * @qos: List of requests to add the notifier to.
+ * @type: Request type.
+ * @notifier: Notifier block to add.
+ */
+int freq_qos_add_notifier(struct freq_constraints *qos,
+                         enum freq_qos_req_type type,
+                         struct notifier_block *notifier)
+{
+       int ret;
+
+       if (IS_ERR_OR_NULL(qos) || !notifier)
+               return -EINVAL;
+
+       switch (type) {
+       case FREQ_QOS_MIN:
+               ret = blocking_notifier_chain_register(qos->min_freq.notifiers,
+                                                      notifier);
+               break;
+       case FREQ_QOS_MAX:
+               ret = blocking_notifier_chain_register(qos->max_freq.notifiers,
+                                                      notifier);
+               break;
+       default:
+               WARN_ON(1);
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(freq_qos_add_notifier);
+
+/**
+ * freq_qos_remove_notifier - Remove frequency QoS change notifier.
+ * @qos: List of requests to remove the notifier from.
+ * @type: Request type.
+ * @notifier: Notifier block to remove.
+ */
+int freq_qos_remove_notifier(struct freq_constraints *qos,
+                            enum freq_qos_req_type type,
+                            struct notifier_block *notifier)
+{
+       int ret;
+
+       if (IS_ERR_OR_NULL(qos) || !notifier)
+               return -EINVAL;
+
+       switch (type) {
+       case FREQ_QOS_MIN:
+               ret = blocking_notifier_chain_unregister(qos->min_freq.notifiers,
+                                                        notifier);
+               break;
+       case FREQ_QOS_MAX:
+               ret = blocking_notifier_chain_unregister(qos->max_freq.notifiers,
+                                                        notifier);
+               break;
+       default:
+               WARN_ON(1);
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(freq_qos_remove_notifier);
index dd05a378631a866c2f499c56986e5de7a703e766..0f2eb3629070700fdc0911e0c0dd495a91ebf386 100644 (file)
@@ -1073,6 +1073,7 @@ uclamp_update_active(struct task_struct *p, enum uclamp_id clamp_id)
        task_rq_unlock(rq, p, &rf);
 }
 
+#ifdef CONFIG_UCLAMP_TASK_GROUP
 static inline void
 uclamp_update_active_tasks(struct cgroup_subsys_state *css,
                           unsigned int clamps)
@@ -1091,7 +1092,6 @@ uclamp_update_active_tasks(struct cgroup_subsys_state *css,
        css_task_iter_end(&it);
 }
 
-#ifdef CONFIG_UCLAMP_TASK_GROUP
 static void cpu_util_update_eff(struct cgroup_subsys_state *css);
 static void uclamp_update_root_tg(void)
 {
@@ -3929,13 +3929,22 @@ pick_next_task(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
        }
 
 restart:
+#ifdef CONFIG_SMP
        /*
-        * Ensure that we put DL/RT tasks before the pick loop, such that they
-        * can PULL higher prio tasks when we lower the RQ 'priority'.
+        * We must do the balancing pass before put_next_task(), such
+        * that when we release the rq->lock the task is in the same
+        * state as before we took rq->lock.
+        *
+        * We can terminate the balance pass as soon as we know there is
+        * a runnable task of @class priority or higher.
         */
-       prev->sched_class->put_prev_task(rq, prev, rf);
-       if (!rq->nr_running)
-               newidle_balance(rq, rf);
+       for_class_range(class, prev->sched_class, &idle_sched_class) {
+               if (class->balance(rq, prev, rf))
+                       break;
+       }
+#endif
+
+       put_prev_task(rq, prev);
 
        for_each_class(class) {
                p = class->pick_next_task(rq, NULL, NULL);
@@ -6201,7 +6210,7 @@ static struct task_struct *__pick_migrate_task(struct rq *rq)
        for_each_class(class) {
                next = class->pick_next_task(rq, NULL, NULL);
                if (next) {
-                       next->sched_class->put_prev_task(rq, next, NULL);
+                       next->sched_class->put_prev_task(rq, next);
                        return next;
                }
        }
index 2dc48720f18914a9f828f5cd653b751a045c4556..a8a08030a8f7482e53c0fcdb19a13feb17440c7b 100644 (file)
@@ -1691,6 +1691,22 @@ static void check_preempt_equal_dl(struct rq *rq, struct task_struct *p)
        resched_curr(rq);
 }
 
+static int balance_dl(struct rq *rq, struct task_struct *p, struct rq_flags *rf)
+{
+       if (!on_dl_rq(&p->dl) && need_pull_dl_task(rq, p)) {
+               /*
+                * This is OK, because current is on_cpu, which avoids it being
+                * picked for load-balance and preemption/IRQs are still
+                * disabled avoiding further scheduler activity on it and we've
+                * not yet started the picking loop.
+                */
+               rq_unpin_lock(rq, rf);
+               pull_dl_task(rq);
+               rq_repin_lock(rq, rf);
+       }
+
+       return sched_stop_runnable(rq) || sched_dl_runnable(rq);
+}
 #endif /* CONFIG_SMP */
 
 /*
@@ -1758,45 +1774,28 @@ static struct task_struct *
 pick_next_task_dl(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
 {
        struct sched_dl_entity *dl_se;
+       struct dl_rq *dl_rq = &rq->dl;
        struct task_struct *p;
-       struct dl_rq *dl_rq;
 
        WARN_ON_ONCE(prev || rf);
 
-       dl_rq = &rq->dl;
-
-       if (unlikely(!dl_rq->dl_nr_running))
+       if (!sched_dl_runnable(rq))
                return NULL;
 
        dl_se = pick_next_dl_entity(rq, dl_rq);
        BUG_ON(!dl_se);
-
        p = dl_task_of(dl_se);
-
        set_next_task_dl(rq, p);
-
        return p;
 }
 
-static void put_prev_task_dl(struct rq *rq, struct task_struct *p, struct rq_flags *rf)
+static void put_prev_task_dl(struct rq *rq, struct task_struct *p)
 {
        update_curr_dl(rq);
 
        update_dl_rq_load_avg(rq_clock_pelt(rq), rq, 1);
        if (on_dl_rq(&p->dl) && p->nr_cpus_allowed > 1)
                enqueue_pushable_dl_task(rq, p);
-
-       if (rf && !on_dl_rq(&p->dl) && need_pull_dl_task(rq, p)) {
-               /*
-                * This is OK, because current is on_cpu, which avoids it being
-                * picked for load-balance and preemption/IRQs are still
-                * disabled avoiding further scheduler activity on it and we've
-                * not yet started the picking loop.
-                */
-               rq_unpin_lock(rq, rf);
-               pull_dl_task(rq);
-               rq_repin_lock(rq, rf);
-       }
 }
 
 /*
@@ -2442,6 +2441,7 @@ const struct sched_class dl_sched_class = {
        .set_next_task          = set_next_task_dl,
 
 #ifdef CONFIG_SMP
+       .balance                = balance_dl,
        .select_task_rq         = select_task_rq_dl,
        .migrate_task_rq        = migrate_task_rq_dl,
        .set_cpus_allowed       = set_cpus_allowed_dl,
index 682a754ea3e1a867e7b1c0cb2c8dee0dfc5c1461..22a2fed29054f40261688c5b00e2c70436900983 100644 (file)
@@ -6570,6 +6570,15 @@ static void task_dead_fair(struct task_struct *p)
 {
        remove_entity_load_avg(&p->se);
 }
+
+static int
+balance_fair(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
+{
+       if (rq->nr_running)
+               return 1;
+
+       return newidle_balance(rq, rf) != 0;
+}
 #endif /* CONFIG_SMP */
 
 static unsigned long wakeup_gran(struct sched_entity *se)
@@ -6746,7 +6755,7 @@ pick_next_task_fair(struct rq *rq, struct task_struct *prev, struct rq_flags *rf
        int new_tasks;
 
 again:
-       if (!cfs_rq->nr_running)
+       if (!sched_fair_runnable(rq))
                goto idle;
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
@@ -6884,7 +6893,7 @@ idle:
 /*
  * Account for a descheduled task:
  */
-static void put_prev_task_fair(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
+static void put_prev_task_fair(struct rq *rq, struct task_struct *prev)
 {
        struct sched_entity *se = &prev->se;
        struct cfs_rq *cfs_rq;
@@ -10414,11 +10423,11 @@ const struct sched_class fair_sched_class = {
        .check_preempt_curr     = check_preempt_wakeup,
 
        .pick_next_task         = pick_next_task_fair,
-
        .put_prev_task          = put_prev_task_fair,
        .set_next_task          = set_next_task_fair,
 
 #ifdef CONFIG_SMP
+       .balance                = balance_fair,
        .select_task_rq         = select_task_rq_fair,
        .migrate_task_rq        = migrate_task_rq_fair,
 
index 8dad5aa600eacbff82480ef84eae684308e6da54..f65ef1e2f20413c604edef762dd05ada0ef60fa7 100644 (file)
@@ -365,6 +365,12 @@ select_task_rq_idle(struct task_struct *p, int cpu, int sd_flag, int flags)
 {
        return task_cpu(p); /* IDLE tasks as never migrated */
 }
+
+static int
+balance_idle(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
+{
+       return WARN_ON_ONCE(1);
+}
 #endif
 
 /*
@@ -375,7 +381,7 @@ static void check_preempt_curr_idle(struct rq *rq, struct task_struct *p, int fl
        resched_curr(rq);
 }
 
-static void put_prev_task_idle(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
+static void put_prev_task_idle(struct rq *rq, struct task_struct *prev)
 {
 }
 
@@ -460,6 +466,7 @@ const struct sched_class idle_sched_class = {
        .set_next_task          = set_next_task_idle,
 
 #ifdef CONFIG_SMP
+       .balance                = balance_idle,
        .select_task_rq         = select_task_rq_idle,
        .set_cpus_allowed       = set_cpus_allowed_common,
 #endif
index ebaa4e619684112cc6c19bc6ba69fe15c3f2b52a..9b8adc01be3da83e153a45713e4dc362412d277a 100644 (file)
@@ -1469,6 +1469,22 @@ static void check_preempt_equal_prio(struct rq *rq, struct task_struct *p)
        resched_curr(rq);
 }
 
+static int balance_rt(struct rq *rq, struct task_struct *p, struct rq_flags *rf)
+{
+       if (!on_rt_rq(&p->rt) && need_pull_rt_task(rq, p)) {
+               /*
+                * This is OK, because current is on_cpu, which avoids it being
+                * picked for load-balance and preemption/IRQs are still
+                * disabled avoiding further scheduler activity on it and we've
+                * not yet started the picking loop.
+                */
+               rq_unpin_lock(rq, rf);
+               pull_rt_task(rq);
+               rq_repin_lock(rq, rf);
+       }
+
+       return sched_stop_runnable(rq) || sched_dl_runnable(rq) || sched_rt_runnable(rq);
+}
 #endif /* CONFIG_SMP */
 
 /*
@@ -1552,21 +1568,18 @@ static struct task_struct *
 pick_next_task_rt(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
 {
        struct task_struct *p;
-       struct rt_rq *rt_rq = &rq->rt;
 
        WARN_ON_ONCE(prev || rf);
 
-       if (!rt_rq->rt_queued)
+       if (!sched_rt_runnable(rq))
                return NULL;
 
        p = _pick_next_task_rt(rq);
-
        set_next_task_rt(rq, p);
-
        return p;
 }
 
-static void put_prev_task_rt(struct rq *rq, struct task_struct *p, struct rq_flags *rf)
+static void put_prev_task_rt(struct rq *rq, struct task_struct *p)
 {
        update_curr_rt(rq);
 
@@ -1578,18 +1591,6 @@ static void put_prev_task_rt(struct rq *rq, struct task_struct *p, struct rq_fla
         */
        if (on_rt_rq(&p->rt) && p->nr_cpus_allowed > 1)
                enqueue_pushable_task(rq, p);
-
-       if (rf && !on_rt_rq(&p->rt) && need_pull_rt_task(rq, p)) {
-               /*
-                * This is OK, because current is on_cpu, which avoids it being
-                * picked for load-balance and preemption/IRQs are still
-                * disabled avoiding further scheduler activity on it and we've
-                * not yet started the picking loop.
-                */
-               rq_unpin_lock(rq, rf);
-               pull_rt_task(rq);
-               rq_repin_lock(rq, rf);
-       }
 }
 
 #ifdef CONFIG_SMP
@@ -2366,8 +2367,8 @@ const struct sched_class rt_sched_class = {
        .set_next_task          = set_next_task_rt,
 
 #ifdef CONFIG_SMP
+       .balance                = balance_rt,
        .select_task_rq         = select_task_rq_rt,
-
        .set_cpus_allowed       = set_cpus_allowed_common,
        .rq_online              = rq_online_rt,
        .rq_offline             = rq_offline_rt,
index 0db2c1b3361e03077d3971876f9dc06cf9bbb027..c8870c5bd7df2ef3194f56c42ad0c7c8d1dc044f 100644 (file)
@@ -1727,10 +1727,11 @@ struct sched_class {
        struct task_struct * (*pick_next_task)(struct rq *rq,
                                               struct task_struct *prev,
                                               struct rq_flags *rf);
-       void (*put_prev_task)(struct rq *rq, struct task_struct *p, struct rq_flags *rf);
+       void (*put_prev_task)(struct rq *rq, struct task_struct *p);
        void (*set_next_task)(struct rq *rq, struct task_struct *p);
 
 #ifdef CONFIG_SMP
+       int (*balance)(struct rq *rq, struct task_struct *prev, struct rq_flags *rf);
        int  (*select_task_rq)(struct task_struct *p, int task_cpu, int sd_flag, int flags);
        void (*migrate_task_rq)(struct task_struct *p, int new_cpu);
 
@@ -1773,7 +1774,7 @@ struct sched_class {
 static inline void put_prev_task(struct rq *rq, struct task_struct *prev)
 {
        WARN_ON_ONCE(rq->curr != prev);
-       prev->sched_class->put_prev_task(rq, prev, NULL);
+       prev->sched_class->put_prev_task(rq, prev);
 }
 
 static inline void set_next_task(struct rq *rq, struct task_struct *next)
@@ -1787,8 +1788,12 @@ static inline void set_next_task(struct rq *rq, struct task_struct *next)
 #else
 #define sched_class_highest (&dl_sched_class)
 #endif
+
+#define for_class_range(class, _from, _to) \
+       for (class = (_from); class != (_to); class = class->next)
+
 #define for_each_class(class) \
-   for (class = sched_class_highest; class; class = class->next)
+       for_class_range(class, sched_class_highest, NULL)
 
 extern const struct sched_class stop_sched_class;
 extern const struct sched_class dl_sched_class;
@@ -1796,6 +1801,25 @@ extern const struct sched_class rt_sched_class;
 extern const struct sched_class fair_sched_class;
 extern const struct sched_class idle_sched_class;
 
+static inline bool sched_stop_runnable(struct rq *rq)
+{
+       return rq->stop && task_on_rq_queued(rq->stop);
+}
+
+static inline bool sched_dl_runnable(struct rq *rq)
+{
+       return rq->dl.dl_nr_running > 0;
+}
+
+static inline bool sched_rt_runnable(struct rq *rq)
+{
+       return rq->rt.rt_queued > 0;
+}
+
+static inline bool sched_fair_runnable(struct rq *rq)
+{
+       return rq->cfs.nr_running > 0;
+}
 
 #ifdef CONFIG_SMP
 
index 7e1cee4e65b211ece98bd640bf691a29de329ed1..c0640739e05ee8f07318920cd3132ef18427f3bc 100644 (file)
@@ -15,6 +15,12 @@ select_task_rq_stop(struct task_struct *p, int cpu, int sd_flag, int flags)
 {
        return task_cpu(p); /* stop tasks as never migrate */
 }
+
+static int
+balance_stop(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
+{
+       return sched_stop_runnable(rq);
+}
 #endif /* CONFIG_SMP */
 
 static void
@@ -31,16 +37,13 @@ static void set_next_task_stop(struct rq *rq, struct task_struct *stop)
 static struct task_struct *
 pick_next_task_stop(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
 {
-       struct task_struct *stop = rq->stop;
-
        WARN_ON_ONCE(prev || rf);
 
-       if (!stop || !task_on_rq_queued(stop))
+       if (!sched_stop_runnable(rq))
                return NULL;
 
-       set_next_task_stop(rq, stop);
-
-       return stop;
+       set_next_task_stop(rq, rq->stop);
+       return rq->stop;
 }
 
 static void
@@ -60,7 +63,7 @@ static void yield_task_stop(struct rq *rq)
        BUG(); /* the stop task should never yield, its pointless. */
 }
 
-static void put_prev_task_stop(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
+static void put_prev_task_stop(struct rq *rq, struct task_struct *prev)
 {
        struct task_struct *curr = rq->curr;
        u64 delta_exec;
@@ -129,6 +132,7 @@ const struct sched_class stop_sched_class = {
        .set_next_task          = set_next_task_stop,
 
 #ifdef CONFIG_SMP
+       .balance                = balance_stop,
        .select_task_rq         = select_task_rq_stop,
        .set_cpus_allowed       = set_cpus_allowed_common,
 #endif
index b5667a273bf67e0718371a783b259ffb4c91cbc7..49b835f1305f8c1cfe659bb466a00c4b71767185 100644 (file)
@@ -1948,7 +1948,7 @@ next_level:
 static int
 build_sched_domains(const struct cpumask *cpu_map, struct sched_domain_attr *attr)
 {
-       enum s_alloc alloc_state;
+       enum s_alloc alloc_state = sa_none;
        struct sched_domain *sd;
        struct s_data d;
        struct rq *rq = NULL;
@@ -1956,6 +1956,9 @@ build_sched_domains(const struct cpumask *cpu_map, struct sched_domain_attr *att
        struct sched_domain_topology_level *tl_asym;
        bool has_asym = false;
 
+       if (WARN_ON(cpumask_empty(cpu_map)))
+               goto error;
+
        alloc_state = __visit_domain_allocation_hell(&d, cpu_map);
        if (alloc_state != sa_rootdomain)
                goto error;
@@ -2026,7 +2029,7 @@ build_sched_domains(const struct cpumask *cpu_map, struct sched_domain_attr *att
        rcu_read_unlock();
 
        if (has_asym)
-               static_branch_enable_cpuslocked(&sched_asym_cpucapacity);
+               static_branch_inc_cpuslocked(&sched_asym_cpucapacity);
 
        if (rq && sched_debug_enabled) {
                pr_info("root domain span: %*pbl (max cpu_capacity = %lu)\n",
@@ -2121,8 +2124,12 @@ int sched_init_domains(const struct cpumask *cpu_map)
  */
 static void detach_destroy_domains(const struct cpumask *cpu_map)
 {
+       unsigned int cpu = cpumask_any(cpu_map);
        int i;
 
+       if (rcu_access_pointer(per_cpu(sd_asym_cpucapacity, cpu)))
+               static_branch_dec_cpuslocked(&sched_asym_cpucapacity);
+
        rcu_read_lock();
        for_each_cpu(i, cpu_map)
                cpu_attach_domain(NULL, &def_root_domain, i);
index 6d1f68b7e528a3f48c97f0a1e5c1a572d8ed8e11..c9ea7eb2cb1a321e0896a9f49398c273968da52d 100644 (file)
@@ -141,7 +141,8 @@ unsigned int stack_trace_save_tsk(struct task_struct *tsk, unsigned long *store,
        struct stacktrace_cookie c = {
                .store  = store,
                .size   = size,
-               .skip   = skipnr + 1,
+               /* skip this function if they are tracing us */
+               .skip   = skipnr + !!(current == tsk),
        };
 
        if (!try_get_task_stack(tsk))
@@ -298,7 +299,8 @@ unsigned int stack_trace_save_tsk(struct task_struct *task,
        struct stack_trace trace = {
                .entries        = store,
                .max_entries    = size,
-               .skip           = skipnr + 1,
+               /* skip this function if they are tracing us */
+               .skip   = skipnr + !!(current == task),
        };
 
        save_stack_trace_tsk(task, &trace);
index 92a431981b1c46862da651201f3721140d76af09..42d512fcfda2e6de092831f97bfc75c85b0b6137 100644 (file)
@@ -266,7 +266,7 @@ static void update_gt_cputime(struct task_cputime_atomic *cputime_atomic,
 /**
  * thread_group_sample_cputime - Sample cputime for a given task
  * @tsk:       Task for which cputime needs to be started
- * @iimes:     Storage for time samples
+ * @samples:   Storage for time samples
  *
  * Called from sys_getitimer() to calculate the expiry time of an active
  * timer. That means group cputime accounting is already active. Called
@@ -1038,12 +1038,12 @@ unlock:
  * member of @pct->bases[CLK].nextevt. False otherwise
  */
 static inline bool
-task_cputimers_expired(const u64 *sample, struct posix_cputimers *pct)
+task_cputimers_expired(const u64 *samples, struct posix_cputimers *pct)
 {
        int i;
 
        for (i = 0; i < CPUCLOCK_MAX; i++) {
-               if (sample[i] >= pct->bases[i].nextevt)
+               if (samples[i] >= pct->bases[i].nextevt)
                        return true;
        }
        return false;
index 142b07619918b13db03d1c3a91437c1f96ff28bf..dbd69052eaa6666854b47562c278336a87a14d89 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/seqlock.h>
 #include <linux/bitops.h>
 
+#include "timekeeping.h"
+
 /**
  * struct clock_read_data - data required to read from sched_clock()
  *
index 4bc37ac3bb0526994e2dcacd20369e6f2e98f8d3..5ee0f77094107486752338021a7e22210bdbec1d 100644 (file)
@@ -110,8 +110,7 @@ void update_vsyscall(struct timekeeper *tk)
        nsec            = nsec + tk->wall_to_monotonic.tv_nsec;
        vdso_ts->sec    += __iter_div_u64_rem(nsec, NSEC_PER_SEC, &vdso_ts->nsec);
 
-       if (__arch_use_vsyscall(vdata))
-               update_vdso_data(vdata, tk);
+       update_vdso_data(vdata, tk);
 
        __arch_update_vsyscall(vdata, tk);
 
@@ -124,10 +123,8 @@ void update_vsyscall_tz(void)
 {
        struct vdso_data *vdata = __arch_get_k_vdso_data();
 
-       if (__arch_use_vsyscall(vdata)) {
-               vdata[CS_HRES_COARSE].tz_minuteswest = sys_tz.tz_minuteswest;
-               vdata[CS_HRES_COARSE].tz_dsttime = sys_tz.tz_dsttime;
-       }
+       vdata[CS_HRES_COARSE].tz_minuteswest = sys_tz.tz_minuteswest;
+       vdata[CS_HRES_COARSE].tz_dsttime = sys_tz.tz_dsttime;
 
        __arch_sync_vdso_data(vdata);
 }
index 0892e38ed6fbeca73258ce357d678c922e48468d..a9dfa04ffa4499117833495aded1db5fdc19eedd 100644 (file)
@@ -272,9 +272,11 @@ int perf_kprobe_init(struct perf_event *p_event, bool is_retprobe)
                goto out;
        }
 
+       mutex_lock(&event_mutex);
        ret = perf_trace_event_init(tp_event, p_event);
        if (ret)
                destroy_local_trace_kprobe(tp_event);
+       mutex_unlock(&event_mutex);
 out:
        kfree(func);
        return ret;
@@ -282,8 +284,10 @@ out:
 
 void perf_kprobe_destroy(struct perf_event *p_event)
 {
+       mutex_lock(&event_mutex);
        perf_trace_event_close(p_event);
        perf_trace_event_unreg(p_event);
+       mutex_unlock(&event_mutex);
 
        destroy_local_trace_kprobe(p_event->tp_event);
 }
index 57648c5aa6797767781f3d9464eed32f426c1b40..7482a1466ebfede5ce50e458d5b80cc2c6a18951 100644 (file)
@@ -679,6 +679,8 @@ static bool synth_field_signed(char *type)
 {
        if (str_has_prefix(type, "u"))
                return false;
+       if (strcmp(type, "gfp_t") == 0)
+               return false;
 
        return true;
 }
index 183f92a297ca557d86de048325f78a048741e37c..3321d04dfa5a5a703909d1f201ffecf75a7767fa 100644 (file)
@@ -447,7 +447,6 @@ config ASSOCIATIVE_ARRAY
 config HAS_IOMEM
        bool
        depends on !NO_IOMEM
-       select GENERIC_IO
        default y
 
 config HAS_IOPORT_MAP
index 5cff72f18c4a4ce4f0770f968dadefd4e6d190ad..33ffbf30885394c89d2c8c933eeb50a7769c357e 100644 (file)
@@ -106,7 +106,12 @@ retry:
                was_locked = 1;
        } else {
                local_irq_restore(flags);
-               cpu_relax();
+               /*
+                * Wait for the lock to release before jumping to
+                * atomic_cmpxchg() in order to mitigate the thundering herd
+                * problem.
+                */
+               do { cpu_relax(); } while (atomic_read(&dump_lock) != -1);
                goto retry;
        }
 
index 66a3748924828dcf4be6f3ffb06ef4a785600f7d..c2cf2c52bbde5c54534b2227cee2176baf78383a 100644 (file)
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -215,7 +215,7 @@ int idr_for_each(const struct idr *idr,
 EXPORT_SYMBOL(idr_for_each);
 
 /**
- * idr_get_next() - Find next populated entry.
+ * idr_get_next_ul() - Find next populated entry.
  * @idr: IDR handle.
  * @nextid: Pointer to an ID.
  *
@@ -224,7 +224,7 @@ EXPORT_SYMBOL(idr_for_each);
  * to the ID of the found value.  To use in a loop, the value pointed to by
  * nextid must be incremented by the user.
  */
-void *idr_get_next(struct idr *idr, int *nextid)
+void *idr_get_next_ul(struct idr *idr, unsigned long *nextid)
 {
        struct radix_tree_iter iter;
        void __rcu **slot;
@@ -245,18 +245,14 @@ void *idr_get_next(struct idr *idr, int *nextid)
        }
        if (!slot)
                return NULL;
-       id = iter.index + base;
-
-       if (WARN_ON_ONCE(id > INT_MAX))
-               return NULL;
 
-       *nextid = id;
+       *nextid = iter.index + base;
        return entry;
 }
-EXPORT_SYMBOL(idr_get_next);
+EXPORT_SYMBOL(idr_get_next_ul);
 
 /**
- * idr_get_next_ul() - Find next populated entry.
+ * idr_get_next() - Find next populated entry.
  * @idr: IDR handle.
  * @nextid: Pointer to an ID.
  *
@@ -265,22 +261,17 @@ EXPORT_SYMBOL(idr_get_next);
  * to the ID of the found value.  To use in a loop, the value pointed to by
  * nextid must be incremented by the user.
  */
-void *idr_get_next_ul(struct idr *idr, unsigned long *nextid)
+void *idr_get_next(struct idr *idr, int *nextid)
 {
-       struct radix_tree_iter iter;
-       void __rcu **slot;
-       unsigned long base = idr->idr_base;
        unsigned long id = *nextid;
+       void *entry = idr_get_next_ul(idr, &id);
 
-       id = (id < base) ? 0 : id - base;
-       slot = radix_tree_iter_find(&idr->idr_rt, &iter, id);
-       if (!slot)
+       if (WARN_ON_ONCE(id > INT_MAX))
                return NULL;
-
-       *nextid = iter.index + base;
-       return rcu_dereference_raw(*slot);
+       *nextid = id;
+       return entry;
 }
-EXPORT_SYMBOL(idr_get_next_ul);
+EXPORT_SYMBOL(idr_get_next);
 
 /**
  * idr_replace() - replace pointer for given ID.
index 18c1dfbb1765487a3df6bd5792c8d6e599fed15c..c8fa1d274530299a124bedf0d689dd108dc5776e 100644 (file)
@@ -1529,7 +1529,7 @@ void __rcu **idr_get_free(struct radix_tree_root *root,
                        offset = radix_tree_find_next_bit(node, IDR_FREE,
                                                        offset + 1);
                        start = next_index(start, node, offset);
-                       if (start > max)
+                       if (start > max || start == 0)
                                return ERR_PTR(-ENOSPC);
                        while (offset == RADIX_TREE_MAP_SIZE) {
                                offset = node->offset + 1;
index 9d631a7b6a70520bc9afccbef042cf8519ee5143..7df4f7f395bf2810913725747d29f1717eb4e1ec 100644 (file)
@@ -1110,6 +1110,28 @@ static noinline void check_find_entry(struct xarray *xa)
        XA_BUG_ON(xa, !xa_empty(xa));
 }
 
+static noinline void check_move_tiny(struct xarray *xa)
+{
+       XA_STATE(xas, xa, 0);
+
+       XA_BUG_ON(xa, !xa_empty(xa));
+       rcu_read_lock();
+       XA_BUG_ON(xa, xas_next(&xas) != NULL);
+       XA_BUG_ON(xa, xas_next(&xas) != NULL);
+       rcu_read_unlock();
+       xa_store_index(xa, 0, GFP_KERNEL);
+       rcu_read_lock();
+       xas_set(&xas, 0);
+       XA_BUG_ON(xa, xas_next(&xas) != xa_mk_index(0));
+       XA_BUG_ON(xa, xas_next(&xas) != NULL);
+       xas_set(&xas, 0);
+       XA_BUG_ON(xa, xas_prev(&xas) != xa_mk_index(0));
+       XA_BUG_ON(xa, xas_prev(&xas) != NULL);
+       rcu_read_unlock();
+       xa_erase_index(xa, 0);
+       XA_BUG_ON(xa, !xa_empty(xa));
+}
+
 static noinline void check_move_small(struct xarray *xa, unsigned long idx)
 {
        XA_STATE(xas, xa, 0);
@@ -1217,6 +1239,8 @@ static noinline void check_move(struct xarray *xa)
 
        xa_destroy(xa);
 
+       check_move_tiny(xa);
+
        for (i = 0; i < 16; i++)
                check_move_small(xa, 1UL << i);
 
index e630e7ff57f1f9102e28820ef98f9c49e23da2ed..45f57fd2db649999741f4c2b9d375635453b53db 100644 (file)
@@ -214,9 +214,10 @@ int __cvdso_clock_getres_common(clockid_t clock, struct __kernel_timespec *res)
                return -1;
        }
 
-       res->tv_sec = 0;
-       res->tv_nsec = ns;
-
+       if (likely(res)) {
+               res->tv_sec = 0;
+               res->tv_nsec = ns;
+       }
        return 0;
 }
 
@@ -245,7 +246,7 @@ __cvdso_clock_getres_time32(clockid_t clock, struct old_timespec32 *res)
                ret = clock_getres_fallback(clock, &ts);
 #endif
 
-       if (likely(!ret)) {
+       if (likely(!ret && res)) {
                res->tv_sec = ts.tv_sec;
                res->tv_nsec = ts.tv_nsec;
        }
index 446b956c918888d06dfca776d00aed8f3c2e54de..1237c213f52bc08ad3f58387aa603979c7cafbcd 100644 (file)
@@ -994,6 +994,8 @@ void *__xas_prev(struct xa_state *xas)
 
        if (!xas_frozen(xas->xa_node))
                xas->xa_index--;
+       if (!xas->xa_node)
+               return set_bounds(xas);
        if (xas_not_node(xas->xa_node))
                return xas_load(xas);
 
@@ -1031,6 +1033,8 @@ void *__xas_next(struct xa_state *xas)
 
        if (!xas_frozen(xas->xa_node))
                xas->xa_index++;
+       if (!xas->xa_node)
+               return set_bounds(xas);
        if (xas_not_node(xas->xa_node))
                return xas_load(xas);
 
index 0a1b4b484ac5b4a0eed5e5148f04849d9e09607b..f05d27b7183dcd9699427e19fdc1b8cd00642028 100644 (file)
@@ -1028,12 +1028,13 @@ static void collapse_huge_page(struct mm_struct *mm,
 
        anon_vma_lock_write(vma->anon_vma);
 
-       pte = pte_offset_map(pmd, address);
-       pte_ptl = pte_lockptr(mm, pmd);
-
        mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, NULL, mm,
                                address, address + HPAGE_PMD_SIZE);
        mmu_notifier_invalidate_range_start(&range);
+
+       pte = pte_offset_map(pmd, address);
+       pte_ptl = pte_lockptr(mm, pmd);
+
        pmd_ptl = pmd_lock(mm, pmd); /* probably unnecessary */
        /*
         * After this gup_fast can't run anymore. This also removes
index 363106578876152b06ced3999cdacefaac0aa485..37592dd7ae3264ba4bf8cc94c63910f56585aa5b 100644 (file)
@@ -484,7 +484,7 @@ ino_t page_cgroup_ino(struct page *page)
        unsigned long ino = 0;
 
        rcu_read_lock();
-       if (PageHead(page) && PageSlab(page))
+       if (PageSlab(page) && !PageTail(page))
                memcg = memcg_from_slab_page(page);
        else
                memcg = READ_ONCE(page->mem_cgroup);
@@ -2534,6 +2534,15 @@ retry:
                goto retry;
        }
 
+       /*
+        * Memcg doesn't have a dedicated reserve for atomic
+        * allocations. But like the global atomic pool, we need to
+        * put the burden of reclaim on regular allocation requests
+        * and let these go through as privileged allocations.
+        */
+       if (gfp_mask & __GFP_ATOMIC)
+               goto force;
+
        /*
         * Unlike in global OOM situations, memcg is not in a physical
         * memory shortage.  Allow dying and OOM-killed tasks to
@@ -5014,12 +5023,6 @@ static void __mem_cgroup_free(struct mem_cgroup *memcg)
 {
        int node;
 
-       /*
-        * Flush percpu vmstats and vmevents to guarantee the value correctness
-        * on parent's and all ancestor levels.
-        */
-       memcg_flush_percpu_vmstats(memcg, false);
-       memcg_flush_percpu_vmevents(memcg);
        for_each_node(node)
                free_mem_cgroup_per_node_info(memcg, node);
        free_percpu(memcg->vmstats_percpu);
@@ -5030,6 +5033,12 @@ static void __mem_cgroup_free(struct mem_cgroup *memcg)
 static void mem_cgroup_free(struct mem_cgroup *memcg)
 {
        memcg_wb_domain_exit(memcg);
+       /*
+        * Flush percpu vmstats and vmevents to guarantee the value correctness
+        * on parent's and all ancestor levels.
+        */
+       memcg_flush_percpu_vmstats(memcg, false);
+       memcg_flush_percpu_vmevents(memcg);
        __mem_cgroup_free(memcg);
 }
 
index df570e5c71cc6b8f696ac44d225529e17703876d..07e5c67f48a85c9c67391a4e6b0a6e3f48466d3b 100644 (file)
@@ -447,6 +447,14 @@ static void update_pgdat_span(struct pglist_data *pgdat)
                                             zone->spanned_pages;
 
                /* No need to lock the zones, they can't change. */
+               if (!zone->spanned_pages)
+                       continue;
+               if (!node_end_pfn) {
+                       node_start_pfn = zone->zone_start_pfn;
+                       node_end_pfn = zone_end_pfn;
+                       continue;
+               }
+
                if (zone_end_pfn > node_end_pfn)
                        node_end_pfn = zone_end_pfn;
                if (zone->zone_start_pfn < node_start_pfn)
index 7fde88695f35d62c1f22ffe1cc724ffe85ea92e9..9a889e456168bcc72957dc79fe4c7c234243aa73 100644 (file)
@@ -180,7 +180,7 @@ int __mmu_notifier_invalidate_range_start(struct mmu_notifier_range *range)
                                        mn->ops->invalidate_range_start, _ret,
                                        !mmu_notifier_range_blockable(range) ? "non-" : "");
                                WARN_ON(mmu_notifier_range_blockable(range) ||
-                                       ret != -EAGAIN);
+                                       _ret != -EAGAIN);
                                ret = _ret;
                        }
                }
index ecc3dbad606b04ce690e584e4d6609e85c66173b..f391c0c4ed1deb2299a7552dcd27c8d68e4b1412 100644 (file)
@@ -1947,6 +1947,14 @@ void __init page_alloc_init_late(void)
        /* Block until all are initialised */
        wait_for_completion(&pgdat_init_all_done_comp);
 
+       /*
+        * The number of managed pages has changed due to the initialisation
+        * so the pcpu batch and high limits needs to be updated or the limits
+        * will be artificially small.
+        */
+       for_each_populated_zone(zone)
+               zone_pcp_update(zone);
+
        /*
         * We initialized the rest of the deferred pages.  Permanently disable
         * on-demand struct page initialization.
@@ -3720,10 +3728,6 @@ try_this_zone:
 static void warn_alloc_show_mem(gfp_t gfp_mask, nodemask_t *nodemask)
 {
        unsigned int filter = SHOW_MEM_FILTER_NODES;
-       static DEFINE_RATELIMIT_STATE(show_mem_rs, HZ, 1);
-
-       if (!__ratelimit(&show_mem_rs))
-               return;
 
        /*
         * This documents exceptions given to allocations in certain
@@ -3744,8 +3748,7 @@ void warn_alloc(gfp_t gfp_mask, nodemask_t *nodemask, const char *fmt, ...)
 {
        struct va_format vaf;
        va_list args;
-       static DEFINE_RATELIMIT_STATE(nopage_rs, DEFAULT_RATELIMIT_INTERVAL,
-                                     DEFAULT_RATELIMIT_BURST);
+       static DEFINE_RATELIMIT_STATE(nopage_rs, 10*HZ, 1);
 
        if ((gfp_mask & __GFP_NOWARN) || !__ratelimit(&nopage_rs))
                return;
@@ -8514,7 +8517,6 @@ void free_contig_range(unsigned long pfn, unsigned int nr_pages)
        WARN(count != 0, "%d pages are still in use!\n", count);
 }
 
-#ifdef CONFIG_MEMORY_HOTPLUG
 /*
  * The zone indicated has a new number of managed_pages; batch sizes and percpu
  * page high values need to be recalulated.
@@ -8528,7 +8530,6 @@ void __meminit zone_pcp_update(struct zone *zone)
                                per_cpu_ptr(zone->pageset, cpu));
        mutex_unlock(&pcp_batch_high_lock);
 }
-#endif
 
 void zone_pcp_reset(struct zone *zone)
 {
index 68e455f2b698cbfab04ac4a1d61df3c1a32cfe9e..b2b01694dc43f63259fa3ee1e1b59ef3505f794b 100644 (file)
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -323,8 +323,8 @@ static inline struct kmem_cache *memcg_root_cache(struct kmem_cache *s)
  * Expects a pointer to a slab page. Please note, that PageSlab() check
  * isn't sufficient, as it returns true also for tail compound slab pages,
  * which do not have slab_cache pointer set.
- * So this function assumes that the page can pass PageHead() and PageSlab()
- * checks.
+ * So this function assumes that the page can pass PageSlab() && !PageTail()
+ * check.
  *
  * The kmem_cache can be reparented asynchronously. The caller must ensure
  * the memcg lifetime, e.g. by taking rcu_read_lock() or cgroup_mutex.
index 6afc892a148a0408a901695d42529a2a1be99939..a8222041bd44d648a4c8b5a1e5e345314efb050e 100644 (file)
@@ -1383,12 +1383,29 @@ static void pagetypeinfo_showfree_print(struct seq_file *m,
                        unsigned long freecount = 0;
                        struct free_area *area;
                        struct list_head *curr;
+                       bool overflow = false;
 
                        area = &(zone->free_area[order]);
 
-                       list_for_each(curr, &area->free_list[mtype])
-                               freecount++;
-                       seq_printf(m, "%6lu ", freecount);
+                       list_for_each(curr, &area->free_list[mtype]) {
+                               /*
+                                * Cap the free_list iteration because it might
+                                * be really large and we are under a spinlock
+                                * so a long time spent here could trigger a
+                                * hard lockup detector. Anyway this is a
+                                * debugging tool so knowing there is a handful
+                                * of pages of this order should be more than
+                                * sufficient.
+                                */
+                               if (++freecount >= 100000) {
+                                       overflow = true;
+                                       break;
+                               }
+                       }
+                       seq_printf(m, "%s%6lu ", overflow ? ">" : "", freecount);
+                       spin_unlock_irq(&zone->lock);
+                       cond_resched();
+                       spin_lock_irq(&zone->lock);
                }
                seq_putc(m, '\n');
        }
@@ -1972,7 +1989,7 @@ void __init init_mm_internals(void)
 #endif
 #ifdef CONFIG_PROC_FS
        proc_create_seq("buddyinfo", 0444, NULL, &fragmentation_op);
-       proc_create_seq("pagetypeinfo", 0444, NULL, &pagetypeinfo_op);
+       proc_create_seq("pagetypeinfo", 0400, NULL, &pagetypeinfo_op);
        proc_create_seq("vmstat", 0444, NULL, &vmstat_op);
        proc_create_seq("zoneinfo", 0444, NULL, &zoneinfo_op);
 #endif
index 54728d2eda189d870ecb97acd0278fdca4358761..d4bcfd8f95bf6435902e10cce19fc43b47d867d9 100644 (file)
@@ -172,7 +172,6 @@ int register_vlan_dev(struct net_device *dev, struct netlink_ext_ack *extack)
        if (err < 0)
                goto out_uninit_mvrp;
 
-       vlan->nest_level = dev_get_nest_level(real_dev) + 1;
        err = register_netdevice(dev);
        if (err < 0)
                goto out_uninit_mvrp;
index 93eadf1791239fd8eb81d4724ae37c7b959e5ca9..e5bff5cc6f97562a9887195ced5c572c1951915e 100644 (file)
@@ -489,36 +489,6 @@ static void vlan_dev_set_rx_mode(struct net_device *vlan_dev)
        dev_uc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev);
 }
 
-/*
- * vlan network devices have devices nesting below it, and are a special
- * "super class" of normal network devices; split their locks off into a
- * separate class since they always nest.
- */
-static struct lock_class_key vlan_netdev_xmit_lock_key;
-static struct lock_class_key vlan_netdev_addr_lock_key;
-
-static void vlan_dev_set_lockdep_one(struct net_device *dev,
-                                    struct netdev_queue *txq,
-                                    void *_subclass)
-{
-       lockdep_set_class_and_subclass(&txq->_xmit_lock,
-                                      &vlan_netdev_xmit_lock_key,
-                                      *(int *)_subclass);
-}
-
-static void vlan_dev_set_lockdep_class(struct net_device *dev, int subclass)
-{
-       lockdep_set_class_and_subclass(&dev->addr_list_lock,
-                                      &vlan_netdev_addr_lock_key,
-                                      subclass);
-       netdev_for_each_tx_queue(dev, vlan_dev_set_lockdep_one, &subclass);
-}
-
-static int vlan_dev_get_lock_subclass(struct net_device *dev)
-{
-       return vlan_dev_priv(dev)->nest_level;
-}
-
 static const struct header_ops vlan_header_ops = {
        .create  = vlan_dev_hard_header,
        .parse   = eth_header_parse,
@@ -609,8 +579,6 @@ static int vlan_dev_init(struct net_device *dev)
 
        SET_NETDEV_DEVTYPE(dev, &vlan_type);
 
-       vlan_dev_set_lockdep_class(dev, vlan_dev_get_lock_subclass(dev));
-
        vlan->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats);
        if (!vlan->vlan_pcpu_stats)
                return -ENOMEM;
@@ -812,7 +780,6 @@ static const struct net_device_ops vlan_netdev_ops = {
        .ndo_netpoll_cleanup    = vlan_dev_netpoll_cleanup,
 #endif
        .ndo_fix_features       = vlan_dev_fix_features,
-       .ndo_get_lock_subclass  = vlan_dev_get_lock_subclass,
        .ndo_get_iflink         = vlan_dev_get_iflink,
 };
 
index b7528e77997c88b7cf15f0b48412e3abef0620e3..0ce530af534ddfed26a32b1b24f202ee7c582198 100644 (file)
@@ -668,7 +668,7 @@ __poll_t vcc_poll(struct file *file, struct socket *sock, poll_table *wait)
                mask |= EPOLLHUP;
 
        /* readable? */
-       if (!skb_queue_empty(&sk->sk_receive_queue))
+       if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
                mask |= EPOLLIN | EPOLLRDNORM;
 
        /* writable? */
index d78938e3e0085d9cff138b805148a0e77de3f654..5b0b20e6da956b4333b118bce1c09c5acef6d66f 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/kernel.h>
 #include <linux/kref.h>
 #include <linux/list.h>
+#include <linux/lockdep.h>
+#include <linux/mutex.h>
 #include <linux/netdevice.h>
 #include <linux/netlink.h>
 #include <linux/pkt_sched.h>
@@ -193,14 +195,18 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
        unsigned char *ogm_buff;
        u32 random_seqno;
 
+       mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
+
        /* randomize initial seqno to avoid collision */
        get_random_bytes(&random_seqno, sizeof(random_seqno));
        atomic_set(&hard_iface->bat_iv.ogm_seqno, random_seqno);
 
        hard_iface->bat_iv.ogm_buff_len = BATADV_OGM_HLEN;
        ogm_buff = kmalloc(hard_iface->bat_iv.ogm_buff_len, GFP_ATOMIC);
-       if (!ogm_buff)
+       if (!ogm_buff) {
+               mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
                return -ENOMEM;
+       }
 
        hard_iface->bat_iv.ogm_buff = ogm_buff;
 
@@ -212,35 +218,59 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
        batadv_ogm_packet->reserved = 0;
        batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE;
 
+       mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
+
        return 0;
 }
 
 static void batadv_iv_ogm_iface_disable(struct batadv_hard_iface *hard_iface)
 {
+       mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
+
        kfree(hard_iface->bat_iv.ogm_buff);
        hard_iface->bat_iv.ogm_buff = NULL;
+
+       mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
 }
 
 static void batadv_iv_ogm_iface_update_mac(struct batadv_hard_iface *hard_iface)
 {
        struct batadv_ogm_packet *batadv_ogm_packet;
-       unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff;
+       void *ogm_buff;
 
-       batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
+       mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
+
+       ogm_buff = hard_iface->bat_iv.ogm_buff;
+       if (!ogm_buff)
+               goto unlock;
+
+       batadv_ogm_packet = ogm_buff;
        ether_addr_copy(batadv_ogm_packet->orig,
                        hard_iface->net_dev->dev_addr);
        ether_addr_copy(batadv_ogm_packet->prev_sender,
                        hard_iface->net_dev->dev_addr);
+
+unlock:
+       mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
 }
 
 static void
 batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface)
 {
        struct batadv_ogm_packet *batadv_ogm_packet;
-       unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff;
+       void *ogm_buff;
 
-       batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
+       mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
+
+       ogm_buff = hard_iface->bat_iv.ogm_buff;
+       if (!ogm_buff)
+               goto unlock;
+
+       batadv_ogm_packet = ogm_buff;
        batadv_ogm_packet->ttl = BATADV_TTL;
+
+unlock:
+       mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
 }
 
 /* when do we schedule our own ogm to be sent */
@@ -742,7 +772,11 @@ batadv_iv_ogm_slide_own_bcast_window(struct batadv_hard_iface *hard_iface)
        }
 }
 
-static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
+/**
+ * batadv_iv_ogm_schedule_buff() - schedule submission of hardif ogm buffer
+ * @hard_iface: interface whose ogm buffer should be transmitted
+ */
+static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)
 {
        struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
        unsigned char **ogm_buff = &hard_iface->bat_iv.ogm_buff;
@@ -753,9 +787,7 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
        u16 tvlv_len = 0;
        unsigned long send_time;
 
-       if (hard_iface->if_status == BATADV_IF_NOT_IN_USE ||
-           hard_iface->if_status == BATADV_IF_TO_BE_REMOVED)
-               return;
+       lockdep_assert_held(&hard_iface->bat_iv.ogm_buff_mutex);
 
        /* the interface gets activated here to avoid race conditions between
         * the moment of activating the interface in
@@ -823,6 +855,17 @@ out:
                batadv_hardif_put(primary_if);
 }
 
+static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
+{
+       if (hard_iface->if_status == BATADV_IF_NOT_IN_USE ||
+           hard_iface->if_status == BATADV_IF_TO_BE_REMOVED)
+               return;
+
+       mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
+       batadv_iv_ogm_schedule_buff(hard_iface);
+       mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
+}
+
 /**
  * batadv_iv_orig_ifinfo_sum() - Get bcast_own sum for originator over iterface
  * @orig_node: originator which reproadcasted the OGMs directly
index dc4f7430cb5a6528ac4635c943ab4d65db1a538b..8033f24f506cae2d734aea5296cb5bd3066e7277 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/kref.h>
 #include <linux/list.h>
 #include <linux/lockdep.h>
+#include <linux/mutex.h>
 #include <linux/netdevice.h>
 #include <linux/random.h>
 #include <linux/rculist.h>
@@ -256,14 +257,12 @@ static void batadv_v_ogm_queue_on_if(struct sk_buff *skb,
 }
 
 /**
- * batadv_v_ogm_send() - periodic worker broadcasting the own OGM
- * @work: work queue item
+ * batadv_v_ogm_send_softif() - periodic worker broadcasting the own OGM
+ * @bat_priv: the bat priv with all the soft interface information
  */
-static void batadv_v_ogm_send(struct work_struct *work)
+static void batadv_v_ogm_send_softif(struct batadv_priv *bat_priv)
 {
        struct batadv_hard_iface *hard_iface;
-       struct batadv_priv_bat_v *bat_v;
-       struct batadv_priv *bat_priv;
        struct batadv_ogm2_packet *ogm_packet;
        struct sk_buff *skb, *skb_tmp;
        unsigned char *ogm_buff;
@@ -271,8 +270,7 @@ static void batadv_v_ogm_send(struct work_struct *work)
        u16 tvlv_len = 0;
        int ret;
 
-       bat_v = container_of(work, struct batadv_priv_bat_v, ogm_wq.work);
-       bat_priv = container_of(bat_v, struct batadv_priv, bat_v);
+       lockdep_assert_held(&bat_priv->bat_v.ogm_buff_mutex);
 
        if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
                goto out;
@@ -363,6 +361,23 @@ out:
        return;
 }
 
+/**
+ * batadv_v_ogm_send() - periodic worker broadcasting the own OGM
+ * @work: work queue item
+ */
+static void batadv_v_ogm_send(struct work_struct *work)
+{
+       struct batadv_priv_bat_v *bat_v;
+       struct batadv_priv *bat_priv;
+
+       bat_v = container_of(work, struct batadv_priv_bat_v, ogm_wq.work);
+       bat_priv = container_of(bat_v, struct batadv_priv, bat_v);
+
+       mutex_lock(&bat_priv->bat_v.ogm_buff_mutex);
+       batadv_v_ogm_send_softif(bat_priv);
+       mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex);
+}
+
 /**
  * batadv_v_ogm_aggr_work() - OGM queue periodic task per interface
  * @work: work queue item
@@ -424,11 +439,15 @@ void batadv_v_ogm_primary_iface_set(struct batadv_hard_iface *primary_iface)
        struct batadv_priv *bat_priv = netdev_priv(primary_iface->soft_iface);
        struct batadv_ogm2_packet *ogm_packet;
 
+       mutex_lock(&bat_priv->bat_v.ogm_buff_mutex);
        if (!bat_priv->bat_v.ogm_buff)
-               return;
+               goto unlock;
 
        ogm_packet = (struct batadv_ogm2_packet *)bat_priv->bat_v.ogm_buff;
        ether_addr_copy(ogm_packet->orig, primary_iface->net_dev->dev_addr);
+
+unlock:
+       mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex);
 }
 
 /**
@@ -1050,6 +1069,8 @@ int batadv_v_ogm_init(struct batadv_priv *bat_priv)
        atomic_set(&bat_priv->bat_v.ogm_seqno, random_seqno);
        INIT_DELAYED_WORK(&bat_priv->bat_v.ogm_wq, batadv_v_ogm_send);
 
+       mutex_init(&bat_priv->bat_v.ogm_buff_mutex);
+
        return 0;
 }
 
@@ -1061,7 +1082,11 @@ void batadv_v_ogm_free(struct batadv_priv *bat_priv)
 {
        cancel_delayed_work_sync(&bat_priv->bat_v.ogm_wq);
 
+       mutex_lock(&bat_priv->bat_v.ogm_buff_mutex);
+
        kfree(bat_priv->bat_v.ogm_buff);
        bat_priv->bat_v.ogm_buff = NULL;
        bat_priv->bat_v.ogm_buff_len = 0;
+
+       mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex);
 }
index c90e47342bb0698ae460efe7f8ca35bd313d6cce..afb52282d5bd0d495febb5b7d636830f5475d74e 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/kref.h>
 #include <linux/limits.h>
 #include <linux/list.h>
+#include <linux/mutex.h>
 #include <linux/netdevice.h>
 #include <linux/printk.h>
 #include <linux/rculist.h>
@@ -929,6 +930,7 @@ batadv_hardif_add_interface(struct net_device *net_dev)
        INIT_LIST_HEAD(&hard_iface->list);
        INIT_HLIST_HEAD(&hard_iface->neigh_list);
 
+       mutex_init(&hard_iface->bat_iv.ogm_buff_mutex);
        spin_lock_init(&hard_iface->neigh_list_lock);
        kref_init(&hard_iface->refcount);
 
index 9cbed6f5a85a61640de1bb14b6e20ed13db352a9..5ee8e9a100f903d01fb6799828dfba6ae416ec66 100644 (file)
@@ -740,36 +740,6 @@ static int batadv_interface_kill_vid(struct net_device *dev, __be16 proto,
        return 0;
 }
 
-/* batman-adv network devices have devices nesting below it and are a special
- * "super class" of normal network devices; split their locks off into a
- * separate class since they always nest.
- */
-static struct lock_class_key batadv_netdev_xmit_lock_key;
-static struct lock_class_key batadv_netdev_addr_lock_key;
-
-/**
- * batadv_set_lockdep_class_one() - Set lockdep class for a single tx queue
- * @dev: device which owns the tx queue
- * @txq: tx queue to modify
- * @_unused: always NULL
- */
-static void batadv_set_lockdep_class_one(struct net_device *dev,
-                                        struct netdev_queue *txq,
-                                        void *_unused)
-{
-       lockdep_set_class(&txq->_xmit_lock, &batadv_netdev_xmit_lock_key);
-}
-
-/**
- * batadv_set_lockdep_class() - Set txq and addr_list lockdep class
- * @dev: network device to modify
- */
-static void batadv_set_lockdep_class(struct net_device *dev)
-{
-       lockdep_set_class(&dev->addr_list_lock, &batadv_netdev_addr_lock_key);
-       netdev_for_each_tx_queue(dev, batadv_set_lockdep_class_one, NULL);
-}
-
 /**
  * batadv_softif_init_late() - late stage initialization of soft interface
  * @dev: registered network device to modify
@@ -783,8 +753,6 @@ static int batadv_softif_init_late(struct net_device *dev)
        int ret;
        size_t cnt_len = sizeof(u64) * BATADV_CNT_NUM;
 
-       batadv_set_lockdep_class(dev);
-
        bat_priv = netdev_priv(dev);
        bat_priv->soft_iface = dev;
 
index be7c02aa91e26dcc8d0c322fa162b0dd3a5a0eb9..4d7f1baee7b7da7d32060014400e89db9c7f0b7a 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/if.h>
 #include <linux/if_ether.h>
 #include <linux/kref.h>
+#include <linux/mutex.h>
 #include <linux/netdevice.h>
 #include <linux/netlink.h>
 #include <linux/sched.h> /* for linux/wait.h */
@@ -81,6 +82,9 @@ struct batadv_hard_iface_bat_iv {
 
        /** @ogm_seqno: OGM sequence number - used to identify each OGM */
        atomic_t ogm_seqno;
+
+       /** @ogm_buff_mutex: lock protecting ogm_buff and ogm_buff_len */
+       struct mutex ogm_buff_mutex;
 };
 
 /**
@@ -1539,6 +1543,9 @@ struct batadv_priv_bat_v {
        /** @ogm_seqno: OGM sequence number - used to identify each OGM */
        atomic_t ogm_seqno;
 
+       /** @ogm_buff_mutex: lock protecting ogm_buff and ogm_buff_len */
+       struct mutex ogm_buff_mutex;
+
        /** @ogm_wq: workqueue used to schedule OGM transmissions */
        struct delayed_work ogm_wq;
 };
index bb55d92691b068d32b281b1b3ceff58b8ac51fc4..4febc82a7c7613244125696cfd464099e10991dc 100644 (file)
@@ -571,15 +571,7 @@ static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev)
        return err < 0 ? NET_XMIT_DROP : err;
 }
 
-static int bt_dev_init(struct net_device *dev)
-{
-       netdev_lockdep_set_classes(dev);
-
-       return 0;
-}
-
 static const struct net_device_ops netdev_ops = {
-       .ndo_init               = bt_dev_init,
        .ndo_start_xmit         = bt_xmit,
 };
 
index 94ddf19998c7ee7098b52c9ef37f3e0296089fab..5f508c50649d0abc317ed83cc0768f6b7a64de96 100644 (file)
@@ -460,7 +460,7 @@ __poll_t bt_sock_poll(struct file *file, struct socket *sock,
        if (sk->sk_state == BT_LISTEN)
                return bt_accept_poll(sk);
 
-       if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
+       if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue))
                mask |= EPOLLERR |
                        (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0);
 
@@ -470,7 +470,7 @@ __poll_t bt_sock_poll(struct file *file, struct socket *sock,
        if (sk->sk_shutdown == SHUTDOWN_MASK)
                mask |= EPOLLHUP;
 
-       if (!skb_queue_empty(&sk->sk_receive_queue))
+       if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
                mask |= EPOLLIN | EPOLLRDNORM;
 
        if (sk->sk_state == BT_CLOSED)
index 681b72862c165558e756afacda786998a0e9f185..e804a3016902b741205366b5e9876a094f9f5856 100644 (file)
@@ -24,8 +24,6 @@
 const struct nf_br_ops __rcu *nf_br_ops __read_mostly;
 EXPORT_SYMBOL_GPL(nf_br_ops);
 
-static struct lock_class_key bridge_netdev_addr_lock_key;
-
 /* net device transmit always called with BH disabled */
 netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
 {
@@ -108,11 +106,6 @@ out:
        return NETDEV_TX_OK;
 }
 
-static void br_set_lockdep_class(struct net_device *dev)
-{
-       lockdep_set_class(&dev->addr_list_lock, &bridge_netdev_addr_lock_key);
-}
-
 static int br_dev_init(struct net_device *dev)
 {
        struct net_bridge *br = netdev_priv(dev);
@@ -150,7 +143,6 @@ static int br_dev_init(struct net_device *dev)
                br_mdb_hash_fini(br);
                br_fdb_hash_fini(br);
        }
-       br_set_lockdep_class(dev);
 
        return err;
 }
index ed91ea31978afff3e2751387954c0e146cd737b8..12a4f4d9368109999d5b2d3c5fe24957c5e7f747 100644 (file)
@@ -20,7 +20,6 @@ static unsigned int
 ebt_dnat_tg(struct sk_buff *skb, const struct xt_action_param *par)
 {
        const struct ebt_nat_info *info = par->targinfo;
-       struct net_device *dev;
 
        if (skb_ensure_writable(skb, ETH_ALEN))
                return EBT_DROP;
@@ -33,10 +32,22 @@ ebt_dnat_tg(struct sk_buff *skb, const struct xt_action_param *par)
                else
                        skb->pkt_type = PACKET_MULTICAST;
        } else {
-               if (xt_hooknum(par) != NF_BR_BROUTING)
-                       dev = br_port_get_rcu(xt_in(par))->br->dev;
-               else
+               const struct net_device *dev;
+
+               switch (xt_hooknum(par)) {
+               case NF_BR_BROUTING:
                        dev = xt_in(par);
+                       break;
+               case NF_BR_PRE_ROUTING:
+                       dev = br_port_get_rcu(xt_in(par))->br->dev;
+                       break;
+               default:
+                       dev = NULL;
+                       break;
+               }
+
+               if (!dev) /* NF_BR_LOCAL_OUT */
+                       return info->target;
 
                if (ether_addr_equal(info->mac, dev->dev_addr))
                        skb->pkt_type = PACKET_HOST;
index 506d6141e44eea67ccc34123ad4250a19bcc7ab7..8096732223828a7110ab35d715fe1894ddf57a91 100644 (file)
@@ -95,7 +95,7 @@ slow_path:
         * This may also be a clone skbuff, we could preserve the geometry for
         * the copies but probably not worth the effort.
         */
-       ip_frag_init(skb, hlen, ll_rs, frag_max_size, &state);
+       ip_frag_init(skb, hlen, ll_rs, frag_max_size, false, &state);
 
        while (state.left > 0) {
                struct sk_buff *skb2;
index 13ea920600aeb66af017134cbe5fcfd5ccc6020e..ef14da50a9819183c538f14b97b5e4986adafb45 100644 (file)
@@ -953,7 +953,7 @@ static __poll_t caif_poll(struct file *file,
                mask |= EPOLLRDHUP;
 
        /* readable? */
-       if (!skb_queue_empty(&sk->sk_receive_queue) ||
+       if (!skb_queue_empty_lockless(&sk->sk_receive_queue) ||
                (sk->sk_shutdown & RCV_SHUTDOWN))
                mask |= EPOLLIN | EPOLLRDNORM;
 
index 37c1040bcb9c127b8ccee1cfebf31b9562c58728..4d8ba701e15d87abcfe87d8fa9540c808b32522d 100644 (file)
@@ -580,6 +580,7 @@ static int j1939_sk_release(struct socket *sock)
                j1939_netdev_stop(priv);
        }
 
+       kfree(jsk->filters);
        sock_orphan(sk);
        sock->sk = NULL;
 
@@ -909,8 +910,10 @@ void j1939_sk_errqueue(struct j1939_session *session,
        memset(serr, 0, sizeof(*serr));
        switch (type) {
        case J1939_ERRQUEUE_ACK:
-               if (!(sk->sk_tsflags & SOF_TIMESTAMPING_TX_ACK))
+               if (!(sk->sk_tsflags & SOF_TIMESTAMPING_TX_ACK)) {
+                       kfree_skb(skb);
                        return;
+               }
 
                serr->ee.ee_errno = ENOMSG;
                serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING;
@@ -918,8 +921,10 @@ void j1939_sk_errqueue(struct j1939_session *session,
                state = "ACK";
                break;
        case J1939_ERRQUEUE_SCHED:
-               if (!(sk->sk_tsflags & SOF_TIMESTAMPING_TX_SCHED))
+               if (!(sk->sk_tsflags & SOF_TIMESTAMPING_TX_SCHED)) {
+                       kfree_skb(skb);
                        return;
+               }
 
                serr->ee.ee_errno = ENOMSG;
                serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING;
index fe000ea757eac9013dfb4322e1f2cc06dadfcb07..e5f1a56994c604e2c7829fc3cefdfb74ff2ba796 100644 (file)
@@ -1273,9 +1273,27 @@ j1939_xtp_rx_abort(struct j1939_priv *priv, struct sk_buff *skb,
 static void
 j1939_xtp_rx_eoma_one(struct j1939_session *session, struct sk_buff *skb)
 {
+       struct j1939_sk_buff_cb *skcb = j1939_skb_to_cb(skb);
+       const u8 *dat;
+       int len;
+
        if (j1939_xtp_rx_cmd_bad_pgn(session, skb))
                return;
 
+       dat = skb->data;
+
+       if (skcb->addr.type == J1939_ETP)
+               len = j1939_etp_ctl_to_size(dat);
+       else
+               len = j1939_tp_ctl_to_size(dat);
+
+       if (session->total_message_size != len) {
+               netdev_warn_once(session->priv->ndev,
+                                "%s: 0x%p: Incorrect size. Expected: %i; got: %i.\n",
+                                __func__, session, session->total_message_size,
+                                len);
+       }
+
        netdev_dbg(session->priv->ndev, "%s: 0x%p\n", __func__, session);
 
        session->pkt.tx_acked = session->pkt.total;
@@ -1432,7 +1450,7 @@ j1939_session *j1939_session_fresh_new(struct j1939_priv *priv,
        skcb = j1939_skb_to_cb(skb);
        memcpy(skcb, rel_skcb, sizeof(*skcb));
 
-       session = j1939_session_new(priv, skb, skb->len);
+       session = j1939_session_new(priv, skb, size);
        if (!session) {
                kfree_skb(skb);
                return NULL;
index c210fc116103d9915a2a4abc5225e0eb75825b0b..da3c24ed129cd64db8bdb1916afa552a47c1a5a3 100644 (file)
@@ -97,7 +97,7 @@ int __skb_wait_for_more_packets(struct sock *sk, int *err, long *timeo_p,
        if (error)
                goto out_err;
 
-       if (sk->sk_receive_queue.prev != skb)
+       if (READ_ONCE(sk->sk_receive_queue.prev) != skb)
                goto out;
 
        /* Socket shut down? */
@@ -278,7 +278,7 @@ struct sk_buff *__skb_try_recv_datagram(struct sock *sk, unsigned int flags,
                        break;
 
                sk_busy_loop(sk, flags & MSG_DONTWAIT);
-       } while (sk->sk_receive_queue.prev != *last);
+       } while (READ_ONCE(sk->sk_receive_queue.prev) != *last);
 
        error = -EAGAIN;
 
@@ -767,7 +767,7 @@ __poll_t datagram_poll(struct file *file, struct socket *sock,
        mask = 0;
 
        /* exceptional events? */
-       if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
+       if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue))
                mask |= EPOLLERR |
                        (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0);
 
@@ -777,7 +777,7 @@ __poll_t datagram_poll(struct file *file, struct socket *sock,
                mask |= EPOLLHUP;
 
        /* readable? */
-       if (!skb_queue_empty(&sk->sk_receive_queue))
+       if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
                mask |= EPOLLIN | EPOLLRDNORM;
 
        /* Connection-based need to check for termination and startup */
index bf3ed413abafe121d8c20ea4ca023ea770c111cc..99ac84ff398f42ff171d5882991724f2f4df11a4 100644 (file)
 #include "net-sysfs.h"
 
 #define MAX_GRO_SKBS 8
+#define MAX_NEST_DEV 8
 
 /* This should be increased if a protocol with a bigger head is added. */
 #define GRO_MAX_HEAD (MAX_HEADER + 128)
@@ -276,88 +277,6 @@ static RAW_NOTIFIER_HEAD(netdev_chain);
 DEFINE_PER_CPU_ALIGNED(struct softnet_data, softnet_data);
 EXPORT_PER_CPU_SYMBOL(softnet_data);
 
-#ifdef CONFIG_LOCKDEP
-/*
- * register_netdevice() inits txq->_xmit_lock and sets lockdep class
- * according to dev->type
- */
-static const unsigned short netdev_lock_type[] = {
-        ARPHRD_NETROM, ARPHRD_ETHER, ARPHRD_EETHER, ARPHRD_AX25,
-        ARPHRD_PRONET, ARPHRD_CHAOS, ARPHRD_IEEE802, ARPHRD_ARCNET,
-        ARPHRD_APPLETLK, ARPHRD_DLCI, ARPHRD_ATM, ARPHRD_METRICOM,
-        ARPHRD_IEEE1394, ARPHRD_EUI64, ARPHRD_INFINIBAND, ARPHRD_SLIP,
-        ARPHRD_CSLIP, ARPHRD_SLIP6, ARPHRD_CSLIP6, ARPHRD_RSRVD,
-        ARPHRD_ADAPT, ARPHRD_ROSE, ARPHRD_X25, ARPHRD_HWX25,
-        ARPHRD_PPP, ARPHRD_CISCO, ARPHRD_LAPB, ARPHRD_DDCMP,
-        ARPHRD_RAWHDLC, ARPHRD_TUNNEL, ARPHRD_TUNNEL6, ARPHRD_FRAD,
-        ARPHRD_SKIP, ARPHRD_LOOPBACK, ARPHRD_LOCALTLK, ARPHRD_FDDI,
-        ARPHRD_BIF, ARPHRD_SIT, ARPHRD_IPDDP, ARPHRD_IPGRE,
-        ARPHRD_PIMREG, ARPHRD_HIPPI, ARPHRD_ASH, ARPHRD_ECONET,
-        ARPHRD_IRDA, ARPHRD_FCPP, ARPHRD_FCAL, ARPHRD_FCPL,
-        ARPHRD_FCFABRIC, ARPHRD_IEEE80211, ARPHRD_IEEE80211_PRISM,
-        ARPHRD_IEEE80211_RADIOTAP, ARPHRD_PHONET, ARPHRD_PHONET_PIPE,
-        ARPHRD_IEEE802154, ARPHRD_VOID, ARPHRD_NONE};
-
-static const char *const netdev_lock_name[] = {
-       "_xmit_NETROM", "_xmit_ETHER", "_xmit_EETHER", "_xmit_AX25",
-       "_xmit_PRONET", "_xmit_CHAOS", "_xmit_IEEE802", "_xmit_ARCNET",
-       "_xmit_APPLETLK", "_xmit_DLCI", "_xmit_ATM", "_xmit_METRICOM",
-       "_xmit_IEEE1394", "_xmit_EUI64", "_xmit_INFINIBAND", "_xmit_SLIP",
-       "_xmit_CSLIP", "_xmit_SLIP6", "_xmit_CSLIP6", "_xmit_RSRVD",
-       "_xmit_ADAPT", "_xmit_ROSE", "_xmit_X25", "_xmit_HWX25",
-       "_xmit_PPP", "_xmit_CISCO", "_xmit_LAPB", "_xmit_DDCMP",
-       "_xmit_RAWHDLC", "_xmit_TUNNEL", "_xmit_TUNNEL6", "_xmit_FRAD",
-       "_xmit_SKIP", "_xmit_LOOPBACK", "_xmit_LOCALTLK", "_xmit_FDDI",
-       "_xmit_BIF", "_xmit_SIT", "_xmit_IPDDP", "_xmit_IPGRE",
-       "_xmit_PIMREG", "_xmit_HIPPI", "_xmit_ASH", "_xmit_ECONET",
-       "_xmit_IRDA", "_xmit_FCPP", "_xmit_FCAL", "_xmit_FCPL",
-       "_xmit_FCFABRIC", "_xmit_IEEE80211", "_xmit_IEEE80211_PRISM",
-       "_xmit_IEEE80211_RADIOTAP", "_xmit_PHONET", "_xmit_PHONET_PIPE",
-       "_xmit_IEEE802154", "_xmit_VOID", "_xmit_NONE"};
-
-static struct lock_class_key netdev_xmit_lock_key[ARRAY_SIZE(netdev_lock_type)];
-static struct lock_class_key netdev_addr_lock_key[ARRAY_SIZE(netdev_lock_type)];
-
-static inline unsigned short netdev_lock_pos(unsigned short dev_type)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(netdev_lock_type); i++)
-               if (netdev_lock_type[i] == dev_type)
-                       return i;
-       /* the last key is used by default */
-       return ARRAY_SIZE(netdev_lock_type) - 1;
-}
-
-static inline void netdev_set_xmit_lockdep_class(spinlock_t *lock,
-                                                unsigned short dev_type)
-{
-       int i;
-
-       i = netdev_lock_pos(dev_type);
-       lockdep_set_class_and_name(lock, &netdev_xmit_lock_key[i],
-                                  netdev_lock_name[i]);
-}
-
-static inline void netdev_set_addr_lockdep_class(struct net_device *dev)
-{
-       int i;
-
-       i = netdev_lock_pos(dev->type);
-       lockdep_set_class_and_name(&dev->addr_list_lock,
-                                  &netdev_addr_lock_key[i],
-                                  netdev_lock_name[i]);
-}
-#else
-static inline void netdev_set_xmit_lockdep_class(spinlock_t *lock,
-                                                unsigned short dev_type)
-{
-}
-static inline void netdev_set_addr_lockdep_class(struct net_device *dev)
-{
-}
-#endif
-
 /*******************************************************************************
  *
  *             Protocol management and registration routines
@@ -6489,6 +6408,9 @@ struct netdev_adjacent {
        /* upper master flag, there can only be one master device per list */
        bool master;
 
+       /* lookup ignore flag */
+       bool ignore;
+
        /* counter for the number of times this device was added to us */
        u16 ref_nr;
 
@@ -6511,7 +6433,7 @@ 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, void *data)
 {
        struct net_device *dev = data;
 
@@ -6532,7 +6454,7 @@ bool netdev_has_upper_dev(struct net_device *dev,
 {
        ASSERT_RTNL();
 
-       return netdev_walk_all_upper_dev_rcu(dev, __netdev_has_upper_dev,
+       return netdev_walk_all_upper_dev_rcu(dev, ____netdev_has_upper_dev,
                                             upper_dev);
 }
 EXPORT_SYMBOL(netdev_has_upper_dev);
@@ -6550,7 +6472,7 @@ EXPORT_SYMBOL(netdev_has_upper_dev);
 bool netdev_has_upper_dev_all_rcu(struct net_device *dev,
                                  struct net_device *upper_dev)
 {
-       return !!netdev_walk_all_upper_dev_rcu(dev, __netdev_has_upper_dev,
+       return !!netdev_walk_all_upper_dev_rcu(dev, ____netdev_has_upper_dev,
                                               upper_dev);
 }
 EXPORT_SYMBOL(netdev_has_upper_dev_all_rcu);
@@ -6594,6 +6516,22 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev)
 }
 EXPORT_SYMBOL(netdev_master_upper_dev_get);
 
+static struct net_device *__netdev_master_upper_dev_get(struct net_device *dev)
+{
+       struct netdev_adjacent *upper;
+
+       ASSERT_RTNL();
+
+       if (list_empty(&dev->adj_list.upper))
+               return NULL;
+
+       upper = list_first_entry(&dev->adj_list.upper,
+                                struct netdev_adjacent, list);
+       if (likely(upper->master) && !upper->ignore)
+               return upper->dev;
+       return NULL;
+}
+
 /**
  * netdev_has_any_lower_dev - Check if device is linked to some device
  * @dev: device
@@ -6644,6 +6582,23 @@ struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
 }
 EXPORT_SYMBOL(netdev_upper_get_next_dev_rcu);
 
+static struct net_device *__netdev_next_upper_dev(struct net_device *dev,
+                                                 struct list_head **iter,
+                                                 bool *ignore)
+{
+       struct netdev_adjacent *upper;
+
+       upper = list_entry((*iter)->next, struct netdev_adjacent, list);
+
+       if (&upper->list == &dev->adj_list.upper)
+               return NULL;
+
+       *iter = &upper->list;
+       *ignore = upper->ignore;
+
+       return upper->dev;
+}
+
 static struct net_device *netdev_next_upper_dev_rcu(struct net_device *dev,
                                                    struct list_head **iter)
 {
@@ -6661,34 +6616,111 @@ static struct net_device *netdev_next_upper_dev_rcu(struct net_device *dev,
        return upper->dev;
 }
 
+static int __netdev_walk_all_upper_dev(struct net_device *dev,
+                                      int (*fn)(struct net_device *dev,
+                                                void *data),
+                                      void *data)
+{
+       struct net_device *udev, *next, *now, *dev_stack[MAX_NEST_DEV + 1];
+       struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1];
+       int ret, cur = 0;
+       bool ignore;
+
+       now = dev;
+       iter = &dev->adj_list.upper;
+
+       while (1) {
+               if (now != dev) {
+                       ret = fn(now, data);
+                       if (ret)
+                               return ret;
+               }
+
+               next = NULL;
+               while (1) {
+                       udev = __netdev_next_upper_dev(now, &iter, &ignore);
+                       if (!udev)
+                               break;
+                       if (ignore)
+                               continue;
+
+                       next = udev;
+                       niter = &udev->adj_list.upper;
+                       dev_stack[cur] = now;
+                       iter_stack[cur++] = iter;
+                       break;
+               }
+
+               if (!next) {
+                       if (!cur)
+                               return 0;
+                       next = dev_stack[--cur];
+                       niter = iter_stack[cur];
+               }
+
+               now = next;
+               iter = niter;
+       }
+
+       return 0;
+}
+
 int netdev_walk_all_upper_dev_rcu(struct net_device *dev,
                                  int (*fn)(struct net_device *dev,
                                            void *data),
                                  void *data)
 {
-       struct net_device *udev;
-       struct list_head *iter;
-       int ret;
+       struct net_device *udev, *next, *now, *dev_stack[MAX_NEST_DEV + 1];
+       struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1];
+       int ret, cur = 0;
 
-       for (iter = &dev->adj_list.upper,
-            udev = netdev_next_upper_dev_rcu(dev, &iter);
-            udev;
-            udev = netdev_next_upper_dev_rcu(dev, &iter)) {
-               /* first is the upper device itself */
-               ret = fn(udev, data);
-               if (ret)
-                       return ret;
+       now = dev;
+       iter = &dev->adj_list.upper;
 
-               /* then look at all of its upper devices */
-               ret = netdev_walk_all_upper_dev_rcu(udev, fn, data);
-               if (ret)
-                       return ret;
+       while (1) {
+               if (now != dev) {
+                       ret = fn(now, data);
+                       if (ret)
+                               return ret;
+               }
+
+               next = NULL;
+               while (1) {
+                       udev = netdev_next_upper_dev_rcu(now, &iter);
+                       if (!udev)
+                               break;
+
+                       next = udev;
+                       niter = &udev->adj_list.upper;
+                       dev_stack[cur] = now;
+                       iter_stack[cur++] = iter;
+                       break;
+               }
+
+               if (!next) {
+                       if (!cur)
+                               return 0;
+                       next = dev_stack[--cur];
+                       niter = iter_stack[cur];
+               }
+
+               now = next;
+               iter = niter;
        }
 
        return 0;
 }
 EXPORT_SYMBOL_GPL(netdev_walk_all_upper_dev_rcu);
 
+static bool __netdev_has_upper_dev(struct net_device *dev,
+                                  struct net_device *upper_dev)
+{
+       ASSERT_RTNL();
+
+       return __netdev_walk_all_upper_dev(dev, ____netdev_has_upper_dev,
+                                          upper_dev);
+}
+
 /**
  * netdev_lower_get_next_private - Get the next ->private from the
  *                                lower neighbour list
@@ -6785,34 +6817,119 @@ static struct net_device *netdev_next_lower_dev(struct net_device *dev,
        return lower->dev;
 }
 
+static struct net_device *__netdev_next_lower_dev(struct net_device *dev,
+                                                 struct list_head **iter,
+                                                 bool *ignore)
+{
+       struct netdev_adjacent *lower;
+
+       lower = list_entry((*iter)->next, struct netdev_adjacent, list);
+
+       if (&lower->list == &dev->adj_list.lower)
+               return NULL;
+
+       *iter = &lower->list;
+       *ignore = lower->ignore;
+
+       return lower->dev;
+}
+
 int netdev_walk_all_lower_dev(struct net_device *dev,
                              int (*fn)(struct net_device *dev,
                                        void *data),
                              void *data)
 {
-       struct net_device *ldev;
-       struct list_head *iter;
-       int ret;
+       struct net_device *ldev, *next, *now, *dev_stack[MAX_NEST_DEV + 1];
+       struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1];
+       int ret, cur = 0;
 
-       for (iter = &dev->adj_list.lower,
-            ldev = netdev_next_lower_dev(dev, &iter);
-            ldev;
-            ldev = netdev_next_lower_dev(dev, &iter)) {
-               /* first is the lower device itself */
-               ret = fn(ldev, data);
-               if (ret)
-                       return ret;
+       now = dev;
+       iter = &dev->adj_list.lower;
 
-               /* then look at all of its lower devices */
-               ret = netdev_walk_all_lower_dev(ldev, fn, data);
-               if (ret)
-                       return ret;
+       while (1) {
+               if (now != dev) {
+                       ret = fn(now, data);
+                       if (ret)
+                               return ret;
+               }
+
+               next = NULL;
+               while (1) {
+                       ldev = netdev_next_lower_dev(now, &iter);
+                       if (!ldev)
+                               break;
+
+                       next = ldev;
+                       niter = &ldev->adj_list.lower;
+                       dev_stack[cur] = now;
+                       iter_stack[cur++] = iter;
+                       break;
+               }
+
+               if (!next) {
+                       if (!cur)
+                               return 0;
+                       next = dev_stack[--cur];
+                       niter = iter_stack[cur];
+               }
+
+               now = next;
+               iter = niter;
        }
 
        return 0;
 }
 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 net_device *ldev, *next, *now, *dev_stack[MAX_NEST_DEV + 1];
+       struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1];
+       int ret, cur = 0;
+       bool ignore;
+
+       now = dev;
+       iter = &dev->adj_list.lower;
+
+       while (1) {
+               if (now != dev) {
+                       ret = fn(now, data);
+                       if (ret)
+                               return ret;
+               }
+
+               next = NULL;
+               while (1) {
+                       ldev = __netdev_next_lower_dev(now, &iter, &ignore);
+                       if (!ldev)
+                               break;
+                       if (ignore)
+                               continue;
+
+                       next = ldev;
+                       niter = &ldev->adj_list.lower;
+                       dev_stack[cur] = now;
+                       iter_stack[cur++] = iter;
+                       break;
+               }
+
+               if (!next) {
+                       if (!cur)
+                               return 0;
+                       next = dev_stack[--cur];
+                       niter = iter_stack[cur];
+               }
+
+               now = next;
+               iter = niter;
+       }
+
+       return 0;
+}
+
 static struct net_device *netdev_next_lower_dev_rcu(struct net_device *dev,
                                                    struct list_head **iter)
 {
@@ -6827,28 +6944,99 @@ static struct net_device *netdev_next_lower_dev_rcu(struct net_device *dev,
        return lower->dev;
 }
 
-int netdev_walk_all_lower_dev_rcu(struct net_device *dev,
-                                 int (*fn)(struct net_device *dev,
-                                           void *data),
-                                 void *data)
+static u8 __netdev_upper_depth(struct net_device *dev)
+{
+       struct net_device *udev;
+       struct list_head *iter;
+       u8 max_depth = 0;
+       bool ignore;
+
+       for (iter = &dev->adj_list.upper,
+            udev = __netdev_next_upper_dev(dev, &iter, &ignore);
+            udev;
+            udev = __netdev_next_upper_dev(dev, &iter, &ignore)) {
+               if (ignore)
+                       continue;
+               if (max_depth < udev->upper_level)
+                       max_depth = udev->upper_level;
+       }
+
+       return max_depth;
+}
+
+static u8 __netdev_lower_depth(struct net_device *dev)
 {
        struct net_device *ldev;
        struct list_head *iter;
-       int ret;
+       u8 max_depth = 0;
+       bool ignore;
 
        for (iter = &dev->adj_list.lower,
-            ldev = netdev_next_lower_dev_rcu(dev, &iter);
+            ldev = __netdev_next_lower_dev(dev, &iter, &ignore);
             ldev;
-            ldev = netdev_next_lower_dev_rcu(dev, &iter)) {
-               /* first is the lower device itself */
-               ret = fn(ldev, data);
-               if (ret)
-                       return ret;
+            ldev = __netdev_next_lower_dev(dev, &iter, &ignore)) {
+               if (ignore)
+                       continue;
+               if (max_depth < ldev->lower_level)
+                       max_depth = ldev->lower_level;
+       }
 
-               /* then look at all of its lower devices */
-               ret = netdev_walk_all_lower_dev_rcu(ldev, fn, data);
-               if (ret)
-                       return ret;
+       return max_depth;
+}
+
+static int __netdev_update_upper_level(struct net_device *dev, void *data)
+{
+       dev->upper_level = __netdev_upper_depth(dev) + 1;
+       return 0;
+}
+
+static int __netdev_update_lower_level(struct net_device *dev, void *data)
+{
+       dev->lower_level = __netdev_lower_depth(dev) + 1;
+       return 0;
+}
+
+int netdev_walk_all_lower_dev_rcu(struct net_device *dev,
+                                 int (*fn)(struct net_device *dev,
+                                           void *data),
+                                 void *data)
+{
+       struct net_device *ldev, *next, *now, *dev_stack[MAX_NEST_DEV + 1];
+       struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1];
+       int ret, cur = 0;
+
+       now = dev;
+       iter = &dev->adj_list.lower;
+
+       while (1) {
+               if (now != dev) {
+                       ret = fn(now, data);
+                       if (ret)
+                               return ret;
+               }
+
+               next = NULL;
+               while (1) {
+                       ldev = netdev_next_lower_dev_rcu(now, &iter);
+                       if (!ldev)
+                               break;
+
+                       next = ldev;
+                       niter = &ldev->adj_list.lower;
+                       dev_stack[cur] = now;
+                       iter_stack[cur++] = iter;
+                       break;
+               }
+
+               if (!next) {
+                       if (!cur)
+                               return 0;
+                       next = dev_stack[--cur];
+                       niter = iter_stack[cur];
+               }
+
+               now = next;
+               iter = niter;
        }
 
        return 0;
@@ -6952,6 +7140,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
        adj->master = master;
        adj->ref_nr = 1;
        adj->private = private;
+       adj->ignore = false;
        dev_hold(adj_dev);
 
        pr_debug("Insert adjacency: dev %s adj_dev %s adj->ref_nr %d; dev_hold on %s\n",
@@ -7102,14 +7291,17 @@ static int __netdev_upper_dev_link(struct net_device *dev,
                return -EBUSY;
 
        /* To prevent loops, check if dev is not upper device to upper_dev. */
-       if (netdev_has_upper_dev(upper_dev, dev))
+       if (__netdev_has_upper_dev(upper_dev, dev))
                return -EBUSY;
 
+       if ((dev->lower_level + upper_dev->upper_level) > MAX_NEST_DEV)
+               return -EMLINK;
+
        if (!master) {
-               if (netdev_has_upper_dev(dev, upper_dev))
+               if (__netdev_has_upper_dev(dev, upper_dev))
                        return -EEXIST;
        } else {
-               master_dev = netdev_master_upper_dev_get(dev);
+               master_dev = __netdev_master_upper_dev_get(dev);
                if (master_dev)
                        return master_dev == upper_dev ? -EEXIST : -EBUSY;
        }
@@ -7131,6 +7323,13 @@ static int __netdev_upper_dev_link(struct net_device *dev,
        if (ret)
                goto rollback;
 
+       __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_walk_all_upper_dev(upper_dev, __netdev_update_lower_level,
+                                   NULL);
+
        return 0;
 
 rollback:
@@ -7213,9 +7412,96 @@ void netdev_upper_dev_unlink(struct net_device *dev,
 
        call_netdevice_notifiers_info(NETDEV_CHANGEUPPER,
                                      &changeupper_info.info);
+
+       __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_walk_all_upper_dev(upper_dev, __netdev_update_lower_level,
+                                   NULL);
 }
 EXPORT_SYMBOL(netdev_upper_dev_unlink);
 
+static void __netdev_adjacent_dev_set(struct net_device *upper_dev,
+                                     struct net_device *lower_dev,
+                                     bool val)
+{
+       struct netdev_adjacent *adj;
+
+       adj = __netdev_find_adj(lower_dev, &upper_dev->adj_list.lower);
+       if (adj)
+               adj->ignore = val;
+
+       adj = __netdev_find_adj(upper_dev, &lower_dev->adj_list.upper);
+       if (adj)
+               adj->ignore = val;
+}
+
+static void netdev_adjacent_dev_disable(struct net_device *upper_dev,
+                                       struct net_device *lower_dev)
+{
+       __netdev_adjacent_dev_set(upper_dev, lower_dev, true);
+}
+
+static void netdev_adjacent_dev_enable(struct net_device *upper_dev,
+                                      struct net_device *lower_dev)
+{
+       __netdev_adjacent_dev_set(upper_dev, lower_dev, false);
+}
+
+int netdev_adjacent_change_prepare(struct net_device *old_dev,
+                                  struct net_device *new_dev,
+                                  struct net_device *dev,
+                                  struct netlink_ext_ack *extack)
+{
+       int err;
+
+       if (!new_dev)
+               return 0;
+
+       if (old_dev && new_dev != old_dev)
+               netdev_adjacent_dev_disable(dev, old_dev);
+
+       err = netdev_upper_dev_link(new_dev, dev, extack);
+       if (err) {
+               if (old_dev && new_dev != old_dev)
+                       netdev_adjacent_dev_enable(dev, old_dev);
+               return err;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(netdev_adjacent_change_prepare);
+
+void netdev_adjacent_change_commit(struct net_device *old_dev,
+                                  struct net_device *new_dev,
+                                  struct net_device *dev)
+{
+       if (!new_dev || !old_dev)
+               return;
+
+       if (new_dev == old_dev)
+               return;
+
+       netdev_adjacent_dev_enable(dev, old_dev);
+       netdev_upper_dev_unlink(old_dev, dev);
+}
+EXPORT_SYMBOL(netdev_adjacent_change_commit);
+
+void netdev_adjacent_change_abort(struct net_device *old_dev,
+                                 struct net_device *new_dev,
+                                 struct net_device *dev)
+{
+       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);
+}
+EXPORT_SYMBOL(netdev_adjacent_change_abort);
+
 /**
  * netdev_bonding_info_change - Dispatch event about slave change
  * @dev: device
@@ -7329,25 +7615,6 @@ void *netdev_lower_dev_get_private(struct net_device *dev,
 EXPORT_SYMBOL(netdev_lower_dev_get_private);
 
 
-int dev_get_nest_level(struct net_device *dev)
-{
-       struct net_device *lower = NULL;
-       struct list_head *iter;
-       int max_nest = -1;
-       int nest;
-
-       ASSERT_RTNL();
-
-       netdev_for_each_lower_dev(dev, lower, iter) {
-               nest = dev_get_nest_level(lower);
-               if (max_nest < nest)
-                       max_nest = nest;
-       }
-
-       return max_nest + 1;
-}
-EXPORT_SYMBOL(dev_get_nest_level);
-
 /**
  * netdev_lower_change - Dispatch event about lower device state change
  * @lower_dev: device
@@ -8154,7 +8421,8 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
                        return -EINVAL;
                }
 
-               if (prog->aux->id == prog_id) {
+               /* prog->aux->id may be 0 for orphaned device-bound progs */
+               if (prog->aux->id && prog->aux->id == prog_id) {
                        bpf_prog_put(prog);
                        return 0;
                }
@@ -8619,7 +8887,7 @@ static void netdev_init_one_queue(struct net_device *dev,
 {
        /* Initialize queue lock */
        spin_lock_init(&queue->_xmit_lock);
-       netdev_set_xmit_lockdep_class(&queue->_xmit_lock, dev->type);
+       lockdep_set_class(&queue->_xmit_lock, &dev->qdisc_xmit_lock_key);
        queue->xmit_lock_owner = -1;
        netdev_queue_numa_node_write(queue, NUMA_NO_NODE);
        queue->dev = dev;
@@ -8666,6 +8934,43 @@ void netif_tx_stop_all_queues(struct net_device *dev)
 }
 EXPORT_SYMBOL(netif_tx_stop_all_queues);
 
+static void netdev_register_lockdep_key(struct net_device *dev)
+{
+       lockdep_register_key(&dev->qdisc_tx_busylock_key);
+       lockdep_register_key(&dev->qdisc_running_key);
+       lockdep_register_key(&dev->qdisc_xmit_lock_key);
+       lockdep_register_key(&dev->addr_list_lock_key);
+}
+
+static void netdev_unregister_lockdep_key(struct net_device *dev)
+{
+       lockdep_unregister_key(&dev->qdisc_tx_busylock_key);
+       lockdep_unregister_key(&dev->qdisc_running_key);
+       lockdep_unregister_key(&dev->qdisc_xmit_lock_key);
+       lockdep_unregister_key(&dev->addr_list_lock_key);
+}
+
+void netdev_update_lockdep_key(struct net_device *dev)
+{
+       struct netdev_queue *queue;
+       int i;
+
+       lockdep_unregister_key(&dev->qdisc_xmit_lock_key);
+       lockdep_unregister_key(&dev->addr_list_lock_key);
+
+       lockdep_register_key(&dev->qdisc_xmit_lock_key);
+       lockdep_register_key(&dev->addr_list_lock_key);
+
+       lockdep_set_class(&dev->addr_list_lock, &dev->addr_list_lock_key);
+       for (i = 0; i < dev->num_tx_queues; i++) {
+               queue = netdev_get_tx_queue(dev, i);
+
+               lockdep_set_class(&queue->_xmit_lock,
+                                 &dev->qdisc_xmit_lock_key);
+       }
+}
+EXPORT_SYMBOL(netdev_update_lockdep_key);
+
 /**
  *     register_netdevice      - register a network device
  *     @dev: device to register
@@ -8700,7 +9005,7 @@ int register_netdevice(struct net_device *dev)
        BUG_ON(!net);
 
        spin_lock_init(&dev->addr_list_lock);
-       netdev_set_addr_lockdep_class(dev);
+       lockdep_set_class(&dev->addr_list_lock, &dev->addr_list_lock_key);
 
        ret = dev_get_valid_name(net, dev, dev->name);
        if (ret < 0)
@@ -9210,8 +9515,12 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
 
        dev_net_set(dev, &init_net);
 
+       netdev_register_lockdep_key(dev);
+
        dev->gso_max_size = GSO_MAX_SIZE;
        dev->gso_max_segs = GSO_MAX_SEGS;
+       dev->upper_level = 1;
+       dev->lower_level = 1;
 
        INIT_LIST_HEAD(&dev->napi_list);
        INIT_LIST_HEAD(&dev->unreg_list);
@@ -9292,6 +9601,8 @@ void free_netdev(struct net_device *dev)
        free_percpu(dev->pcpu_refcnt);
        dev->pcpu_refcnt = NULL;
 
+       netdev_unregister_lockdep_key(dev);
+
        /*  Compatibility with error handling in drivers */
        if (dev->reg_state == NETREG_UNINITIALIZED) {
                netdev_freemem(dev);
@@ -9460,7 +9771,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
        call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
        rcu_barrier();
 
-       new_nsid = peernet2id_alloc(dev_net(dev), net);
+       new_nsid = peernet2id_alloc(dev_net(dev), net, GFP_KERNEL);
        /* If there is an ifindex conflict assign a new one */
        if (__dev_get_by_index(net, dev->ifindex))
                new_ifindex = dev_new_index(net);
index 6393ba930097b49b26a70cf01b657da08514f552..2f949b5a1eb9cd9a65e0c0a6d089032a92e100e2 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);
@@ -691,7 +691,7 @@ void dev_uc_unsync(struct net_device *to, struct net_device *from)
                return;
 
        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);
@@ -858,7 +858,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);
@@ -888,7 +888,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);
@@ -912,7 +912,7 @@ void dev_mc_unsync(struct net_device *to, struct net_device *from)
                return;
 
        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 c763106c73fc5d660e8489da0f0823e0536fd96e..cd9bc67381b221aae31695f15dec0784973c5da9 100644 (file)
@@ -1396,11 +1396,13 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr)
 
 static int ethtool_get_wol(struct net_device *dev, char __user *useraddr)
 {
-       struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
+       struct ethtool_wolinfo wol;
 
        if (!dev->ethtool_ops->get_wol)
                return -EOPNOTSUPP;
 
+       memset(&wol, 0, sizeof(struct ethtool_wolinfo));
+       wol.cmd = ETHTOOL_GWOL;
        dev->ethtool_ops->get_wol(dev, &wol);
 
        if (copy_to_user(useraddr, &wol, sizeof(wol)))
index 7c09d87d3269e4d01fd895c595a3a6e67d350685..68eda10d0680749ef07372951debab913449e661 100644 (file)
@@ -1350,30 +1350,21 @@ out_bad:
 }
 EXPORT_SYMBOL(__skb_flow_dissect);
 
-static u32 hashrnd __read_mostly;
+static siphash_key_t hashrnd __read_mostly;
 static __always_inline void __flow_hash_secret_init(void)
 {
        net_get_random_once(&hashrnd, sizeof(hashrnd));
 }
 
-static __always_inline u32 __flow_hash_words(const u32 *words, u32 length,
-                                            u32 keyval)
+static const void *flow_keys_hash_start(const struct flow_keys *flow)
 {
-       return jhash2(words, length, keyval);
-}
-
-static inline const u32 *flow_keys_hash_start(const struct flow_keys *flow)
-{
-       const void *p = flow;
-
-       BUILD_BUG_ON(FLOW_KEYS_HASH_OFFSET % sizeof(u32));
-       return (const u32 *)(p + FLOW_KEYS_HASH_OFFSET);
+       BUILD_BUG_ON(FLOW_KEYS_HASH_OFFSET % SIPHASH_ALIGNMENT);
+       return &flow->FLOW_KEYS_HASH_START_FIELD;
 }
 
 static inline size_t flow_keys_hash_length(const struct flow_keys *flow)
 {
        size_t diff = FLOW_KEYS_HASH_OFFSET + sizeof(flow->addrs);
-       BUILD_BUG_ON((sizeof(*flow) - FLOW_KEYS_HASH_OFFSET) % sizeof(u32));
        BUILD_BUG_ON(offsetof(typeof(*flow), addrs) !=
                     sizeof(*flow) - sizeof(flow->addrs));
 
@@ -1388,7 +1379,7 @@ static inline size_t flow_keys_hash_length(const struct flow_keys *flow)
                diff -= sizeof(flow->addrs.tipckey);
                break;
        }
-       return (sizeof(*flow) - diff) / sizeof(u32);
+       return sizeof(*flow) - diff;
 }
 
 __be32 flow_get_u32_src(const struct flow_keys *flow)
@@ -1454,14 +1445,15 @@ static inline void __flow_hash_consistentify(struct flow_keys *keys)
        }
 }
 
-static inline u32 __flow_hash_from_keys(struct flow_keys *keys, u32 keyval)
+static inline u32 __flow_hash_from_keys(struct flow_keys *keys,
+                                       const siphash_key_t *keyval)
 {
        u32 hash;
 
        __flow_hash_consistentify(keys);
 
-       hash = __flow_hash_words(flow_keys_hash_start(keys),
-                                flow_keys_hash_length(keys), keyval);
+       hash = siphash(flow_keys_hash_start(keys),
+                      flow_keys_hash_length(keys), keyval);
        if (!hash)
                hash = 1;
 
@@ -1471,12 +1463,13 @@ static inline u32 __flow_hash_from_keys(struct flow_keys *keys, u32 keyval)
 u32 flow_hash_from_keys(struct flow_keys *keys)
 {
        __flow_hash_secret_init();
-       return __flow_hash_from_keys(keys, hashrnd);
+       return __flow_hash_from_keys(keys, &hashrnd);
 }
 EXPORT_SYMBOL(flow_hash_from_keys);
 
 static inline u32 ___skb_get_hash(const struct sk_buff *skb,
-                                 struct flow_keys *keys, u32 keyval)
+                                 struct flow_keys *keys,
+                                 const siphash_key_t *keyval)
 {
        skb_flow_dissect_flow_keys(skb, keys,
                                   FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL);
@@ -1524,7 +1517,7 @@ u32 __skb_get_hash_symmetric(const struct sk_buff *skb)
                           &keys, NULL, 0, 0, 0,
                           FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL);
 
-       return __flow_hash_from_keys(&keys, hashrnd);
+       return __flow_hash_from_keys(&keys, &hashrnd);
 }
 EXPORT_SYMBOL_GPL(__skb_get_hash_symmetric);
 
@@ -1544,13 +1537,14 @@ void __skb_get_hash(struct sk_buff *skb)
 
        __flow_hash_secret_init();
 
-       hash = ___skb_get_hash(skb, &keys, hashrnd);
+       hash = ___skb_get_hash(skb, &keys, &hashrnd);
 
        __skb_set_sw_hash(skb, hash, flow_keys_have_l4(&keys));
 }
 EXPORT_SYMBOL(__skb_get_hash);
 
-__u32 skb_get_hash_perturb(const struct sk_buff *skb, u32 perturb)
+__u32 skb_get_hash_perturb(const struct sk_buff *skb,
+                          const siphash_key_t *perturb)
 {
        struct flow_keys keys;
 
index f93785e5833c1f82eed0176e3f939b32216dbaab..74cfb8b5ab3306485385e3e5682350fe9a0709dc 100644 (file)
@@ -88,11 +88,16 @@ static int bpf_lwt_input_reroute(struct sk_buff *skb)
        int err = -EINVAL;
 
        if (skb->protocol == htons(ETH_P_IP)) {
+               struct net_device *dev = skb_dst(skb)->dev;
                struct iphdr *iph = ip_hdr(skb);
 
+               dev_hold(dev);
+               skb_dst_drop(skb);
                err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
-                                          iph->tos, skb_dst(skb)->dev);
+                                          iph->tos, dev);
+               dev_put(dev);
        } else if (skb->protocol == htons(ETH_P_IPV6)) {
+               skb_dst_drop(skb);
                err = ipv6_stub->ipv6_route_input(skb);
        } else {
                err = -EAFNOSUPPORT;
index 6d3e4821b02d8ad231f81e35947902be4b3e010e..39402840025e18682da44f40c509b265f9743fd1 100644 (file)
@@ -246,11 +246,11 @@ static int __peernet2id(struct net *net, struct net *peer)
 }
 
 static void rtnl_net_notifyid(struct net *net, int cmd, int id, u32 portid,
-                             struct nlmsghdr *nlh);
+                             struct nlmsghdr *nlh, gfp_t gfp);
 /* This function returns the id of a peer netns. If no id is assigned, one will
  * be allocated and returned.
  */
-int peernet2id_alloc(struct net *net, struct net *peer)
+int peernet2id_alloc(struct net *net, struct net *peer, gfp_t gfp)
 {
        bool alloc = false, alive = false;
        int id;
@@ -269,7 +269,7 @@ int peernet2id_alloc(struct net *net, struct net *peer)
        id = __peernet2id_alloc(net, peer, &alloc);
        spin_unlock_bh(&net->nsid_lock);
        if (alloc && id >= 0)
-               rtnl_net_notifyid(net, RTM_NEWNSID, id, 0, NULL);
+               rtnl_net_notifyid(net, RTM_NEWNSID, id, 0, NULL, gfp);
        if (alive)
                put_net(peer);
        return id;
@@ -479,6 +479,7 @@ struct net *copy_net_ns(unsigned long flags,
 
        if (rv < 0) {
 put_userns:
+               key_remove_domain(net->key_domain);
                put_user_ns(user_ns);
                net_drop_ns(net);
 dec_ucounts:
@@ -533,7 +534,8 @@ static void unhash_nsid(struct net *net, struct net *last)
                        idr_remove(&tmp->netns_ids, id);
                spin_unlock_bh(&tmp->nsid_lock);
                if (id >= 0)
-                       rtnl_net_notifyid(tmp, RTM_DELNSID, id, 0, NULL);
+                       rtnl_net_notifyid(tmp, RTM_DELNSID, id, 0, NULL,
+                                         GFP_KERNEL);
                if (tmp == last)
                        break;
        }
@@ -766,7 +768,7 @@ static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh,
        spin_unlock_bh(&net->nsid_lock);
        if (err >= 0) {
                rtnl_net_notifyid(net, RTM_NEWNSID, err, NETLINK_CB(skb).portid,
-                                 nlh);
+                                 nlh, GFP_KERNEL);
                err = 0;
        } else if (err == -ENOSPC && nsid >= 0) {
                err = -EEXIST;
@@ -1054,7 +1056,7 @@ end:
 }
 
 static void rtnl_net_notifyid(struct net *net, int cmd, int id, u32 portid,
-                             struct nlmsghdr *nlh)
+                             struct nlmsghdr *nlh, gfp_t gfp)
 {
        struct net_fill_args fillargs = {
                .portid = portid,
@@ -1065,7 +1067,7 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id, u32 portid,
        struct sk_buff *msg;
        int err = -ENOMEM;
 
-       msg = nlmsg_new(rtnl_net_get_size(), GFP_KERNEL);
+       msg = nlmsg_new(rtnl_net_get_size(), gfp);
        if (!msg)
                goto out;
 
@@ -1073,7 +1075,7 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id, u32 portid,
        if (err < 0)
                goto err_out;
 
-       rtnl_notify(msg, net, portid, RTNLGRP_NSID, nlh, 0);
+       rtnl_notify(msg, net, portid, RTNLGRP_NSID, nlh, gfp);
        return;
 
 err_out:
index 1ee6460f82756be6dd797b000c11f29826e2e710..c81cd80114d993ad1d924c3e388813474c211904 100644 (file)
@@ -1523,7 +1523,7 @@ static noinline_for_stack int nla_put_ifalias(struct sk_buff *skb,
 
 static int rtnl_fill_link_netnsid(struct sk_buff *skb,
                                  const struct net_device *dev,
-                                 struct net *src_net)
+                                 struct net *src_net, gfp_t gfp)
 {
        bool put_iflink = false;
 
@@ -1531,7 +1531,7 @@ static int rtnl_fill_link_netnsid(struct sk_buff *skb,
                struct net *link_net = dev->rtnl_link_ops->get_link_net(dev);
 
                if (!net_eq(dev_net(dev), link_net)) {
-                       int id = peernet2id_alloc(src_net, link_net);
+                       int id = peernet2id_alloc(src_net, link_net, gfp);
 
                        if (nla_put_s32(skb, IFLA_LINK_NETNSID, id))
                                return -EMSGSIZE;
@@ -1589,7 +1589,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
                            int type, u32 pid, u32 seq, u32 change,
                            unsigned int flags, u32 ext_filter_mask,
                            u32 event, int *new_nsid, int new_ifindex,
-                           int tgt_netnsid)
+                           int tgt_netnsid, gfp_t gfp)
 {
        struct ifinfomsg *ifm;
        struct nlmsghdr *nlh;
@@ -1681,7 +1681,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
                        goto nla_put_failure;
        }
 
-       if (rtnl_fill_link_netnsid(skb, dev, src_net))
+       if (rtnl_fill_link_netnsid(skb, dev, src_net, gfp))
                goto nla_put_failure;
 
        if (new_nsid &&
@@ -2001,7 +2001,7 @@ walk_entries:
                                               NETLINK_CB(cb->skb).portid,
                                               nlh->nlmsg_seq, 0, flags,
                                               ext_filter_mask, 0, NULL, 0,
-                                              netnsid);
+                                              netnsid, GFP_KERNEL);
 
                        if (err < 0) {
                                if (likely(skb->len))
@@ -2355,6 +2355,7 @@ static int do_set_master(struct net_device *dev, int ifindex,
                        err = ops->ndo_del_slave(upper_dev, dev);
                        if (err)
                                return err;
+                       netdev_update_lockdep_key(dev);
                } else {
                        return -EOPNOTSUPP;
                }
@@ -3359,7 +3360,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr *nlh,
        err = rtnl_fill_ifinfo(nskb, dev, net,
                               RTM_NEWLINK, NETLINK_CB(skb).portid,
                               nlh->nlmsg_seq, 0, 0, ext_filter_mask,
-                              0, NULL, 0, netnsid);
+                              0, NULL, 0, netnsid, GFP_KERNEL);
        if (err < 0) {
                /* -EMSGSIZE implies BUG in if_nlmsg_size */
                WARN_ON(err == -EMSGSIZE);
@@ -3471,7 +3472,7 @@ struct sk_buff *rtmsg_ifinfo_build_skb(int type, struct net_device *dev,
 
        err = rtnl_fill_ifinfo(skb, dev, dev_net(dev),
                               type, 0, 0, change, 0, 0, event,
-                              new_nsid, new_ifindex, -1);
+                              new_nsid, new_ifindex, -1, flags);
        if (err < 0) {
                /* -EMSGSIZE implies BUG in if_nlmsg_size() */
                WARN_ON(err == -EMSGSIZE);
@@ -3916,7 +3917,7 @@ static int valid_fdb_dump_strict(const struct nlmsghdr *nlh,
        ndm = nlmsg_data(nlh);
        if (ndm->ndm_pad1  || ndm->ndm_pad2  || ndm->ndm_state ||
            ndm->ndm_flags || ndm->ndm_type) {
-               NL_SET_ERR_MSG(extack, "Invalid values in header for fbd dump request");
+               NL_SET_ERR_MSG(extack, "Invalid values in header for fdb dump request");
                return -EINVAL;
        }
 
index cf390e0aa73dcd926de83f780a8d562fc741c27d..ad31e4e53d0a7186e9d2b7e5663c4c7bfa569fc3 100644 (file)
@@ -270,18 +270,28 @@ void sk_msg_trim(struct sock *sk, struct sk_msg *msg, int len)
 
        msg->sg.data[i].length -= trim;
        sk_mem_uncharge(sk, trim);
+       /* Adjust copybreak if it falls into the trimmed part of last buf */
+       if (msg->sg.curr == i && msg->sg.copybreak > msg->sg.data[i].length)
+               msg->sg.copybreak = msg->sg.data[i].length;
 out:
-       /* If we trim data before curr pointer update copybreak and current
-        * so that any future copy operations start at new copy location.
+       sk_msg_iter_var_next(i);
+       msg->sg.end = i;
+
+       /* If we trim data a full sg elem before curr pointer update
+        * copybreak and current so that any future copy operations
+        * start at new copy location.
         * However trimed data that has not yet been used in a copy op
         * does not require an update.
         */
-       if (msg->sg.curr >= i) {
+       if (!msg->sg.size) {
+               msg->sg.curr = msg->sg.start;
+               msg->sg.copybreak = 0;
+       } else if (sk_msg_iter_dist(msg->sg.start, msg->sg.curr) >=
+                  sk_msg_iter_dist(msg->sg.start, msg->sg.end)) {
+               sk_msg_iter_var_prev(i);
                msg->sg.curr = i;
                msg->sg.copybreak = msg->sg.data[i].length;
        }
-       sk_msg_iter_var_next(i);
-       msg->sg.end = i;
 }
 EXPORT_SYMBOL_GPL(sk_msg_trim);
 
index a515392ba84b67b2bf5400e0cfb7c3454fa87af8..ac78a570e43add1ce263841212b3759dbbfd8eae 100644 (file)
@@ -1127,7 +1127,7 @@ set_rcvbuf:
                break;
                }
        case SO_INCOMING_CPU:
-               sk->sk_incoming_cpu = val;
+               WRITE_ONCE(sk->sk_incoming_cpu, val);
                break;
 
        case SO_CNX_ADVICE:
@@ -1476,7 +1476,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
                break;
 
        case SO_INCOMING_CPU:
-               v.val = sk->sk_incoming_cpu;
+               v.val = READ_ONCE(sk->sk_incoming_cpu);
                break;
 
        case SO_MEMINFO:
@@ -3600,7 +3600,7 @@ bool sk_busy_loop_end(void *p, unsigned long start_time)
 {
        struct sock *sk = p;
 
-       return !skb_queue_empty(&sk->sk_receive_queue) ||
+       return !skb_queue_empty_lockless(&sk->sk_receive_queue) ||
               sk_busy_loop_timeout(sk, start_time);
 }
 EXPORT_SYMBOL(sk_busy_loop_end);
index d9b4200ed12df8ecc7ff7de26827207c5a290e37..d19557c6d04b58a3eccad3d7971522fad666157b 100644 (file)
@@ -117,7 +117,7 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
                                                    inet->inet_daddr,
                                                    inet->inet_sport,
                                                    inet->inet_dport);
-       inet->inet_id = dp->dccps_iss ^ jiffies;
+       inet->inet_id = prandom_u32();
 
        err = dccp_connect(sk);
        rt = NULL;
@@ -416,7 +416,7 @@ struct sock *dccp_v4_request_recv_sock(const struct sock *sk,
        RCU_INIT_POINTER(newinet->inet_opt, rcu_dereference(ireq->ireq_opt));
        newinet->mc_index  = inet_iif(skb);
        newinet->mc_ttl    = ip_hdr(skb)->ttl;
-       newinet->inet_id   = jiffies;
+       newinet->inet_id   = prandom_u32();
 
        if (dst == NULL && (dst = inet_csk_route_child_sock(sk, newsk, req)) == NULL)
                goto put_and_exit;
index 0ea75286abf46ad9da2e6c58d4facc91f731b8bf..3349ea81f9016fb785ec888fadf86faa4d859ed7 100644 (file)
@@ -1205,7 +1205,7 @@ static __poll_t dn_poll(struct file *file, struct socket *sock, poll_table  *wai
        struct dn_scp *scp = DN_SK(sk);
        __poll_t mask = datagram_poll(file, sock, wait);
 
-       if (!skb_queue_empty(&scp->other_receive_queue))
+       if (!skb_queue_empty_lockless(&scp->other_receive_queue))
                mask |= EPOLLRDBAND;
 
        return mask;
index a8e52c9967f4c1a9c24a5c91f143e09b6136b569..3255dfc97f865b1c2e4634d9f4a48925b7a1804a 100644 (file)
@@ -310,8 +310,6 @@ static void dsa_master_reset_mtu(struct net_device *dev)
        rtnl_unlock();
 }
 
-static struct lock_class_key dsa_master_addr_list_lock_key;
-
 int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp)
 {
        int ret;
@@ -325,9 +323,6 @@ int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp)
        wmb();
 
        dev->dsa_ptr = cpu_dp;
-       lockdep_set_class(&dev->addr_list_lock,
-                         &dsa_master_addr_list_lock_key);
-
        ret = dsa_master_ethtool_setup(dev);
        if (ret)
                return ret;
index 75d58229a4bd356a18375a4e0c9e22e9e9a64082..028e65f4b5bafc93af03820055dab72fef4f708f 100644 (file)
@@ -1341,15 +1341,6 @@ static int dsa_slave_phy_setup(struct net_device *slave_dev)
        return ret;
 }
 
-static struct lock_class_key dsa_slave_netdev_xmit_lock_key;
-static void dsa_slave_set_lockdep_class_one(struct net_device *dev,
-                                           struct netdev_queue *txq,
-                                           void *_unused)
-{
-       lockdep_set_class(&txq->_xmit_lock,
-                         &dsa_slave_netdev_xmit_lock_key);
-}
-
 int dsa_slave_suspend(struct net_device *slave_dev)
 {
        struct dsa_port *dp = dsa_slave_to_port(slave_dev);
@@ -1433,9 +1424,6 @@ int dsa_slave_create(struct dsa_port *port)
        slave_dev->max_mtu = ETH_MAX_MTU;
        SET_NETDEV_DEVTYPE(slave_dev, &dsa_type);
 
-       netdev_for_each_tx_queue(slave_dev, dsa_slave_set_lockdep_class_one,
-                                NULL);
-
        SET_NETDEV_DEV(slave_dev, port->ds->dev);
        slave_dev->dev.of_node = port->dn;
        slave_dev->vlan_features = master->vlan_features;
index 3297e7fa99458b13c40609588f187d366cf37411..c0b107cdd7153f7fbafdc546fea3511740e6933b 100644 (file)
@@ -58,13 +58,6 @@ static const struct header_ops lowpan_header_ops = {
        .create = lowpan_header_create,
 };
 
-static int lowpan_dev_init(struct net_device *ldev)
-{
-       netdev_lockdep_set_classes(ldev);
-
-       return 0;
-}
-
 static int lowpan_open(struct net_device *dev)
 {
        if (!open_count)
@@ -96,7 +89,6 @@ static int lowpan_get_iflink(const struct net_device *dev)
 }
 
 static const struct net_device_ops lowpan_netdev_ops = {
-       .ndo_init               = lowpan_dev_init,
        .ndo_start_xmit         = lowpan_xmit,
        .ndo_open               = lowpan_open,
        .ndo_stop               = lowpan_stop,
index 9a0fe0c2fa02c9707e6fc8c02529a48e84f7d680..4a8550c49202db13b17d5cf4ed1e44dd8852c212 100644 (file)
@@ -73,7 +73,7 @@ int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len
        reuseport_has_conns(sk, true);
        sk->sk_state = TCP_ESTABLISHED;
        sk_set_txhash(sk);
-       inet->inet_id = jiffies;
+       inet->inet_id = prandom_u32();
 
        sk_dst_set(sk, &rt->dst);
        err = 0;
index dde77f72e03edc8423e98c6f8a4a349aa4e306ec..71c78d223dfd32b1b95ee9e9aeffdaa95fd1a8c6 100644 (file)
@@ -1148,7 +1148,7 @@ void fib_modify_prefix_metric(struct in_ifaddr *ifa, u32 new_metric)
        if (!(dev->flags & IFF_UP) ||
            ifa->ifa_flags & (IFA_F_SECONDARY | IFA_F_NOPREFIXROUTE) ||
            ipv4_is_zeronet(prefix) ||
-           prefix == ifa->ifa_local || ifa->ifa_prefixlen == 32)
+           (prefix == ifa->ifa_local && ifa->ifa_prefixlen == 32))
                return;
 
        /* add the new */
index 0913a090b2bf4232d82b6294051d4924052f66b1..f1888c68342631cab0a1c2d23b9a465b7757df75 100644 (file)
@@ -1814,8 +1814,8 @@ int fib_sync_down_addr(struct net_device *dev, __be32 local)
        int ret = 0;
        unsigned int hash = fib_laddr_hashfn(local);
        struct hlist_head *head = &fib_info_laddrhash[hash];
+       int tb_id = l3mdev_fib_table(dev) ? : RT_TABLE_MAIN;
        struct net *net = dev_net(dev);
-       int tb_id = l3mdev_fib_table(dev);
        struct fib_info *fi;
 
        if (!fib_info_laddrhash || local == 0)
index 97824864e40d13bac71510920ae125c6a89fef1d..83fb00153018f16678e71695134f7ae4d30ee0a3 100644 (file)
@@ -240,7 +240,7 @@ static inline int compute_score(struct sock *sk, struct net *net,
                        return -1;
 
                score = sk->sk_family == PF_INET ? 2 : 1;
-               if (sk->sk_incoming_cpu == raw_smp_processor_id())
+               if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id())
                        score++;
        }
        return score;
index 52690bb3e40f9f52d533e531838e34fdebdcf3cf..10636fb6093e3cba09cfe6835077edb664e7244d 100644 (file)
@@ -509,9 +509,9 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
        key = &tun_info->key;
        if (!(tun_info->key.tun_flags & TUNNEL_ERSPAN_OPT))
                goto err_free_skb;
-       md = ip_tunnel_info_opts(tun_info);
-       if (!md)
+       if (tun_info->options_len < sizeof(*md))
                goto err_free_skb;
+       md = ip_tunnel_info_opts(tun_info);
 
        /* ERSPAN has fixed 8 byte GRE header */
        version = md->version;
index 814b9b8882a0237bffd869cb13739e03af227f30..3d8baaaf7086dba0c8fde178891734b2da7d7ec7 100644 (file)
@@ -645,11 +645,12 @@ void ip_fraglist_prepare(struct sk_buff *skb, struct ip_fraglist_iter *iter)
 EXPORT_SYMBOL(ip_fraglist_prepare);
 
 void ip_frag_init(struct sk_buff *skb, unsigned int hlen,
-                 unsigned int ll_rs, unsigned int mtu,
+                 unsigned int ll_rs, unsigned int mtu, bool DF,
                  struct ip_frag_state *state)
 {
        struct iphdr *iph = ip_hdr(skb);
 
+       state->DF = DF;
        state->hlen = hlen;
        state->ll_rs = ll_rs;
        state->mtu = mtu;
@@ -668,9 +669,6 @@ static void ip_frag_ipcb(struct sk_buff *from, struct sk_buff *to,
        /* Copy the flags to each fragment. */
        IPCB(to)->flags = IPCB(from)->flags;
 
-       if (IPCB(from)->flags & IPSKB_FRAG_PMTU)
-               state->iph->frag_off |= htons(IP_DF);
-
        /* ANK: dirty, but effective trick. Upgrade options only if
         * the segment to be fragmented was THE FIRST (otherwise,
         * options are already fixed) and make it ONCE
@@ -738,6 +736,8 @@ struct sk_buff *ip_frag_next(struct sk_buff *skb, struct ip_frag_state *state)
         */
        iph = ip_hdr(skb2);
        iph->frag_off = htons((state->offset >> 3));
+       if (state->DF)
+               iph->frag_off |= htons(IP_DF);
 
        /*
         *      Added AC : If we are fragmenting a fragment that's not the
@@ -883,7 +883,8 @@ slow_path:
         *      Fragment the datagram.
         */
 
-       ip_frag_init(skb, hlen, ll_rs, mtu, &state);
+       ip_frag_init(skb, hlen, ll_rs, mtu, IPCB(skb)->flags & IPSKB_FRAG_PMTU,
+                    &state);
 
        /*
         *      Keep copying data until we run out.
index 42187a3b82f4f6280d831c34d9ca6b7bcffc191f..d8876f0e9672718b4e02bc7aaaac30ecfd4903cb 100644 (file)
@@ -584,7 +584,7 @@ __poll_t tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
        }
        /* This barrier is coupled with smp_wmb() in tcp_reset() */
        smp_rmb();
-       if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
+       if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue))
                mask |= EPOLLERR;
 
        return mask;
@@ -1964,7 +1964,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
        if (unlikely(flags & MSG_ERRQUEUE))
                return inet_recv_error(sk, msg, len, addr_len);
 
-       if (sk_can_busy_loop(sk) && skb_queue_empty(&sk->sk_receive_queue) &&
+       if (sk_can_busy_loop(sk) && skb_queue_empty_lockless(&sk->sk_receive_queue) &&
            (sk->sk_state == TCP_ESTABLISHED))
                sk_busy_loop(sk, nonblock);
 
index 6be568334848c7841a4a09126937f71f60420103..67b2dc7a17274bd4cdadd01c45a9afdc66dc01d3 100644 (file)
@@ -303,7 +303,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
                                                 inet->inet_daddr);
        }
 
-       inet->inet_id = tp->write_seq ^ jiffies;
+       inet->inet_id = prandom_u32();
 
        if (tcp_fastopen_defer_connect(sk, &err))
                return err;
@@ -1450,7 +1450,7 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
        inet_csk(newsk)->icsk_ext_hdr_len = 0;
        if (inet_opt)
                inet_csk(newsk)->icsk_ext_hdr_len = inet_opt->opt.optlen;
-       newinet->inet_id = newtp->write_seq ^ jiffies;
+       newinet->inet_id = prandom_u32();
 
        if (!dst) {
                dst = inet_csk_route_child_sock(sk, newsk, req);
@@ -2681,7 +2681,7 @@ static int __net_init tcp_sk_init(struct net *net)
        net->ipv4.tcp_death_row.sysctl_max_tw_buckets = cnt / 2;
        net->ipv4.tcp_death_row.hashinfo = &tcp_hashinfo;
 
-       net->ipv4.sysctl_max_syn_backlog = max(128, cnt / 256);
+       net->ipv4.sysctl_max_syn_backlog = max(128, cnt / 128);
        net->ipv4.sysctl_tcp_sack = 1;
        net->ipv4.sysctl_tcp_window_scaling = 1;
        net->ipv4.sysctl_tcp_timestamps = 1;
index 14bc654b6842003b325efe268041749c6770947f..1d58ce829dcae476a7a32a6ab5fa8bb91ec8ae67 100644 (file)
@@ -388,7 +388,7 @@ static int compute_score(struct sock *sk, struct net *net,
                return -1;
        score += 4;
 
-       if (sk->sk_incoming_cpu == raw_smp_processor_id())
+       if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id())
                score++;
        return score;
 }
@@ -1316,6 +1316,20 @@ static void udp_set_dev_scratch(struct sk_buff *skb)
                scratch->_tsize_state |= UDP_SKB_IS_STATELESS;
 }
 
+static void udp_skb_csum_unnecessary_set(struct sk_buff *skb)
+{
+       /* We come here after udp_lib_checksum_complete() returned 0.
+        * This means that __skb_checksum_complete() might have
+        * set skb->csum_valid to 1.
+        * On 64bit platforms, we can set csum_unnecessary
+        * to true, but only if the skb is not shared.
+        */
+#if BITS_PER_LONG == 64
+       if (!skb_shared(skb))
+               udp_skb_scratch(skb)->csum_unnecessary = true;
+#endif
+}
+
 static int udp_skb_truesize(struct sk_buff *skb)
 {
        return udp_skb_scratch(skb)->_tsize_state & ~UDP_SKB_IS_STATELESS;
@@ -1550,10 +1564,7 @@ static struct sk_buff *__first_packet_length(struct sock *sk,
                        *total += skb->truesize;
                        kfree_skb(skb);
                } else {
-                       /* the csum related bits could be changed, refresh
-                        * the scratch area
-                        */
-                       udp_set_dev_scratch(skb);
+                       udp_skb_csum_unnecessary_set(skb);
                        break;
                }
        }
@@ -1577,7 +1588,7 @@ static int first_packet_length(struct sock *sk)
 
        spin_lock_bh(&rcvq->lock);
        skb = __first_packet_length(sk, rcvq, &total);
-       if (!skb && !skb_queue_empty(sk_queue)) {
+       if (!skb && !skb_queue_empty_lockless(sk_queue)) {
                spin_lock(&sk_queue->lock);
                skb_queue_splice_tail_init(sk_queue, rcvq);
                spin_unlock(&sk_queue->lock);
@@ -1650,7 +1661,7 @@ struct sk_buff *__skb_recv_udp(struct sock *sk, unsigned int flags,
                                return skb;
                        }
 
-                       if (skb_queue_empty(sk_queue)) {
+                       if (skb_queue_empty_lockless(sk_queue)) {
                                spin_unlock_bh(&queue->lock);
                                goto busy_check;
                        }
@@ -1676,7 +1687,7 @@ busy_check:
                                break;
 
                        sk_busy_loop(sk, flags & MSG_DONTWAIT);
-               } while (!skb_queue_empty(sk_queue));
+               } while (!skb_queue_empty_lockless(sk_queue));
 
                /* sk_queue is empty, reader_queue may contain peeked packets */
        } while (timeo &&
@@ -2712,7 +2723,7 @@ __poll_t udp_poll(struct file *file, struct socket *sock, poll_table *wait)
        __poll_t mask = datagram_poll(file, sock, wait);
        struct sock *sk = sock->sk;
 
-       if (!skb_queue_empty(&udp_sk(sk)->reader_queue))
+       if (!skb_queue_empty_lockless(&udp_sk(sk)->reader_queue))
                mask |= EPOLLIN | EPOLLRDNORM;
 
        /* Check for false positives due to checksum errors */
index 783f3c1466daca7ea3d348fa1cc766fcc9026d62..2fc079284ca43886652ce394d701b153d18cf32f 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/export.h>
 #include <net/ipv6.h>
 #include <net/ipv6_stubs.h>
+#include <net/addrconf.h>
 #include <net/ip.h>
 
 /* if ipv6 module registers this function is used by xfrm to force all
index cf60fae9533b230455d89007a9ac45af958f2efe..fbe9d4295eac38d247aca362d6006cdec2d7f7da 100644 (file)
@@ -105,7 +105,7 @@ static inline int compute_score(struct sock *sk, struct net *net,
                        return -1;
 
                score = 1;
-               if (sk->sk_incoming_cpu == raw_smp_processor_id())
+               if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id())
                        score++;
        }
        return score;
index 787d9f2a6e990d12b8a7e52760f39cc4213bb4d5..923034c52ce40d85c91a54d1b107e2088d31bb85 100644 (file)
@@ -980,9 +980,9 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
                dsfield = key->tos;
                if (!(tun_info->key.tun_flags & TUNNEL_ERSPAN_OPT))
                        goto tx_err;
-               md = ip_tunnel_info_opts(tun_info);
-               if (!md)
+               if (tun_info->options_len < sizeof(*md))
                        goto tx_err;
+               md = ip_tunnel_info_opts(tun_info);
 
                tun_id = tunnel_id_to_key32(key->tun_id);
                if (md->version == 1) {
index a63ff85fe14198fc23a5cbc7abcd107df5df00c8..e60bf8e7dd1aa8dafe8981ecef633e16e1a52d8d 100644 (file)
@@ -621,6 +621,7 @@ static void rt6_probe(struct fib6_nh *fib6_nh)
 {
        struct __rt6_probe_work *work = NULL;
        const struct in6_addr *nh_gw;
+       unsigned long last_probe;
        struct neighbour *neigh;
        struct net_device *dev;
        struct inet6_dev *idev;
@@ -639,6 +640,7 @@ static void rt6_probe(struct fib6_nh *fib6_nh)
        nh_gw = &fib6_nh->fib_nh_gw6;
        dev = fib6_nh->fib_nh_dev;
        rcu_read_lock_bh();
+       last_probe = READ_ONCE(fib6_nh->last_probe);
        idev = __in6_dev_get(dev);
        neigh = __ipv6_neigh_lookup_noref(dev, nh_gw);
        if (neigh) {
@@ -654,13 +656,15 @@ static void rt6_probe(struct fib6_nh *fib6_nh)
                                __neigh_set_probe_once(neigh);
                }
                write_unlock(&neigh->lock);
-       } else if (time_after(jiffies, fib6_nh->last_probe +
+       } else if (time_after(jiffies, last_probe +
                                       idev->cnf.rtr_probe_interval)) {
                work = kmalloc(sizeof(*work), GFP_ATOMIC);
        }
 
-       if (work) {
-               fib6_nh->last_probe = jiffies;
+       if (!work || cmpxchg(&fib6_nh->last_probe,
+                            last_probe, jiffies) != last_probe) {
+               kfree(work);
+       } else {
                INIT_WORK(&work->work, rt6_probe_deferred);
                work->target = *nh_gw;
                dev_hold(dev);
@@ -3383,6 +3387,9 @@ int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh,
        int err;
 
        fib6_nh->fib_nh_family = AF_INET6;
+#ifdef CONFIG_IPV6_ROUTER_PREF
+       fib6_nh->last_probe = jiffies;
+#endif
 
        err = -ENODEV;
        if (cfg->fc_ifindex) {
index 6324d3a8cb53dd76ea0deaf4358e33e529ce56ec..9fec580c968e0d331fcaf54289364526ebd902c2 100644 (file)
@@ -135,7 +135,7 @@ static int compute_score(struct sock *sk, struct net *net,
                return -1;
        score++;
 
-       if (sk->sk_incoming_cpu == raw_smp_processor_id())
+       if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id())
                score++;
 
        return score;
index fd5ac2788e45c5b8710aae54fd2df17cae325424..d3b520b9b2c9d226f90b579b7b40e8baf459f73a 100644 (file)
@@ -56,7 +56,6 @@ static int l2tp_eth_dev_init(struct net_device *dev)
 {
        eth_hw_addr_random(dev);
        eth_broadcast_addr(dev->broadcast);
-       netdev_lockdep_set_classes(dev);
 
        return 0;
 }
index aba094b4ccfc0918859186552b730dde74934c03..2d05c4cfaf6d6401217e6fe19387e112a25a1f7b 100644 (file)
@@ -1292,8 +1292,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
        ieee80211_remove_interfaces(local);
  fail_rate:
        rtnl_unlock();
-       ieee80211_led_exit(local);
  fail_flows:
+       ieee80211_led_exit(local);
        destroy_workqueue(local->workqueue);
  fail_workqueue:
        wiphy_unregister(local->hw.wiphy);
index bd11fef2139f882517cdfbe55a0afb80c0a950c7..8d3a2389b055cfd970564ea995ed2a8877a7ba9e 100644 (file)
@@ -2457,7 +2457,8 @@ unsigned long ieee80211_sta_last_active(struct sta_info *sta)
 {
        struct ieee80211_sta_rx_stats *stats = sta_get_last_rx_stats(sta);
 
-       if (time_after(stats->last_rx, sta->status_stats.last_ack))
+       if (!sta->status_stats.last_ack ||
+           time_after(stats->last_rx, sta->status_stats.last_ack))
                return stats->last_rx;
        return sta->status_stats.last_ack;
 }
index e64d5f9a89dd331e48ddf38af1c9978d2507a958..d73d1828216a6e7b10e690312316729d699f7689 100644 (file)
@@ -296,7 +296,8 @@ ip_set_get_ipaddr4(struct nlattr *nla,  __be32 *ipaddr)
 
        if (unlikely(!flag_nested(nla)))
                return -IPSET_ERR_PROTOCOL;
-       if (nla_parse_nested_deprecated(tb, IPSET_ATTR_IPADDR_MAX, nla, ipaddr_policy, NULL))
+       if (nla_parse_nested(tb, IPSET_ATTR_IPADDR_MAX, nla,
+                            ipaddr_policy, NULL))
                return -IPSET_ERR_PROTOCOL;
        if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_IPADDR_IPV4)))
                return -IPSET_ERR_PROTOCOL;
@@ -314,7 +315,8 @@ ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr)
        if (unlikely(!flag_nested(nla)))
                return -IPSET_ERR_PROTOCOL;
 
-       if (nla_parse_nested_deprecated(tb, IPSET_ATTR_IPADDR_MAX, nla, ipaddr_policy, NULL))
+       if (nla_parse_nested(tb, IPSET_ATTR_IPADDR_MAX, nla,
+                            ipaddr_policy, NULL))
                return -IPSET_ERR_PROTOCOL;
        if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_IPADDR_IPV6)))
                return -IPSET_ERR_PROTOCOL;
@@ -934,7 +936,8 @@ static int ip_set_create(struct net *net, struct sock *ctnl,
 
        /* Without holding any locks, create private part. */
        if (attr[IPSET_ATTR_DATA] &&
-           nla_parse_nested_deprecated(tb, IPSET_ATTR_CREATE_MAX, attr[IPSET_ATTR_DATA], set->type->create_policy, NULL)) {
+           nla_parse_nested(tb, IPSET_ATTR_CREATE_MAX, attr[IPSET_ATTR_DATA],
+                            set->type->create_policy, NULL)) {
                ret = -IPSET_ERR_PROTOCOL;
                goto put_out;
        }
@@ -1281,6 +1284,14 @@ dump_attrs(struct nlmsghdr *nlh)
        }
 }
 
+static const struct nla_policy
+ip_set_dump_policy[IPSET_ATTR_CMD_MAX + 1] = {
+       [IPSET_ATTR_PROTOCOL]   = { .type = NLA_U8 },
+       [IPSET_ATTR_SETNAME]    = { .type = NLA_NUL_STRING,
+                                   .len = IPSET_MAXNAMELEN - 1 },
+       [IPSET_ATTR_FLAGS]      = { .type = NLA_U32 },
+};
+
 static int
 dump_init(struct netlink_callback *cb, struct ip_set_net *inst)
 {
@@ -1292,9 +1303,9 @@ dump_init(struct netlink_callback *cb, struct ip_set_net *inst)
        ip_set_id_t index;
        int ret;
 
-       ret = nla_parse_deprecated(cda, IPSET_ATTR_CMD_MAX, attr,
-                                  nlh->nlmsg_len - min_len,
-                                  ip_set_setname_policy, NULL);
+       ret = nla_parse(cda, IPSET_ATTR_CMD_MAX, attr,
+                       nlh->nlmsg_len - min_len,
+                       ip_set_dump_policy, NULL);
        if (ret)
                return ret;
 
@@ -1543,9 +1554,9 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
                memcpy(&errmsg->msg, nlh, nlh->nlmsg_len);
                cmdattr = (void *)&errmsg->msg + min_len;
 
-               ret = nla_parse_deprecated(cda, IPSET_ATTR_CMD_MAX, cmdattr,
-                                          nlh->nlmsg_len - min_len,
-                                          ip_set_adt_policy, NULL);
+               ret = nla_parse(cda, IPSET_ATTR_CMD_MAX, cmdattr,
+                               nlh->nlmsg_len - min_len, ip_set_adt_policy,
+                               NULL);
 
                if (ret) {
                        nlmsg_free(skb2);
@@ -1596,7 +1607,9 @@ static int ip_set_ad(struct net *net, struct sock *ctnl,
 
        use_lineno = !!attr[IPSET_ATTR_LINENO];
        if (attr[IPSET_ATTR_DATA]) {
-               if (nla_parse_nested_deprecated(tb, IPSET_ATTR_ADT_MAX, attr[IPSET_ATTR_DATA], set->type->adt_policy, NULL))
+               if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX,
+                                    attr[IPSET_ATTR_DATA],
+                                    set->type->adt_policy, NULL))
                        return -IPSET_ERR_PROTOCOL;
                ret = call_ad(ctnl, skb, set, tb, adt, flags,
                              use_lineno);
@@ -1606,7 +1619,8 @@ static int ip_set_ad(struct net *net, struct sock *ctnl,
                nla_for_each_nested(nla, attr[IPSET_ATTR_ADT], nla_rem) {
                        if (nla_type(nla) != IPSET_ATTR_DATA ||
                            !flag_nested(nla) ||
-                           nla_parse_nested_deprecated(tb, IPSET_ATTR_ADT_MAX, nla, set->type->adt_policy, NULL))
+                           nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla,
+                                            set->type->adt_policy, NULL))
                                return -IPSET_ERR_PROTOCOL;
                        ret = call_ad(ctnl, skb, set, tb, adt,
                                      flags, use_lineno);
@@ -1655,7 +1669,8 @@ static int ip_set_utest(struct net *net, struct sock *ctnl, struct sk_buff *skb,
        if (!set)
                return -ENOENT;
 
-       if (nla_parse_nested_deprecated(tb, IPSET_ATTR_ADT_MAX, attr[IPSET_ATTR_DATA], set->type->adt_policy, NULL))
+       if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, attr[IPSET_ATTR_DATA],
+                            set->type->adt_policy, NULL))
                return -IPSET_ERR_PROTOCOL;
 
        rcu_read_lock_bh();
@@ -1961,7 +1976,7 @@ static const struct nfnl_callback ip_set_netlink_subsys_cb[IPSET_MSG_MAX] = {
        [IPSET_CMD_LIST]        = {
                .call           = ip_set_dump,
                .attr_count     = IPSET_ATTR_CMD_MAX,
-               .policy         = ip_set_setname_policy,
+               .policy         = ip_set_dump_policy,
        },
        [IPSET_CMD_SAVE]        = {
                .call           = ip_set_dump,
@@ -2069,8 +2084,9 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
                }
 
                req_version->version = IPSET_PROTOCOL;
-               ret = copy_to_user(user, req_version,
-                                  sizeof(struct ip_set_req_version));
+               if (copy_to_user(user, req_version,
+                                sizeof(struct ip_set_req_version)))
+                       ret = -EFAULT;
                goto done;
        }
        case IP_SET_OP_GET_BYNAME: {
@@ -2129,7 +2145,8 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
        }       /* end of switch(op) */
 
 copy:
-       ret = copy_to_user(user, data, copylen);
+       if (copy_to_user(user, data, copylen))
+               ret = -EFAULT;
 
 done:
        vfree(data);
index 24d8f4df4230ca573098fbcdc83baadfd855e094..4ce563eb927d468d9450aed5f261a9ebaaf1e6cf 100644 (file)
@@ -209,7 +209,7 @@ hash_ipmac6_kadt(struct ip_set *set, const struct sk_buff *skb,
            (skb_mac_header(skb) + ETH_HLEN) > skb->data)
                return -EINVAL;
 
-       if (opt->flags & IPSET_DIM_ONE_SRC)
+       if (opt->flags & IPSET_DIM_TWO_SRC)
                ether_addr_copy(e.ether, eth_hdr(skb)->h_source);
        else
                ether_addr_copy(e.ether, eth_hdr(skb)->h_dest);
index c259cbc3ef453eaee5461e2b98fc3dc735d196ad..3d932de0ad295a811c51cebcd32e695cbb871fcc 100644 (file)
@@ -368,6 +368,7 @@ static struct ip_set_type hash_net_type __read_mostly = {
                [IPSET_ATTR_IP_TO]      = { .type = NLA_NESTED },
                [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
                [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
+               [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
                [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
                [IPSET_ATTR_BYTES]      = { .type = NLA_U64 },
                [IPSET_ATTR_PACKETS]    = { .type = NLA_U64 },
index a3ae69bfee668466f276f5cdebb451048a7eb5e9..4398322fad59207d03681492306d3d2b63f1c271 100644 (file)
@@ -476,6 +476,7 @@ static struct ip_set_type hash_netnet_type __read_mostly = {
                [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
                [IPSET_ATTR_CIDR2]      = { .type = NLA_U8 },
                [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
+               [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
                [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
                [IPSET_ATTR_BYTES]      = { .type = NLA_U64 },
                [IPSET_ATTR_PACKETS]    = { .type = NLA_U64 },
index 4515056ef1c2b4d7ab268986152bc6845b006fbd..f9b16f2b221918f1be0ae6bd8da118b2046670a2 100644 (file)
@@ -193,21 +193,29 @@ struct ip_vs_app *register_ip_vs_app(struct netns_ipvs *ipvs, struct ip_vs_app *
 
        mutex_lock(&__ip_vs_app_mutex);
 
+       /* increase the module use count */
+       if (!ip_vs_use_count_inc()) {
+               err = -ENOENT;
+               goto out_unlock;
+       }
+
        list_for_each_entry(a, &ipvs->app_list, a_list) {
                if (!strcmp(app->name, a->name)) {
                        err = -EEXIST;
+                       /* decrease the module use count */
+                       ip_vs_use_count_dec();
                        goto out_unlock;
                }
        }
        a = kmemdup(app, sizeof(*app), GFP_KERNEL);
        if (!a) {
                err = -ENOMEM;
+               /* decrease the module use count */
+               ip_vs_use_count_dec();
                goto out_unlock;
        }
        INIT_LIST_HEAD(&a->incs_list);
        list_add(&a->a_list, &ipvs->app_list);
-       /* increase the module use count */
-       ip_vs_use_count_inc();
 
 out_unlock:
        mutex_unlock(&__ip_vs_app_mutex);
index 8b48e7ce1c2c2243bbdc8c4e43e4e484f3e52df6..3cccc88ef817bdbc4719316757e8cf8b5d61df1b 100644 (file)
@@ -93,7 +93,6 @@ static bool __ip_vs_addr_is_local_v6(struct net *net,
 static void update_defense_level(struct netns_ipvs *ipvs)
 {
        struct sysinfo i;
-       static int old_secure_tcp = 0;
        int availmem;
        int nomem;
        int to_change = -1;
@@ -174,35 +173,35 @@ static void update_defense_level(struct netns_ipvs *ipvs)
        spin_lock(&ipvs->securetcp_lock);
        switch (ipvs->sysctl_secure_tcp) {
        case 0:
-               if (old_secure_tcp >= 2)
+               if (ipvs->old_secure_tcp >= 2)
                        to_change = 0;
                break;
        case 1:
                if (nomem) {
-                       if (old_secure_tcp < 2)
+                       if (ipvs->old_secure_tcp < 2)
                                to_change = 1;
                        ipvs->sysctl_secure_tcp = 2;
                } else {
-                       if (old_secure_tcp >= 2)
+                       if (ipvs->old_secure_tcp >= 2)
                                to_change = 0;
                }
                break;
        case 2:
                if (nomem) {
-                       if (old_secure_tcp < 2)
+                       if (ipvs->old_secure_tcp < 2)
                                to_change = 1;
                } else {
-                       if (old_secure_tcp >= 2)
+                       if (ipvs->old_secure_tcp >= 2)
                                to_change = 0;
                        ipvs->sysctl_secure_tcp = 1;
                }
                break;
        case 3:
-               if (old_secure_tcp < 2)
+               if (ipvs->old_secure_tcp < 2)
                        to_change = 1;
                break;
        }
-       old_secure_tcp = ipvs->sysctl_secure_tcp;
+       ipvs->old_secure_tcp = ipvs->sysctl_secure_tcp;
        if (to_change >= 0)
                ip_vs_protocol_timeout_change(ipvs,
                                              ipvs->sysctl_secure_tcp > 1);
@@ -1275,7 +1274,8 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u,
        struct ip_vs_service *svc = NULL;
 
        /* increase the module use count */
-       ip_vs_use_count_inc();
+       if (!ip_vs_use_count_inc())
+               return -ENOPROTOOPT;
 
        /* Lookup the scheduler by 'u->sched_name' */
        if (strcmp(u->sched_name, "none")) {
@@ -2435,9 +2435,6 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
        if (copy_from_user(arg, user, len) != 0)
                return -EFAULT;
 
-       /* increase the module use count */
-       ip_vs_use_count_inc();
-
        /* Handle daemons since they have another lock */
        if (cmd == IP_VS_SO_SET_STARTDAEMON ||
            cmd == IP_VS_SO_SET_STOPDAEMON) {
@@ -2450,13 +2447,13 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
                        ret = -EINVAL;
                        if (strscpy(cfg.mcast_ifn, dm->mcast_ifn,
                                    sizeof(cfg.mcast_ifn)) <= 0)
-                               goto out_dec;
+                               return ret;
                        cfg.syncid = dm->syncid;
                        ret = start_sync_thread(ipvs, &cfg, dm->state);
                } else {
                        ret = stop_sync_thread(ipvs, dm->state);
                }
-               goto out_dec;
+               return ret;
        }
 
        mutex_lock(&__ip_vs_mutex);
@@ -2551,10 +2548,6 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
 
   out_unlock:
        mutex_unlock(&__ip_vs_mutex);
-  out_dec:
-       /* decrease the module use count */
-       ip_vs_use_count_dec();
-
        return ret;
 }
 
index 8e104dff7abc414c3879a5a7555814badf44b8e4..166c669f07634b2652e8ed71938415de20b9a14f 100644 (file)
@@ -68,7 +68,8 @@ int register_ip_vs_pe(struct ip_vs_pe *pe)
        struct ip_vs_pe *tmp;
 
        /* increase the module use count */
-       ip_vs_use_count_inc();
+       if (!ip_vs_use_count_inc())
+               return -ENOENT;
 
        mutex_lock(&ip_vs_pe_mutex);
        /* Make sure that the pe with this name doesn't exist
index 2f9d5cd5daeeeb842fc174cb47612a1e81d202fe..d4903723be7e90ad6c996f00ee66486acd6302fb 100644 (file)
@@ -179,7 +179,8 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler)
        }
 
        /* increase the module use count */
-       ip_vs_use_count_inc();
+       if (!ip_vs_use_count_inc())
+               return -ENOENT;
 
        mutex_lock(&ip_vs_sched_mutex);
 
index a4a78c4b06dec380dc4db957f9c95cf050998580..8dc892a9dc91a9bbd0b11bf53c3da506de548fd2 100644 (file)
@@ -1762,6 +1762,10 @@ int start_sync_thread(struct netns_ipvs *ipvs, struct ipvs_sync_daemon_cfg *c,
        IP_VS_DBG(7, "Each ip_vs_sync_conn entry needs %zd bytes\n",
                  sizeof(struct ip_vs_sync_conn_v0));
 
+       /* increase the module use count */
+       if (!ip_vs_use_count_inc())
+               return -ENOPROTOOPT;
+
        /* Do not hold one mutex and then to block on another */
        for (;;) {
                rtnl_lock();
@@ -1892,9 +1896,6 @@ int start_sync_thread(struct netns_ipvs *ipvs, struct ipvs_sync_daemon_cfg *c,
        mutex_unlock(&ipvs->sync_mutex);
        rtnl_unlock();
 
-       /* increase the module use count */
-       ip_vs_use_count_inc();
-
        return 0;
 
 out:
@@ -1924,11 +1925,17 @@ out:
                }
                kfree(ti);
        }
+
+       /* decrease the module use count */
+       ip_vs_use_count_dec();
        return result;
 
 out_early:
        mutex_unlock(&ipvs->sync_mutex);
        rtnl_unlock();
+
+       /* decrease the module use count */
+       ip_vs_use_count_dec();
        return result;
 }
 
index 132f5228b4319df1f584d69f0ff75f40c45dad28..128245efe84abec57723f2c26262c90d7b3e27e8 100644 (file)
@@ -202,6 +202,8 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
 {
        int err;
 
+       flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT;
+
        err = rhashtable_insert_fast(&flow_table->rhashtable,
                                     &flow->tuplehash[0].node,
                                     nf_flow_offload_rhash_params);
@@ -218,7 +220,6 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
                return err;
        }
 
-       flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT;
        return 0;
 }
 EXPORT_SYMBOL_GPL(flow_offload_add);
index d481f9baca2f8b225afbec0069ac8a3b73e1659b..712a428509add2c28261b9daf537abe8f9d71311 100644 (file)
@@ -1922,6 +1922,7 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
                if (nlh->nlmsg_flags & NLM_F_REPLACE)
                        return -EOPNOTSUPP;
 
+               flags |= chain->flags & NFT_BASE_CHAIN;
                return nf_tables_updchain(&ctx, genmask, policy, flags);
        }
 
@@ -5143,9 +5144,6 @@ static int nf_tables_updobj(const struct nft_ctx *ctx,
        struct nft_trans *trans;
        int err;
 
-       if (!obj->ops->update)
-               return -EOPNOTSUPP;
-
        trans = nft_trans_alloc(ctx, NFT_MSG_NEWOBJ,
                                sizeof(struct nft_trans_obj));
        if (!trans)
@@ -6499,7 +6497,8 @@ static void nft_obj_commit_update(struct nft_trans *trans)
        obj = nft_trans_obj(trans);
        newobj = nft_trans_obj_newobj(trans);
 
-       obj->ops->update(obj, newobj);
+       if (obj->ops->update)
+               obj->ops->update(obj, newobj);
 
        kfree(newobj);
 }
index e546f759b7a714b5376c035e1a82cc1821cb680e..e25dab8128db37879ff692ba59e454925bdad429 100644 (file)
@@ -334,7 +334,8 @@ int nft_flow_rule_offload_commit(struct net *net)
 
                switch (trans->msg_type) {
                case NFT_MSG_NEWCHAIN:
-                       if (!(trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD))
+                       if (!(trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD) ||
+                           nft_trans_chain_update(trans))
                                continue;
 
                        policy = nft_trans_chain_policy(trans);
@@ -347,7 +348,7 @@ int nft_flow_rule_offload_commit(struct net *net)
 
                        policy = nft_trans_chain_policy(trans);
                        err = nft_flow_offload_chain(trans->ctx.chain, &policy,
-                                                    FLOW_BLOCK_BIND);
+                                                    FLOW_BLOCK_UNBIND);
                        break;
                case NFT_MSG_NEWRULE:
                        if (!(trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD))
index 974300178fa9064898d74827a901de2efc81c608..02afa752dd2e626355217d2f31e731ac131a4ce7 100644 (file)
@@ -134,12 +134,13 @@ static int nft_bitwise_offload(struct nft_offload_ctx *ctx,
                                const struct nft_expr *expr)
 {
        const struct nft_bitwise *priv = nft_expr_priv(expr);
+       struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
 
        if (memcmp(&priv->xor, &zero, sizeof(priv->xor)) ||
-           priv->sreg != priv->dreg)
+           priv->sreg != priv->dreg || priv->len != reg->len)
                return -EOPNOTSUPP;
 
-       memcpy(&ctx->regs[priv->dreg].mask, &priv->mask, sizeof(priv->mask));
+       memcpy(&reg->mask, &priv->mask, sizeof(priv->mask));
 
        return 0;
 }
index bd173b1824c6ed6c28d2fae579a1e3a0a132fe05..0744b2bb46da922b20f1a4798639916cd29f8587 100644 (file)
@@ -116,7 +116,7 @@ static int __nft_cmp_offload(struct nft_offload_ctx *ctx,
        u8 *mask = (u8 *)&flow->match.mask;
        u8 *key = (u8 *)&flow->match.key;
 
-       if (priv->op != NFT_CMP_EQ)
+       if (priv->op != NFT_CMP_EQ || reg->len != priv->len)
                return -EOPNOTSUPP;
 
        memcpy(key + reg->offset, &priv->data, priv->len);
index 22a80eb60222ef06b671b0b1cbea87609a71786e..5cb2d8908d2a5d47bdedcaaf3383636708b366fc 100644 (file)
@@ -161,13 +161,21 @@ static int nft_payload_offload_ll(struct nft_offload_ctx *ctx,
 
        switch (priv->offset) {
        case offsetof(struct ethhdr, h_source):
+               if (priv->len != ETH_ALEN)
+                       return -EOPNOTSUPP;
+
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs,
                                  src, ETH_ALEN, reg);
                break;
        case offsetof(struct ethhdr, h_dest):
+               if (priv->len != ETH_ALEN)
+                       return -EOPNOTSUPP;
+
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs,
                                  dst, ETH_ALEN, reg);
                break;
+       default:
+               return -EOPNOTSUPP;
        }
 
        return 0;
@@ -181,14 +189,23 @@ static int nft_payload_offload_ip(struct nft_offload_ctx *ctx,
 
        switch (priv->offset) {
        case offsetof(struct iphdr, saddr):
+               if (priv->len != sizeof(struct in_addr))
+                       return -EOPNOTSUPP;
+
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, src,
                                  sizeof(struct in_addr), reg);
                break;
        case offsetof(struct iphdr, daddr):
+               if (priv->len != sizeof(struct in_addr))
+                       return -EOPNOTSUPP;
+
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, dst,
                                  sizeof(struct in_addr), reg);
                break;
        case offsetof(struct iphdr, protocol):
+               if (priv->len != sizeof(__u8))
+                       return -EOPNOTSUPP;
+
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
                                  sizeof(__u8), reg);
                nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
@@ -208,14 +225,23 @@ static int nft_payload_offload_ip6(struct nft_offload_ctx *ctx,
 
        switch (priv->offset) {
        case offsetof(struct ipv6hdr, saddr):
+               if (priv->len != sizeof(struct in6_addr))
+                       return -EOPNOTSUPP;
+
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, src,
                                  sizeof(struct in6_addr), reg);
                break;
        case offsetof(struct ipv6hdr, daddr):
+               if (priv->len != sizeof(struct in6_addr))
+                       return -EOPNOTSUPP;
+
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, dst,
                                  sizeof(struct in6_addr), reg);
                break;
        case offsetof(struct ipv6hdr, nexthdr):
+               if (priv->len != sizeof(__u8))
+                       return -EOPNOTSUPP;
+
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
                                  sizeof(__u8), reg);
                nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
@@ -255,10 +281,16 @@ static int nft_payload_offload_tcp(struct nft_offload_ctx *ctx,
 
        switch (priv->offset) {
        case offsetof(struct tcphdr, source):
+               if (priv->len != sizeof(__be16))
+                       return -EOPNOTSUPP;
+
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src,
                                  sizeof(__be16), reg);
                break;
        case offsetof(struct tcphdr, dest):
+               if (priv->len != sizeof(__be16))
+                       return -EOPNOTSUPP;
+
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst,
                                  sizeof(__be16), reg);
                break;
@@ -277,10 +309,16 @@ static int nft_payload_offload_udp(struct nft_offload_ctx *ctx,
 
        switch (priv->offset) {
        case offsetof(struct udphdr, source):
+               if (priv->len != sizeof(__be16))
+                       return -EOPNOTSUPP;
+
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src,
                                  sizeof(__be16), reg);
                break;
        case offsetof(struct udphdr, dest):
+               if (priv->len != sizeof(__be16))
+                       return -EOPNOTSUPP;
+
                NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst,
                                  sizeof(__be16), reg);
                break;
index c4f54ad2b98afb44002415ce1daf2afef646d8c0..58d5373c513c7999bd73813eafd80c8abad87dc4 100644 (file)
@@ -63,28 +63,6 @@ static DEFINE_SPINLOCK(nr_list_lock);
 
 static const struct proto_ops nr_proto_ops;
 
-/*
- * NETROM network devices are virtual network devices encapsulating NETROM
- * frames into AX.25 which will be sent through an AX.25 device, so form a
- * special "super class" of normal net devices; split their locks off into a
- * separate class since they always nest.
- */
-static struct lock_class_key nr_netdev_xmit_lock_key;
-static struct lock_class_key nr_netdev_addr_lock_key;
-
-static void nr_set_lockdep_one(struct net_device *dev,
-                              struct netdev_queue *txq,
-                              void *_unused)
-{
-       lockdep_set_class(&txq->_xmit_lock, &nr_netdev_xmit_lock_key);
-}
-
-static void nr_set_lockdep_key(struct net_device *dev)
-{
-       lockdep_set_class(&dev->addr_list_lock, &nr_netdev_addr_lock_key);
-       netdev_for_each_tx_queue(dev, nr_set_lockdep_one, NULL);
-}
-
 /*
  *     Socket removal during an interrupt is now safe.
  */
@@ -1414,7 +1392,6 @@ static int __init nr_proto_init(void)
                        free_netdev(dev);
                        goto fail;
                }
-               nr_set_lockdep_key(dev);
                dev_nr[i] = dev;
        }
 
index ccdd790e163a81d0be5c69842fb3d25a57c743c4..28604414dec1b7d03f0d175cc87c10e0922c7043 100644 (file)
@@ -554,11 +554,11 @@ static __poll_t llcp_sock_poll(struct file *file, struct socket *sock,
        if (sk->sk_state == LLCP_LISTEN)
                return llcp_accept_poll(sk);
 
-       if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
+       if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue))
                mask |= EPOLLERR |
                        (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0);
 
-       if (!skb_queue_empty(&sk->sk_receive_queue))
+       if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
                mask |= EPOLLIN | EPOLLRDNORM;
 
        if (sk->sk_state == LLCP_CLOSED)
index 17e6ca62f1beb5c6048c163271fe254c1e3e55ca..afde0d763039b8a1006ef02ade0243c8d25f9d72 100644 (file)
@@ -1099,7 +1099,6 @@ static int nfc_genl_llc_set_params(struct sk_buff *skb, struct genl_info *info)
 
        local = nfc_llcp_find_local(dev);
        if (!local) {
-               nfc_put_device(dev);
                rc = -ENODEV;
                goto exit;
        }
@@ -1159,7 +1158,6 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info)
 
        local = nfc_llcp_find_local(dev);
        if (!local) {
-               nfc_put_device(dev);
                rc = -ENODEV;
                goto exit;
        }
index f30e406fbec5a321de0a489b2d41c39dd08fb561..d8c364d637b12d8ec6f1e30bb46a06b27cd06311 100644 (file)
@@ -1881,7 +1881,7 @@ static struct genl_family dp_datapath_genl_family __ro_after_init = {
 /* Called with ovs_mutex or RCU read lock. */
 static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
                                   struct net *net, u32 portid, u32 seq,
-                                  u32 flags, u8 cmd)
+                                  u32 flags, u8 cmd, gfp_t gfp)
 {
        struct ovs_header *ovs_header;
        struct ovs_vport_stats vport_stats;
@@ -1902,7 +1902,7 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
                goto nla_put_failure;
 
        if (!net_eq(net, dev_net(vport->dev))) {
-               int id = peernet2id_alloc(net, dev_net(vport->dev));
+               int id = peernet2id_alloc(net, dev_net(vport->dev), gfp);
 
                if (nla_put_s32(skb, OVS_VPORT_ATTR_NETNSID, id))
                        goto nla_put_failure;
@@ -1943,11 +1943,12 @@ struct sk_buff *ovs_vport_cmd_build_info(struct vport *vport, struct net *net,
        struct sk_buff *skb;
        int retval;
 
-       skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
+       skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
        if (!skb)
                return ERR_PTR(-ENOMEM);
 
-       retval = ovs_vport_cmd_fill_info(vport, skb, net, portid, seq, 0, cmd);
+       retval = ovs_vport_cmd_fill_info(vport, skb, net, portid, seq, 0, cmd,
+                                        GFP_KERNEL);
        BUG_ON(retval < 0);
 
        return skb;
@@ -2089,7 +2090,7 @@ restart:
 
        err = ovs_vport_cmd_fill_info(vport, reply, genl_info_net(info),
                                      info->snd_portid, info->snd_seq, 0,
-                                     OVS_VPORT_CMD_NEW);
+                                     OVS_VPORT_CMD_NEW, GFP_KERNEL);
 
        new_headroom = netdev_get_fwd_headroom(vport->dev);
 
@@ -2150,7 +2151,7 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
 
        err = ovs_vport_cmd_fill_info(vport, reply, genl_info_net(info),
                                      info->snd_portid, info->snd_seq, 0,
-                                     OVS_VPORT_CMD_SET);
+                                     OVS_VPORT_CMD_SET, GFP_KERNEL);
        BUG_ON(err < 0);
 
        ovs_unlock();
@@ -2190,7 +2191,7 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info)
 
        err = ovs_vport_cmd_fill_info(vport, reply, genl_info_net(info),
                                      info->snd_portid, info->snd_seq, 0,
-                                     OVS_VPORT_CMD_DEL);
+                                     OVS_VPORT_CMD_DEL, GFP_KERNEL);
        BUG_ON(err < 0);
 
        /* the vport deletion may trigger dp headroom update */
@@ -2237,7 +2238,7 @@ static int ovs_vport_cmd_get(struct sk_buff *skb, struct genl_info *info)
                goto exit_unlock_free;
        err = ovs_vport_cmd_fill_info(vport, reply, genl_info_net(info),
                                      info->snd_portid, info->snd_seq, 0,
-                                     OVS_VPORT_CMD_GET);
+                                     OVS_VPORT_CMD_GET, GFP_ATOMIC);
        BUG_ON(err < 0);
        rcu_read_unlock();
 
@@ -2273,7 +2274,8 @@ static int ovs_vport_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
                                                    NETLINK_CB(cb->skb).portid,
                                                    cb->nlh->nlmsg_seq,
                                                    NLM_F_MULTI,
-                                                   OVS_VPORT_CMD_GET) < 0)
+                                                   OVS_VPORT_CMD_GET,
+                                                   GFP_ATOMIC) < 0)
                                goto out;
 
                        j++;
index 21c90d3a7ebf7233160467de97eec379467765a9..58a7b8312c28992ad96827d1eabea443f098a448 100644 (file)
@@ -137,7 +137,7 @@ static void do_setup(struct net_device *netdev)
        netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_OPENVSWITCH |
                              IFF_NO_QUEUE;
        netdev->needs_free_netdev = true;
-       netdev->priv_destructor = internal_dev_destructor;
+       netdev->priv_destructor = NULL;
        netdev->ethtool_ops = &internal_dev_ethtool_ops;
        netdev->rtnl_link_ops = &internal_dev_link_ops;
 
@@ -159,7 +159,6 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)
        struct internal_dev *internal_dev;
        struct net_device *dev;
        int err;
-       bool free_vport = true;
 
        vport = ovs_vport_alloc(0, &ovs_internal_vport_ops, parms);
        if (IS_ERR(vport)) {
@@ -190,10 +189,9 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)
 
        rtnl_lock();
        err = register_netdevice(vport->dev);
-       if (err) {
-               free_vport = false;
+       if (err)
                goto error_unlock;
-       }
+       vport->dev->priv_destructor = internal_dev_destructor;
 
        dev_set_promiscuity(vport->dev, 1);
        rtnl_unlock();
@@ -207,8 +205,7 @@ error_unlock:
 error_free_netdev:
        free_netdev(dev);
 error_free_vport:
-       if (free_vport)
-               ovs_vport_free(vport);
+       ovs_vport_free(vport);
 error:
        return ERR_PTR(err);
 }
index 96ea9f254ae90ae957f800566b05a7f75d13948f..76d499f6af9ab32aa17422ef911497585b6649b7 100644 (file)
@@ -338,9 +338,9 @@ static __poll_t pn_socket_poll(struct file *file, struct socket *sock,
 
        if (sk->sk_state == TCP_CLOSE)
                return EPOLLERR;
-       if (!skb_queue_empty(&sk->sk_receive_queue))
+       if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
                mask |= EPOLLIN | EPOLLRDNORM;
-       if (!skb_queue_empty(&pn->ctrlreq_queue))
+       if (!skb_queue_empty_lockless(&pn->ctrlreq_queue))
                mask |= EPOLLPRI;
        if (!mask && sk->sk_state == TCP_CLOSE_WAIT)
                return EPOLLHUP;
index f0e9ccf472a970004bd4ea1adb4d758b926b5837..6a0df7c8a939e4976aa2815127885e127dd864fc 100644 (file)
@@ -64,28 +64,6 @@ static const struct proto_ops rose_proto_ops;
 
 ax25_address rose_callsign;
 
-/*
- * ROSE network devices are virtual network devices encapsulating ROSE
- * frames into AX.25 which will be sent through an AX.25 device, so form a
- * special "super class" of normal net devices; split their locks off into a
- * separate class since they always nest.
- */
-static struct lock_class_key rose_netdev_xmit_lock_key;
-static struct lock_class_key rose_netdev_addr_lock_key;
-
-static void rose_set_lockdep_one(struct net_device *dev,
-                                struct netdev_queue *txq,
-                                void *_unused)
-{
-       lockdep_set_class(&txq->_xmit_lock, &rose_netdev_xmit_lock_key);
-}
-
-static void rose_set_lockdep_key(struct net_device *dev)
-{
-       lockdep_set_class(&dev->addr_list_lock, &rose_netdev_addr_lock_key);
-       netdev_for_each_tx_queue(dev, rose_set_lockdep_one, NULL);
-}
-
 /*
  *     Convert a ROSE address into text.
  */
@@ -1533,7 +1511,6 @@ static int __init rose_proto_init(void)
                        free_netdev(dev);
                        goto fail;
                }
-               rose_set_lockdep_key(dev);
                dev_rose[i] = dev;
        }
 
index ecc17dabec8fc0b6dc505e940b2ca78145d1c794..7c7d10f2e0c181776611cd54d6048a17ed512d5f 100644 (file)
@@ -601,6 +601,7 @@ struct rxrpc_call {
        int                     debug_id;       /* debug ID for printks */
        unsigned short          rx_pkt_offset;  /* Current recvmsg packet offset */
        unsigned short          rx_pkt_len;     /* Current recvmsg packet len */
+       bool                    rx_pkt_last;    /* Current recvmsg packet is last */
 
        /* Rx/Tx circular buffer, depending on phase.
         *
index a4090797c9b2585b830f31437fff01eef7736d42..8578c39ec83959b99dc50fb00fb70968e09ad18e 100644 (file)
@@ -267,11 +267,13 @@ static int rxrpc_verify_packet(struct rxrpc_call *call, struct sk_buff *skb,
  */
 static int rxrpc_locate_data(struct rxrpc_call *call, struct sk_buff *skb,
                             u8 *_annotation,
-                            unsigned int *_offset, unsigned int *_len)
+                            unsigned int *_offset, unsigned int *_len,
+                            bool *_last)
 {
        struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
        unsigned int offset = sizeof(struct rxrpc_wire_header);
        unsigned int len;
+       bool last = false;
        int ret;
        u8 annotation = *_annotation;
        u8 subpacket = annotation & RXRPC_RX_ANNO_SUBPACKET;
@@ -281,6 +283,8 @@ static int rxrpc_locate_data(struct rxrpc_call *call, struct sk_buff *skb,
        len = skb->len - offset;
        if (subpacket < sp->nr_subpackets - 1)
                len = RXRPC_JUMBO_DATALEN;
+       else if (sp->rx_flags & RXRPC_SKB_INCL_LAST)
+               last = true;
 
        if (!(annotation & RXRPC_RX_ANNO_VERIFIED)) {
                ret = rxrpc_verify_packet(call, skb, annotation, offset, len);
@@ -291,6 +295,7 @@ static int rxrpc_locate_data(struct rxrpc_call *call, struct sk_buff *skb,
 
        *_offset = offset;
        *_len = len;
+       *_last = last;
        call->security->locate_data(call, skb, _offset, _len);
        return 0;
 }
@@ -309,7 +314,7 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
        rxrpc_serial_t serial;
        rxrpc_seq_t hard_ack, top, seq;
        size_t remain;
-       bool last;
+       bool rx_pkt_last;
        unsigned int rx_pkt_offset, rx_pkt_len;
        int ix, copy, ret = -EAGAIN, ret2;
 
@@ -319,6 +324,7 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
 
        rx_pkt_offset = call->rx_pkt_offset;
        rx_pkt_len = call->rx_pkt_len;
+       rx_pkt_last = call->rx_pkt_last;
 
        if (call->state >= RXRPC_CALL_SERVER_ACK_REQUEST) {
                seq = call->rx_hard_ack;
@@ -329,6 +335,7 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
        /* Barriers against rxrpc_input_data(). */
        hard_ack = call->rx_hard_ack;
        seq = hard_ack + 1;
+
        while (top = smp_load_acquire(&call->rx_top),
               before_eq(seq, top)
               ) {
@@ -356,7 +363,8 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
                if (rx_pkt_offset == 0) {
                        ret2 = rxrpc_locate_data(call, skb,
                                                 &call->rxtx_annotations[ix],
-                                                &rx_pkt_offset, &rx_pkt_len);
+                                                &rx_pkt_offset, &rx_pkt_len,
+                                                &rx_pkt_last);
                        trace_rxrpc_recvmsg(call, rxrpc_recvmsg_next, seq,
                                            rx_pkt_offset, rx_pkt_len, ret2);
                        if (ret2 < 0) {
@@ -396,13 +404,12 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
                }
 
                /* The whole packet has been transferred. */
-               last = sp->hdr.flags & RXRPC_LAST_PACKET;
                if (!(flags & MSG_PEEK))
                        rxrpc_rotate_rx_window(call);
                rx_pkt_offset = 0;
                rx_pkt_len = 0;
 
-               if (last) {
+               if (rx_pkt_last) {
                        ASSERTCMP(seq, ==, READ_ONCE(call->rx_top));
                        ret = 1;
                        goto out;
@@ -415,6 +422,7 @@ out:
        if (!(flags & MSG_PEEK)) {
                call->rx_pkt_offset = rx_pkt_offset;
                call->rx_pkt_len = rx_pkt_len;
+               call->rx_pkt_last = rx_pkt_last;
        }
 done:
        trace_rxrpc_recvmsg(call, rxrpc_recvmsg_data_return, seq,
index 8717c0b26c905457e5b220465cceb2ffae71e561..20d60b8fcb70c0175bc1a998a9eb80f693c1f8cd 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/slab.h>
 #include <linux/idr.h>
 #include <linux/rhashtable.h>
+#include <linux/jhash.h>
 #include <net/net_namespace.h>
 #include <net/sock.h>
 #include <net/netlink.h>
@@ -47,6 +48,62 @@ static LIST_HEAD(tcf_proto_base);
 /* Protects list of registered TC modules. It is pure SMP lock. */
 static DEFINE_RWLOCK(cls_mod_lock);
 
+static u32 destroy_obj_hashfn(const struct tcf_proto *tp)
+{
+       return jhash_3words(tp->chain->index, tp->prio,
+                           (__force __u32)tp->protocol, 0);
+}
+
+static void tcf_proto_signal_destroying(struct tcf_chain *chain,
+                                       struct tcf_proto *tp)
+{
+       struct tcf_block *block = chain->block;
+
+       mutex_lock(&block->proto_destroy_lock);
+       hash_add_rcu(block->proto_destroy_ht, &tp->destroy_ht_node,
+                    destroy_obj_hashfn(tp));
+       mutex_unlock(&block->proto_destroy_lock);
+}
+
+static bool tcf_proto_cmp(const struct tcf_proto *tp1,
+                         const struct tcf_proto *tp2)
+{
+       return tp1->chain->index == tp2->chain->index &&
+              tp1->prio == tp2->prio &&
+              tp1->protocol == tp2->protocol;
+}
+
+static bool tcf_proto_exists_destroying(struct tcf_chain *chain,
+                                       struct tcf_proto *tp)
+{
+       u32 hash = destroy_obj_hashfn(tp);
+       struct tcf_proto *iter;
+       bool found = false;
+
+       rcu_read_lock();
+       hash_for_each_possible_rcu(chain->block->proto_destroy_ht, iter,
+                                  destroy_ht_node, hash) {
+               if (tcf_proto_cmp(tp, iter)) {
+                       found = true;
+                       break;
+               }
+       }
+       rcu_read_unlock();
+
+       return found;
+}
+
+static void
+tcf_proto_signal_destroyed(struct tcf_chain *chain, struct tcf_proto *tp)
+{
+       struct tcf_block *block = chain->block;
+
+       mutex_lock(&block->proto_destroy_lock);
+       if (hash_hashed(&tp->destroy_ht_node))
+               hash_del_rcu(&tp->destroy_ht_node);
+       mutex_unlock(&block->proto_destroy_lock);
+}
+
 /* Find classifier type by string name */
 
 static const struct tcf_proto_ops *__tcf_proto_lookup_ops(const char *kind)
@@ -234,9 +291,11 @@ static void tcf_proto_get(struct tcf_proto *tp)
 static void tcf_chain_put(struct tcf_chain *chain);
 
 static void tcf_proto_destroy(struct tcf_proto *tp, bool rtnl_held,
-                             struct netlink_ext_ack *extack)
+                             bool sig_destroy, struct netlink_ext_ack *extack)
 {
        tp->ops->destroy(tp, rtnl_held, extack);
+       if (sig_destroy)
+               tcf_proto_signal_destroyed(tp->chain, tp);
        tcf_chain_put(tp->chain);
        module_put(tp->ops->owner);
        kfree_rcu(tp, rcu);
@@ -246,7 +305,7 @@ static void tcf_proto_put(struct tcf_proto *tp, bool rtnl_held,
                          struct netlink_ext_ack *extack)
 {
        if (refcount_dec_and_test(&tp->refcnt))
-               tcf_proto_destroy(tp, rtnl_held, extack);
+               tcf_proto_destroy(tp, rtnl_held, true, extack);
 }
 
 static int walker_check_empty(struct tcf_proto *tp, void *fh,
@@ -370,6 +429,7 @@ static bool tcf_chain_detach(struct tcf_chain *chain)
 static void tcf_block_destroy(struct tcf_block *block)
 {
        mutex_destroy(&block->lock);
+       mutex_destroy(&block->proto_destroy_lock);
        kfree_rcu(block, rcu);
 }
 
@@ -545,6 +605,12 @@ static void tcf_chain_flush(struct tcf_chain *chain, bool rtnl_held)
 
        mutex_lock(&chain->filter_chain_lock);
        tp = tcf_chain_dereference(chain->filter_chain, chain);
+       while (tp) {
+               tp_next = rcu_dereference_protected(tp->next, 1);
+               tcf_proto_signal_destroying(chain, tp);
+               tp = tp_next;
+       }
+       tp = tcf_chain_dereference(chain->filter_chain, chain);
        RCU_INIT_POINTER(chain->filter_chain, NULL);
        tcf_chain0_head_change(chain, NULL);
        chain->flushing = true;
@@ -844,6 +910,7 @@ static struct tcf_block *tcf_block_create(struct net *net, struct Qdisc *q,
                return ERR_PTR(-ENOMEM);
        }
        mutex_init(&block->lock);
+       mutex_init(&block->proto_destroy_lock);
        init_rwsem(&block->cb_lock);
        flow_block_init(&block->flow_block);
        INIT_LIST_HEAD(&block->chain_list);
@@ -1621,6 +1688,12 @@ static struct tcf_proto *tcf_chain_tp_insert_unique(struct tcf_chain *chain,
 
        mutex_lock(&chain->filter_chain_lock);
 
+       if (tcf_proto_exists_destroying(chain, tp_new)) {
+               mutex_unlock(&chain->filter_chain_lock);
+               tcf_proto_destroy(tp_new, rtnl_held, false, NULL);
+               return ERR_PTR(-EAGAIN);
+       }
+
        tp = tcf_chain_tp_find(chain, &chain_info,
                               protocol, prio, false);
        if (!tp)
@@ -1628,10 +1701,10 @@ static struct tcf_proto *tcf_chain_tp_insert_unique(struct tcf_chain *chain,
        mutex_unlock(&chain->filter_chain_lock);
 
        if (tp) {
-               tcf_proto_destroy(tp_new, rtnl_held, NULL);
+               tcf_proto_destroy(tp_new, rtnl_held, false, NULL);
                tp_new = tp;
        } else if (err) {
-               tcf_proto_destroy(tp_new, rtnl_held, NULL);
+               tcf_proto_destroy(tp_new, rtnl_held, false, NULL);
                tp_new = ERR_PTR(err);
        }
 
@@ -1669,6 +1742,7 @@ static void tcf_chain_tp_delete_empty(struct tcf_chain *chain,
                return;
        }
 
+       tcf_proto_signal_destroying(chain, tp);
        next = tcf_chain_dereference(chain_info.next, chain);
        if (tp == chain->filter_chain)
                tcf_chain0_head_change(chain, next);
@@ -2188,6 +2262,7 @@ static int tc_del_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
                err = -EINVAL;
                goto errout_locked;
        } else if (t->tcm_handle == 0) {
+               tcf_proto_signal_destroying(chain, tp);
                tcf_chain_tp_remove(chain, &chain_info, tp);
                mutex_unlock(&chain->filter_chain_lock);
 
index bf10bdaf5012734012b34a30e0d31faebcbeed21..8229ed4a67bee6eaa46cd365f202b6e698b1d7a9 100644 (file)
@@ -162,16 +162,20 @@ static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog,
        cls_bpf.name = obj->bpf_name;
        cls_bpf.exts_integrated = obj->exts_integrated;
 
-       if (oldprog)
+       if (oldprog && prog)
                err = tc_setup_cb_replace(block, tp, TC_SETUP_CLSBPF, &cls_bpf,
                                          skip_sw, &oldprog->gen_flags,
                                          &oldprog->in_hw_count,
                                          &prog->gen_flags, &prog->in_hw_count,
                                          true);
-       else
+       else if (prog)
                err = tc_setup_cb_add(block, tp, TC_SETUP_CLSBPF, &cls_bpf,
                                      skip_sw, &prog->gen_flags,
                                      &prog->in_hw_count, true);
+       else
+               err = tc_setup_cb_destroy(block, tp, TC_SETUP_CLSBPF, &cls_bpf,
+                                         skip_sw, &oldprog->gen_flags,
+                                         &oldprog->in_hw_count, true);
 
        if (prog && err) {
                cls_bpf_offload_cmd(tp, oldprog, prog, extack);
index 17bd8f539bc7f1d596e97c713467f953802c9b82..8769b4b8807d9d6638619059230462750bdff2ee 100644 (file)
@@ -799,9 +799,6 @@ struct Qdisc_ops pfifo_fast_ops __read_mostly = {
 };
 EXPORT_SYMBOL(pfifo_fast_ops);
 
-static struct lock_class_key qdisc_tx_busylock;
-static struct lock_class_key qdisc_running_key;
-
 struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
                          const struct Qdisc_ops *ops,
                          struct netlink_ext_ack *extack)
@@ -854,17 +851,9 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
        }
 
        spin_lock_init(&sch->busylock);
-       lockdep_set_class(&sch->busylock,
-                         dev->qdisc_tx_busylock ?: &qdisc_tx_busylock);
-
        /* seqlock has the same scope of busylock, for NOLOCK qdisc */
        spin_lock_init(&sch->seqlock);
-       lockdep_set_class(&sch->busylock,
-                         dev->qdisc_tx_busylock ?: &qdisc_tx_busylock);
-
        seqcount_init(&sch->running);
-       lockdep_set_class(&sch->running,
-                         dev->qdisc_running_key ?: &qdisc_running_key);
 
        sch->ops = ops;
        sch->flags = ops->static_flags;
@@ -875,6 +864,12 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
        dev_hold(dev);
        refcount_set(&sch->refcnt, 1);
 
+       if (sch != &noop_qdisc) {
+               lockdep_set_class(&sch->busylock, &dev->qdisc_tx_busylock_key);
+               lockdep_set_class(&sch->seqlock, &dev->qdisc_tx_busylock_key);
+               lockdep_set_class(&sch->running, &dev->qdisc_running_key);
+       }
+
        return sch;
 errout1:
        kfree(p);
@@ -1043,6 +1038,8 @@ static void attach_one_default_qdisc(struct net_device *dev,
 
        if (dev->priv_flags & IFF_NO_QUEUE)
                ops = &noqueue_qdisc_ops;
+       else if(dev->type == ARPHRD_CAN)
+               ops = &pfifo_fast_ops;
 
        qdisc = qdisc_create_dflt(dev_queue, ops, TC_H_ROOT, NULL);
        if (!qdisc) {
index 23cd1c873a2cfc24b907a8177e71dd68b0939701..be35f03b657b1eb10d224594981aa44e1776801c 100644 (file)
@@ -5,11 +5,11 @@
  * Copyright (C) 2013 Nandita Dukkipati <nanditad@google.com>
  */
 
-#include <linux/jhash.h>
 #include <linux/jiffies.h>
 #include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/vmalloc.h>
+#include <linux/siphash.h>
 #include <net/pkt_sched.h>
 #include <net/sock.h>
 
@@ -126,7 +126,7 @@ struct wdrr_bucket {
 
 struct hhf_sched_data {
        struct wdrr_bucket buckets[WDRR_BUCKET_CNT];
-       u32                perturbation;   /* hash perturbation */
+       siphash_key_t      perturbation;   /* hash perturbation */
        u32                quantum;        /* psched_mtu(qdisc_dev(sch)); */
        u32                drop_overlimit; /* number of times max qdisc packet
                                            * limit was hit
@@ -264,7 +264,7 @@ static enum wdrr_bucket_idx hhf_classify(struct sk_buff *skb, struct Qdisc *sch)
        }
 
        /* Get hashed flow-id of the skb. */
-       hash = skb_get_hash_perturb(skb, q->perturbation);
+       hash = skb_get_hash_perturb(skb, &q->perturbation);
 
        /* Check if this packet belongs to an already established HH flow. */
        flow_pos = hash & HHF_BIT_MASK;
@@ -582,7 +582,7 @@ static int hhf_init(struct Qdisc *sch, struct nlattr *opt,
 
        sch->limit = 1000;
        q->quantum = psched_mtu(qdisc_dev(sch));
-       q->perturbation = prandom_u32();
+       get_random_bytes(&q->perturbation, sizeof(q->perturbation));
        INIT_LIST_HEAD(&q->new_buckets);
        INIT_LIST_HEAD(&q->old_buckets);
 
index d448fe3068e5b9f0b35a37d921ab5a74350dc155..4074c50ac3d73100dd82bd631c127326ff49f355 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/errno.h>
 #include <linux/skbuff.h>
 #include <linux/random.h>
-#include <linux/jhash.h>
+#include <linux/siphash.h>
 #include <net/ip.h>
 #include <net/pkt_sched.h>
 #include <net/pkt_cls.h>
@@ -45,7 +45,7 @@ struct sfb_bucket {
  * (Section 4.4 of SFB reference : moving hash functions)
  */
 struct sfb_bins {
-       u32               perturbation; /* jhash perturbation */
+       siphash_key_t     perturbation; /* siphash key */
        struct sfb_bucket bins[SFB_LEVELS][SFB_NUMBUCKETS];
 };
 
@@ -217,7 +217,8 @@ static u32 sfb_compute_qlen(u32 *prob_r, u32 *avgpm_r, const struct sfb_sched_da
 
 static void sfb_init_perturbation(u32 slot, struct sfb_sched_data *q)
 {
-       q->bins[slot].perturbation = prandom_u32();
+       get_random_bytes(&q->bins[slot].perturbation,
+                        sizeof(q->bins[slot].perturbation));
 }
 
 static void sfb_swap_slot(struct sfb_sched_data *q)
@@ -314,9 +315,9 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                /* If using external classifiers, get result and record it. */
                if (!sfb_classify(skb, fl, &ret, &salt))
                        goto other_drop;
-               sfbhash = jhash_1word(salt, q->bins[slot].perturbation);
+               sfbhash = siphash_1u32(salt, &q->bins[slot].perturbation);
        } else {
-               sfbhash = skb_get_hash_perturb(skb, q->bins[slot].perturbation);
+               sfbhash = skb_get_hash_perturb(skb, &q->bins[slot].perturbation);
        }
 
 
@@ -352,7 +353,7 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                /* Inelastic flow */
                if (q->double_buffering) {
                        sfbhash = skb_get_hash_perturb(skb,
-                           q->bins[slot].perturbation);
+                           &q->bins[slot].perturbation);
                        if (!sfbhash)
                                sfbhash = 1;
                        sfb_skb_cb(skb)->hashes[slot] = sfbhash;
index 68404a9d2ce426f7027d83f0adde634cb031ef4a..c787d4d46017b4b41b8eb6d41f2b0a44560ff5bf 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/skbuff.h>
-#include <linux/jhash.h>
+#include <linux/siphash.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <net/netlink.h>
@@ -117,7 +117,7 @@ struct sfq_sched_data {
        u8              headdrop;
        u8              maxdepth;       /* limit of packets per flow */
 
-       u32             perturbation;
+       siphash_key_t   perturbation;
        u8              cur_depth;      /* depth of longest slot */
        u8              flags;
        unsigned short  scaled_quantum; /* SFQ_ALLOT_SIZE(quantum) */
@@ -157,7 +157,7 @@ static inline struct sfq_head *sfq_dep_head(struct sfq_sched_data *q, sfq_index
 static unsigned int sfq_hash(const struct sfq_sched_data *q,
                             const struct sk_buff *skb)
 {
-       return skb_get_hash_perturb(skb, q->perturbation) & (q->divisor - 1);
+       return skb_get_hash_perturb(skb, &q->perturbation) & (q->divisor - 1);
 }
 
 static unsigned int sfq_classify(struct sk_buff *skb, struct Qdisc *sch,
@@ -607,9 +607,11 @@ static void sfq_perturbation(struct timer_list *t)
        struct sfq_sched_data *q = from_timer(q, t, perturb_timer);
        struct Qdisc *sch = q->sch;
        spinlock_t *root_lock = qdisc_lock(qdisc_root_sleeping(sch));
+       siphash_key_t nkey;
 
+       get_random_bytes(&nkey, sizeof(nkey));
        spin_lock(root_lock);
-       q->perturbation = prandom_u32();
+       q->perturbation = nkey;
        if (!q->filter_list && q->tail)
                sfq_rehash(sch);
        spin_unlock(root_lock);
@@ -688,7 +690,7 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt)
        del_timer(&q->perturb_timer);
        if (q->perturb_period) {
                mod_timer(&q->perturb_timer, jiffies + q->perturb_period);
-               q->perturbation = prandom_u32();
+               get_random_bytes(&q->perturbation, sizeof(q->perturbation));
        }
        sch_tree_unlock(sch);
        kfree(p);
@@ -745,7 +747,7 @@ static int sfq_init(struct Qdisc *sch, struct nlattr *opt,
        q->quantum = psched_mtu(qdisc_dev(sch));
        q->scaled_quantum = SFQ_ALLOT_SIZE(q->quantum);
        q->perturb_period = 0;
-       q->perturbation = prandom_u32();
+       get_random_bytes(&q->perturbation, sizeof(q->perturbation));
 
        if (opt) {
                int err = sfq_change(sch, opt);
index 6719a65169d49bc0b4e3b9ddd796ed998b82b61a..7cd68628c637d6ac9e0dc00ce450ea945e5320bc 100644 (file)
@@ -1152,7 +1152,7 @@ EXPORT_SYMBOL_GPL(taprio_offload_free);
  * offload state (PENDING, ACTIVE, INACTIVE) so it can be visible in dump().
  * This is left as TODO.
  */
-void taprio_offload_config_changed(struct taprio_sched *q)
+static void taprio_offload_config_changed(struct taprio_sched *q)
 {
        struct sched_gate_list *oper, *admin;
 
@@ -1224,8 +1224,6 @@ static int taprio_enable_offload(struct net_device *dev,
                goto done;
        }
 
-       taprio_offload_config_changed(q);
-
 done:
        taprio_offload_free(offload);
 
@@ -1505,6 +1503,9 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
                        call_rcu(&admin->rcu, taprio_free_sched_cb);
 
                spin_unlock_irqrestore(&q->current_entry_lock, flags);
+
+               if (FULL_OFFLOAD_IS_ENABLED(taprio_flags))
+                       taprio_offload_config_changed(q);
        }
 
        new_admin = NULL;
index 5ca0ec0e823c4a7c62e794a05129fbd80ff29331..ffd3262b7a41eac2e3d825c3f0665066f376ea3c 100644 (file)
@@ -8476,7 +8476,7 @@ __poll_t sctp_poll(struct file *file, struct socket *sock, poll_table *wait)
        mask = 0;
 
        /* Is there any exceptional events?  */
-       if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
+       if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue))
                mask |= EPOLLERR |
                        (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0);
        if (sk->sk_shutdown & RCV_SHUTDOWN)
@@ -8485,7 +8485,7 @@ __poll_t sctp_poll(struct file *file, struct socket *sock, poll_table *wait)
                mask |= EPOLLHUP;
 
        /* Is it readable?  Reconsider this code with TCP-style support.  */
-       if (!skb_queue_empty(&sk->sk_receive_queue))
+       if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
                mask |= EPOLLIN | EPOLLRDNORM;
 
        /* The association is either gone or not ready.  */
@@ -8871,7 +8871,7 @@ struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags,
                if (sk_can_busy_loop(sk)) {
                        sk_busy_loop(sk, noblock);
 
-                       if (!skb_queue_empty(&sk->sk_receive_queue))
+                       if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
                                continue;
                }
 
@@ -9306,7 +9306,7 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk,
        newinet->inet_rcv_saddr = inet->inet_rcv_saddr;
        newinet->inet_dport = htons(asoc->peer.port);
        newinet->pmtudisc = inet->pmtudisc;
-       newinet->inet_id = asoc->next_tsn ^ jiffies;
+       newinet->inet_id = prandom_u32();
 
        newinet->uc_ttl = inet->uc_ttl;
        newinet->mc_loop = 1;
index 5b932583e4076feacb786d315bc4d6181fd9a17b..47946f489fd4f4a7bfb771a4062d962b818670ca 100644 (file)
@@ -123,6 +123,12 @@ struct proto smc_proto6 = {
 };
 EXPORT_SYMBOL_GPL(smc_proto6);
 
+static void smc_restore_fallback_changes(struct smc_sock *smc)
+{
+       smc->clcsock->file->private_data = smc->sk.sk_socket;
+       smc->clcsock->file = NULL;
+}
+
 static int __smc_release(struct smc_sock *smc)
 {
        struct sock *sk = &smc->sk;
@@ -141,6 +147,7 @@ static int __smc_release(struct smc_sock *smc)
                }
                sk->sk_state = SMC_CLOSED;
                sk->sk_state_change(sk);
+               smc_restore_fallback_changes(smc);
        }
 
        sk->sk_prot->unhash(sk);
@@ -700,8 +707,6 @@ static int __smc_connect(struct smc_sock *smc)
        int smc_type;
        int rc = 0;
 
-       sock_hold(&smc->sk); /* sock put in passive closing */
-
        if (smc->use_fallback)
                return smc_connect_fallback(smc, smc->fallback_rsn);
 
@@ -846,6 +851,8 @@ static int smc_connect(struct socket *sock, struct sockaddr *addr,
        rc = kernel_connect(smc->clcsock, addr, alen, flags);
        if (rc && rc != -EINPROGRESS)
                goto out;
+
+       sock_hold(&smc->sk); /* sock put in passive closing */
        if (flags & O_NONBLOCK) {
                if (schedule_work(&smc->connect_work))
                        smc->connect_nonblock = 1;
@@ -1291,8 +1298,8 @@ static void smc_listen_work(struct work_struct *work)
        /* check if RDMA is available */
        if (!ism_supported) { /* SMC_TYPE_R or SMC_TYPE_B */
                /* prepare RDMA check */
-               memset(&ini, 0, sizeof(ini));
                ini.is_smcd = false;
+               ini.ism_dev = NULL;
                ini.ib_lcl = &pclc->lcl;
                rc = smc_find_rdma_device(new_smc, &ini);
                if (rc) {
index 88556f0251ab974b9821b18ecf83ddb9a334fa36..2ba97ff325a5d1eb90761ad47f1a8fa5d2f743d3 100644 (file)
@@ -561,7 +561,7 @@ int smc_vlan_by_tcpsk(struct socket *clcsock, struct smc_init_info *ini)
        }
 
        rtnl_lock();
-       nest_lvl = dev_get_nest_level(ndev);
+       nest_lvl = ndev->lower_level;
        for (i = 0; i < nest_lvl; i++) {
                struct list_head *lower = &ndev->adj_list.lower;
 
index bab2da8cf17af875db0348a80b1d0488272f4990..571e6d84da3ba680706f29233898995b8d7c3705 100644 (file)
@@ -376,8 +376,6 @@ static int smc_pnet_fill_entry(struct net *net,
        return 0;
 
 error:
-       if (pnetelem->ndev)
-               dev_put(pnetelem->ndev);
        return rc;
 }
 
@@ -718,7 +716,7 @@ static struct net_device *pnet_find_base_ndev(struct net_device *ndev)
        int i, nest_lvl;
 
        rtnl_lock();
-       nest_lvl = dev_get_nest_level(ndev);
+       nest_lvl = ndev->lower_level;
        for (i = 0; i < nest_lvl; i++) {
                struct list_head *lower = &ndev->adj_list.lower;
 
index 339e8c077c2db9dadf79e6498b2361c483753be3..195b40c5dae4ba8cb364c46d4631680b257bb7fa 100644 (file)
@@ -220,7 +220,7 @@ void xprt_destroy_bc(struct rpc_xprt *xprt, unsigned int max_reqs)
                goto out;
 
        spin_lock_bh(&xprt->bc_pa_lock);
-       xprt->bc_alloc_max -= max_reqs;
+       xprt->bc_alloc_max -= min(max_reqs, xprt->bc_alloc_max);
        list_for_each_entry_safe(req, tmp, &xprt->bc_pa_list, rq_bc_pa_list) {
                dprintk("RPC:        req=%p\n", req);
                list_del(&req->rq_bc_pa_list);
@@ -307,8 +307,8 @@ void xprt_free_bc_rqst(struct rpc_rqst *req)
                 */
                dprintk("RPC:       Last session removed req=%p\n", req);
                xprt_free_allocation(req);
-               return;
        }
+       xprt_put(xprt);
 }
 
 /*
@@ -339,7 +339,7 @@ found:
                spin_unlock(&xprt->bc_pa_lock);
                if (new) {
                        if (req != new)
-                               xprt_free_bc_rqst(new);
+                               xprt_free_allocation(new);
                        break;
                } else if (req)
                        break;
@@ -368,6 +368,7 @@ void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied)
        set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
 
        dprintk("RPC:       add callback request to list\n");
+       xprt_get(xprt);
        spin_lock(&bc_serv->sv_cb_lock);
        list_add(&req->rq_bc_list, &bc_serv->sv_cb_list);
        wake_up(&bc_serv->sv_cb_waitq);
index 8a45b3ccc31343aa089e9bed8837247256ecd61d..41df4c507193b39410f8c99f65c9fa0f795380c1 100644 (file)
@@ -1942,6 +1942,11 @@ static void xprt_destroy_cb(struct work_struct *work)
        rpc_destroy_wait_queue(&xprt->sending);
        rpc_destroy_wait_queue(&xprt->backlog);
        kfree(xprt->servername);
+       /*
+        * Destroy any existing back channel
+        */
+       xprt_destroy_backchannel(xprt, UINT_MAX);
+
        /*
         * Tear down transport state and free the rpc_xprt
         */
index 50e075fcdd8feb13bc9747c613373e9b2570c073..b458bf53ca699adc271a790b7cb082af8aa31633 100644 (file)
@@ -163,6 +163,7 @@ void xprt_rdma_bc_free_rqst(struct rpc_rqst *rqst)
        spin_lock(&xprt->bc_pa_lock);
        list_add_tail(&rqst->rq_bc_pa_list, &xprt->bc_pa_list);
        spin_unlock(&xprt->bc_pa_lock);
+       xprt_put(xprt);
 }
 
 static struct rpc_rqst *rpcrdma_bc_rqst_get(struct rpcrdma_xprt *r_xprt)
@@ -259,6 +260,7 @@ void rpcrdma_bc_receive_call(struct rpcrdma_xprt *r_xprt,
 
        /* Queue rqst for ULP's callback service */
        bc_serv = xprt->bc_serv;
+       xprt_get(xprt);
        spin_lock(&bc_serv->sv_cb_lock);
        list_add(&rqst->rq_bc_list, &bc_serv->sv_cb_list);
        spin_unlock(&bc_serv->sv_cb_lock);
index f8bbc4aab21397ecb184a6b869327a5b124cb7e4..4b92b196cfa668c9ee59b9dae4e83bb7b5b5ba3d 100644 (file)
@@ -740,7 +740,7 @@ static __poll_t tipc_poll(struct file *file, struct socket *sock,
                /* fall through */
        case TIPC_LISTEN:
        case TIPC_CONNECTING:
-               if (!skb_queue_empty(&sk->sk_receive_queue))
+               if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
                        revents |= EPOLLIN | EPOLLRDNORM;
                break;
        case TIPC_OPEN:
@@ -748,7 +748,7 @@ static __poll_t tipc_poll(struct file *file, struct socket *sock,
                        revents |= EPOLLOUT;
                if (!tipc_sk_type_connectionless(sk))
                        break;
-               if (skb_queue_empty(&sk->sk_receive_queue))
+               if (skb_queue_empty_lockless(&sk->sk_receive_queue))
                        break;
                revents |= EPOLLIN | EPOLLRDNORM;
                break;
index f959487c5cd18848235891c789edc72596417c55..683d0083769350e3fa57c356e8bb43a5d8e350b4 100644 (file)
@@ -523,8 +523,10 @@ last_record:
 int tls_device_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
 {
        unsigned char record_type = TLS_RECORD_TYPE_DATA;
+       struct tls_context *tls_ctx = tls_get_ctx(sk);
        int rc;
 
+       mutex_lock(&tls_ctx->tx_lock);
        lock_sock(sk);
 
        if (unlikely(msg->msg_controllen)) {
@@ -538,12 +540,14 @@ int tls_device_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
 
 out:
        release_sock(sk);
+       mutex_unlock(&tls_ctx->tx_lock);
        return rc;
 }
 
 int tls_device_sendpage(struct sock *sk, struct page *page,
                        int offset, size_t size, int flags)
 {
+       struct tls_context *tls_ctx = tls_get_ctx(sk);
        struct iov_iter msg_iter;
        char *kaddr = kmap(page);
        struct kvec iov;
@@ -552,6 +556,7 @@ int tls_device_sendpage(struct sock *sk, struct page *page,
        if (flags & MSG_SENDPAGE_NOTLAST)
                flags |= MSG_MORE;
 
+       mutex_lock(&tls_ctx->tx_lock);
        lock_sock(sk);
 
        if (flags & MSG_OOB) {
@@ -568,6 +573,7 @@ int tls_device_sendpage(struct sock *sk, struct page *page,
 
 out:
        release_sock(sk);
+       mutex_unlock(&tls_ctx->tx_lock);
        return rc;
 }
 
@@ -623,9 +629,11 @@ static int tls_device_push_pending_record(struct sock *sk, int flags)
 
 void tls_device_write_space(struct sock *sk, struct tls_context *ctx)
 {
-       if (!sk->sk_write_pending && tls_is_partially_sent_record(ctx)) {
+       if (tls_is_partially_sent_record(ctx)) {
                gfp_t sk_allocation = sk->sk_allocation;
 
+               WARN_ON_ONCE(sk->sk_write_pending);
+
                sk->sk_allocation = GFP_ATOMIC;
                tls_push_partial_record(sk, ctx,
                                        MSG_DONTWAIT | MSG_NOSIGNAL |
index ac88877dcade8c7227a3fc42d872a53ce53c9acd..0775ae40fcfb49435d9127ac87e473f220b34016 100644 (file)
@@ -267,6 +267,7 @@ void tls_ctx_free(struct sock *sk, struct tls_context *ctx)
 
        memzero_explicit(&ctx->crypto_send, sizeof(ctx->crypto_send));
        memzero_explicit(&ctx->crypto_recv, sizeof(ctx->crypto_recv));
+       mutex_destroy(&ctx->tx_lock);
 
        if (sk)
                kfree_rcu(ctx, rcu);
@@ -612,6 +613,7 @@ static struct tls_context *create_ctx(struct sock *sk)
        if (!ctx)
                return NULL;
 
+       mutex_init(&ctx->tx_lock);
        rcu_assign_pointer(icsk->icsk_ulp_data, ctx);
        ctx->sk_proto = sk->sk_prot;
        return ctx;
index c2b5e0d2ba1a2a2308a375dfccb49a3760aae64e..446f23c1f3ce4a3e6b2d2978060de7c159b2b678 100644 (file)
@@ -897,15 +897,9 @@ int tls_sw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
        if (msg->msg_flags & ~(MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL))
                return -ENOTSUPP;
 
+       mutex_lock(&tls_ctx->tx_lock);
        lock_sock(sk);
 
-       /* Wait till there is any pending write on socket */
-       if (unlikely(sk->sk_write_pending)) {
-               ret = wait_on_pending_writer(sk, &timeo);
-               if (unlikely(ret))
-                       goto send_end;
-       }
-
        if (unlikely(msg->msg_controllen)) {
                ret = tls_proccess_cmsg(sk, msg, &record_type);
                if (ret) {
@@ -1091,6 +1085,7 @@ send_end:
        ret = sk_stream_error(sk, msg->msg_flags, ret);
 
        release_sock(sk);
+       mutex_unlock(&tls_ctx->tx_lock);
        return copied ? copied : ret;
 }
 
@@ -1114,13 +1109,6 @@ static int tls_sw_do_sendpage(struct sock *sk, struct page *page,
        eor = !(flags & (MSG_MORE | MSG_SENDPAGE_NOTLAST));
        sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk);
 
-       /* Wait till there is any pending write on socket */
-       if (unlikely(sk->sk_write_pending)) {
-               ret = wait_on_pending_writer(sk, &timeo);
-               if (unlikely(ret))
-                       goto sendpage_end;
-       }
-
        /* Call the sk_stream functions to manage the sndbuf mem. */
        while (size > 0) {
                size_t copy, required_size;
@@ -1219,15 +1207,18 @@ sendpage_end:
 int tls_sw_sendpage(struct sock *sk, struct page *page,
                    int offset, size_t size, int flags)
 {
+       struct tls_context *tls_ctx = tls_get_ctx(sk);
        int ret;
 
        if (flags & ~(MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL |
                      MSG_SENDPAGE_NOTLAST | MSG_SENDPAGE_NOPOLICY))
                return -ENOTSUPP;
 
+       mutex_lock(&tls_ctx->tx_lock);
        lock_sock(sk);
        ret = tls_sw_do_sendpage(sk, page, offset, size, flags);
        release_sock(sk);
+       mutex_unlock(&tls_ctx->tx_lock);
        return ret;
 }
 
@@ -2170,9 +2161,11 @@ static void tx_work_handler(struct work_struct *work)
 
        if (!test_and_clear_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask))
                return;
+       mutex_lock(&tls_ctx->tx_lock);
        lock_sock(sk);
        tls_tx_records(sk, -1);
        release_sock(sk);
+       mutex_unlock(&tls_ctx->tx_lock);
 }
 
 void tls_sw_write_space(struct sock *sk, struct tls_context *ctx)
@@ -2180,12 +2173,9 @@ void tls_sw_write_space(struct sock *sk, struct tls_context *ctx)
        struct tls_sw_context_tx *tx_ctx = tls_sw_ctx_tx(ctx);
 
        /* Schedule the transmission if tx list is ready */
-       if (is_tx_ready(tx_ctx) && !sk->sk_write_pending) {
-               /* Schedule the transmission */
-               if (!test_and_set_bit(BIT_TX_SCHEDULED,
-                                     &tx_ctx->tx_bitmask))
-                       schedule_delayed_work(&tx_ctx->tx_work.work, 0);
-       }
+       if (is_tx_ready(tx_ctx) &&
+           !test_and_set_bit(BIT_TX_SCHEDULED, &tx_ctx->tx_bitmask))
+               schedule_delayed_work(&tx_ctx->tx_work.work, 0);
 }
 
 void tls_sw_strparser_arm(struct sock *sk, struct tls_context *tls_ctx)
index 67e87db5877f1132b52b0c93d349983873fec38f..0d8da809bea2e6053c6bd5687ae19ab3f3ca617a 100644 (file)
@@ -2599,7 +2599,7 @@ static __poll_t unix_poll(struct file *file, struct socket *sock, poll_table *wa
                mask |= EPOLLRDHUP | EPOLLIN | EPOLLRDNORM;
 
        /* readable? */
-       if (!skb_queue_empty(&sk->sk_receive_queue))
+       if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
                mask |= EPOLLIN | EPOLLRDNORM;
 
        /* Connection-based need to check for termination and startup */
@@ -2628,7 +2628,7 @@ static __poll_t unix_dgram_poll(struct file *file, struct socket *sock,
        mask = 0;
 
        /* exceptional events? */
-       if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
+       if (sk->sk_err || !skb_queue_empty_lockless(&sk->sk_error_queue))
                mask |= EPOLLERR |
                        (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? EPOLLPRI : 0);
 
@@ -2638,7 +2638,7 @@ static __poll_t unix_dgram_poll(struct file *file, struct socket *sock,
                mask |= EPOLLHUP;
 
        /* readable? */
-       if (!skb_queue_empty(&sk->sk_receive_queue))
+       if (!skb_queue_empty_lockless(&sk->sk_receive_queue))
                mask |= EPOLLIN | EPOLLRDNORM;
 
        /* Connection-based need to check for termination and startup */
index 2ab43b2bba31bca91de7fe7840c487e07683a922..582a3e4dfce295fa67100468335bc8dbf8dc1095 100644 (file)
@@ -870,7 +870,7 @@ static __poll_t vsock_poll(struct file *file, struct socket *sock,
                 * the queue and write as long as the socket isn't shutdown for
                 * sending.
                 */
-               if (!skb_queue_empty(&sk->sk_receive_queue) ||
+               if (!skb_queue_empty_lockless(&sk->sk_receive_queue) ||
                    (sk->sk_shutdown & RCV_SHUTDOWN)) {
                        mask |= EPOLLIN | EPOLLRDNORM;
                }
index 481f7f8a16551ce8de4f6e3100464a32b0033997..fb2060dffb0afb13ba160c6159ff85d40c8ac0ca 100644 (file)
@@ -947,9 +947,11 @@ virtio_transport_recv_connected(struct sock *sk,
                if (le32_to_cpu(pkt->hdr.flags) & VIRTIO_VSOCK_SHUTDOWN_SEND)
                        vsk->peer_shutdown |= SEND_SHUTDOWN;
                if (vsk->peer_shutdown == SHUTDOWN_MASK &&
-                   vsock_stream_has_data(vsk) <= 0) {
-                       sock_set_flag(sk, SOCK_DONE);
-                       sk->sk_state = TCP_CLOSING;
+                   vsock_stream_has_data(vsk) <= 0 &&
+                   !sock_flag(sk, SOCK_DONE)) {
+                       (void)virtio_transport_reset(vsk, NULL);
+
+                       virtio_transport_do_close(vsk, true);
                }
                if (le32_to_cpu(pkt->hdr.flags))
                        sk->sk_state_change(sk);
index e851cafd8e2f631fb4461676155ed9210eea8ec1..fcac5c6366e16d5d40e69a4cdc9378c7ba926528 100644 (file)
@@ -204,6 +204,11 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
                return false;
        }
 
+       /* channel 14 is only for IEEE 802.11b */
+       if (chandef->center_freq1 == 2484 &&
+           chandef->width != NL80211_CHAN_WIDTH_20_NOHT)
+               return false;
+
        if (cfg80211_chandef_is_edmg(chandef) &&
            !cfg80211_edmg_chandef_valid(chandef))
                return false;
index 4453dd375de9dc4ea15d5a029157b7d47bfd3b79..7b72286922f7263acb9c0179d4110725a4311aba 100644 (file)
@@ -393,7 +393,7 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        [NL80211_ATTR_MNTR_FLAGS] = { /* NLA_NESTED can't be empty */ },
        [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
                                   .len = IEEE80211_MAX_MESH_ID_LEN },
-       [NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 },
+       [NL80211_ATTR_MPATH_NEXT_HOP] = NLA_POLICY_ETH_ADDR_COMPAT,
 
        [NL80211_ATTR_REG_ALPHA2] = { .type = NLA_STRING, .len = 2 },
        [NL80211_ATTR_REG_RULES] = { .type = NLA_NESTED },
index 419eb12c1e932d17f072b75288a7726c8b96da52..5b4ed5bbc542555a4ebd4e8fcfbb6dccf10e9f3f 100644 (file)
@@ -1559,7 +1559,8 @@ bool ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef,
        }
 
        if (freq == 2484) {
-               if (chandef->width > NL80211_CHAN_WIDTH_40)
+               /* channel 14 is only for IEEE 802.11b */
+               if (chandef->width != NL80211_CHAN_WIDTH_20_NOHT)
                        return false;
 
                *op_class = 82; /* channel 14 */
index 16d5f353163a166dd4f29a8ae2b99aea63629c22..3049af269fbf6b3fc3fc0f8d40651ba39d187ed8 100644 (file)
@@ -27,6 +27,9 @@ void xdp_add_sk_umem(struct xdp_umem *umem, struct xdp_sock *xs)
 {
        unsigned long flags;
 
+       if (!xs->tx)
+               return;
+
        spin_lock_irqsave(&umem->xsk_list_lock, flags);
        list_add_rcu(&xs->list, &umem->xsk_list);
        spin_unlock_irqrestore(&umem->xsk_list_lock, flags);
@@ -36,6 +39,9 @@ void xdp_del_sk_umem(struct xdp_umem *umem, struct xdp_sock *xs)
 {
        unsigned long flags;
 
+       if (!xs->tx)
+               return;
+
        spin_lock_irqsave(&umem->xsk_list_lock, flags);
        list_del_rcu(&xs->list);
        spin_unlock_irqrestore(&umem->xsk_list_lock, flags);
index 1d9be26b4edd79b2ad0f4661411790d9e71d45dd..42b571cde17781f9951a90b44d9b0f85f37a3a72 100644 (file)
@@ -176,6 +176,7 @@ KBUILD_HOSTCFLAGS += -I$(srctree)/tools/lib/bpf/
 KBUILD_HOSTCFLAGS += -I$(srctree)/tools/testing/selftests/bpf/
 KBUILD_HOSTCFLAGS += -I$(srctree)/tools/lib/ -I$(srctree)/tools/include
 KBUILD_HOSTCFLAGS += -I$(srctree)/tools/perf
+KBUILD_HOSTCFLAGS += -DHAVE_ATTR_TEST=0
 
 HOSTCFLAGS_bpf_load.o += -I$(objtree)/usr/include -Wno-unused-variable
 
index 7b7c2fafbc687d2f9cb0316089c8e124bf9a9fd0..be984aa29b759cb1e42bb2c8d6e42eb4b061fb9c 100644 (file)
@@ -99,7 +99,8 @@ lx-symbols command."""
             attrs[n]['name'].string(): attrs[n]['address']
             for n in range(int(sect_attrs['nsections']))}
         args = []
-        for section_name in [".data", ".data..read_mostly", ".rodata", ".bss"]:
+        for section_name in [".data", ".data..read_mostly", ".rodata", ".bss",
+                             ".text", ".text.hot", ".text.unlikely"]:
             address = section_name_to_address.get(section_name)
             if address:
                 args.append(" -s {name} {addr}".format(
index 936d3ad23c83eb35a7fd6cb0faa6443c6e779089..d2a30a7b3f07cc884889555948054acb911e1fc7 100644 (file)
@@ -348,26 +348,38 @@ static enum export export_from_sec(struct elf_info *elf, unsigned int sec)
                return export_unknown;
 }
 
-static char *sym_extract_namespace(const char **symname)
+static const char *namespace_from_kstrtabns(struct elf_info *info,
+                                           Elf_Sym *kstrtabns)
 {
-       char *namespace = NULL;
-       char *ns_separator;
+       char *value = info->ksymtab_strings + kstrtabns->st_value;
+       return value[0] ? value : NULL;
+}
+
+static void sym_update_namespace(const char *symname, const char *namespace)
+{
+       struct symbol *s = find_symbol(symname);
 
-       ns_separator = strchr(*symname, '.');
-       if (ns_separator) {
-               namespace = NOFAIL(strndup(*symname, ns_separator - *symname));
-               *symname = ns_separator + 1;
+       /*
+        * That symbol should have been created earlier and thus this is
+        * actually an assertion.
+        */
+       if (!s) {
+               merror("Could not update namespace(%s) for symbol %s\n",
+                      namespace, symname);
+               return;
        }
 
-       return namespace;
+       free(s->namespace);
+       s->namespace =
+               namespace && namespace[0] ? NOFAIL(strdup(namespace)) : NULL;
 }
 
 /**
  * Add an exported symbol - it may have already been added without a
  * CRC, in this case just update the CRC
  **/
-static struct symbol *sym_add_exported(const char *name, const char *namespace,
-                                      struct module *mod, enum export export)
+static struct symbol *sym_add_exported(const char *name, struct module *mod,
+                                      enum export export)
 {
        struct symbol *s = find_symbol(name);
 
@@ -383,8 +395,6 @@ static struct symbol *sym_add_exported(const char *name, const char *namespace,
                        s->module = mod;
                }
        }
-       free(s->namespace);
-       s->namespace = namespace ? strdup(namespace) : NULL;
        s->preloaded = 0;
        s->vmlinux   = is_vmlinux(mod->name);
        s->kernel    = 0;
@@ -583,6 +593,10 @@ static int parse_elf(struct elf_info *info, const char *filename)
                        info->export_unused_gpl_sec = i;
                else if (strcmp(secname, "__ksymtab_gpl_future") == 0)
                        info->export_gpl_future_sec = i;
+               else if (strcmp(secname, "__ksymtab_strings") == 0)
+                       info->ksymtab_strings = (void *)hdr +
+                                               sechdrs[i].sh_offset -
+                                               sechdrs[i].sh_addr;
 
                if (sechdrs[i].sh_type == SHT_SYMTAB) {
                        unsigned int sh_link_idx;
@@ -672,7 +686,6 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
        enum export export;
        bool is_crc = false;
        const char *name;
-       char *namespace;
 
        if ((!is_vmlinux(mod->name) || mod->is_dot_o) &&
            strstarts(symname, "__ksymtab"))
@@ -745,9 +758,7 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
                /* All exported symbols */
                if (strstarts(symname, "__ksymtab_")) {
                        name = symname + strlen("__ksymtab_");
-                       namespace = sym_extract_namespace(&name);
-                       sym_add_exported(name, namespace, mod, export);
-                       free(namespace);
+                       sym_add_exported(name, mod, export);
                }
                if (strcmp(symname, "init_module") == 0)
                        mod->has_init = 1;
@@ -2043,6 +2054,16 @@ static void read_symbols(const char *modname)
                handle_moddevtable(mod, &info, sym, symname);
        }
 
+       /* Apply symbol namespaces from __kstrtabns_<symbol> entries. */
+       for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
+               symname = remove_dot(info.strtab + sym->st_name);
+
+               if (strstarts(symname, "__kstrtabns_"))
+                       sym_update_namespace(symname + strlen("__kstrtabns_"),
+                                            namespace_from_kstrtabns(&info,
+                                                                     sym));
+       }
+
        // check for static EXPORT_SYMBOL_* functions && global vars
        for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
                unsigned char bind = ELF_ST_BIND(sym->st_info);
@@ -2196,7 +2217,7 @@ static int check_exports(struct module *mod)
                else
                        basename = mod->name;
 
-               if (exp->namespace && exp->namespace[0]) {
+               if (exp->namespace) {
                        add_namespace(&mod->required_namespaces,
                                      exp->namespace);
 
@@ -2454,12 +2475,12 @@ static void read_dump(const char *fname, unsigned int kernel)
                        mod = new_module(modname);
                        mod->skip = 1;
                }
-               s = sym_add_exported(symname, namespace, mod,
-                                    export_no(export));
+               s = sym_add_exported(symname, mod, export_no(export));
                s->kernel    = kernel;
                s->preloaded = 1;
                s->is_static = 0;
                sym_update_crc(symname, mod, crc, export_no(export));
+               sym_update_namespace(symname, namespace);
        }
        release_file(file, size);
        return;
index 92a926d375d287c0629facef7de45cee938aa99c..ad271bc6c3130410ab9f515b75d1efea26f89b97 100644 (file)
@@ -143,6 +143,7 @@ struct elf_info {
        Elf_Section  export_gpl_sec;
        Elf_Section  export_unused_gpl_sec;
        Elf_Section  export_gpl_future_sec;
+       char         *ksymtab_strings;
        char         *strtab;
        char         *modinfo;
        unsigned int modinfo_len;
index 3754dac13b312f16a655e73af68d4912c8da7c9b..04cea092167368dad12f213b9bdd6b32562aac66 100644 (file)
@@ -31,12 +31,12 @@ generate_deps() {
        local mod_file=`echo $@ | sed -e 's/\.ko/\.mod/'`
        local ns_deps_file=`echo $@ | sed -e 's/\.ko/\.ns_deps/'`
        if [ ! -f "$ns_deps_file" ]; then return; fi
-       local mod_source_files=`cat $mod_file | sed -n 1p                      \
+       local mod_source_files="`cat $mod_file | sed -n 1p                      \
                                              | sed -e 's/\.o/\.c/g'           \
-                                             | sed "s/[^ ]* */${srctree}\/&/g"`
+                                             | sed "s|[^ ]* *|${srctree}/&|g"`"
        for ns in `cat $ns_deps_file`; do
                echo "Adding namespace $ns to module $mod_name (if needed)."
-               generate_deps_for_ns $ns $mod_source_files
+               generate_deps_for_ns $ns "$mod_source_files"
                # sort the imports
                for source_file in $mod_source_files; do
                        sed '/MODULE_IMPORT_NS/Q' $source_file > ${source_file}.tmp
index 8a10b43daf74e5c3b86a06e19b4856b684dacc66..40b790536defaf8dcdad0655d4423f33c94dcd06 100644 (file)
@@ -20,6 +20,7 @@ static const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {
        [LOCKDOWN_NONE] = "none",
        [LOCKDOWN_MODULE_SIGNATURE] = "unsigned module loading",
        [LOCKDOWN_DEV_MEM] = "/dev/mem,kmem,port",
+       [LOCKDOWN_EFI_TEST] = "/dev/efi_test access",
        [LOCKDOWN_KEXEC] = "kexec of unsigned images",
        [LOCKDOWN_HIBERNATION] = "hibernation",
        [LOCKDOWN_PCI_ACCESS] = "direct PCI access",
index 41905afada63fee667d34478301217e05b98d3c5..f34ce564d92c481791c4121c5b4c8b64f953be9e 100644 (file)
@@ -528,7 +528,7 @@ static int snd_compress_check_input(struct snd_compr_params *params)
 {
        /* first let's check the buffer parameter's */
        if (params->buffer.fragment_size == 0 ||
-           params->buffer.fragments > INT_MAX / params->buffer.fragment_size ||
+           params->buffer.fragments > U32_MAX / params->buffer.fragment_size ||
            params->buffer.fragments == 0)
                return -EINVAL;
 
index 5c9fbf3f43407a33aeb9dcbb338d6b98c9f18dc3..59ae21b0bb936c0757d58573b1bac3ed3defcb1a 100644 (file)
@@ -226,7 +226,8 @@ static int snd_timer_check_master(struct snd_timer_instance *master)
        return 0;
 }
 
-static int snd_timer_close_locked(struct snd_timer_instance *timeri);
+static int snd_timer_close_locked(struct snd_timer_instance *timeri,
+                                 struct device **card_devp_to_put);
 
 /*
  * open a timer instance
@@ -238,6 +239,7 @@ int snd_timer_open(struct snd_timer_instance **ti,
 {
        struct snd_timer *timer;
        struct snd_timer_instance *timeri = NULL;
+       struct device *card_dev_to_put = NULL;
        int err;
 
        mutex_lock(&register_mutex);
@@ -261,7 +263,7 @@ int snd_timer_open(struct snd_timer_instance **ti,
                list_add_tail(&timeri->open_list, &snd_timer_slave_list);
                err = snd_timer_check_slave(timeri);
                if (err < 0) {
-                       snd_timer_close_locked(timeri);
+                       snd_timer_close_locked(timeri, &card_dev_to_put);
                        timeri = NULL;
                }
                goto unlock;
@@ -282,11 +284,11 @@ int snd_timer_open(struct snd_timer_instance **ti,
                goto unlock;
        }
        if (!list_empty(&timer->open_list_head)) {
-               timeri = list_entry(timer->open_list_head.next,
+               struct snd_timer_instance *t =
+                       list_entry(timer->open_list_head.next,
                                    struct snd_timer_instance, open_list);
-               if (timeri->flags & SNDRV_TIMER_IFLG_EXCLUSIVE) {
+               if (t->flags & SNDRV_TIMER_IFLG_EXCLUSIVE) {
                        err = -EBUSY;
-                       timeri = NULL;
                        goto unlock;
                }
        }
@@ -313,7 +315,7 @@ int snd_timer_open(struct snd_timer_instance **ti,
                        timeri = NULL;
 
                        if (timer->card)
-                               put_device(&timer->card->card_dev);
+                               card_dev_to_put = &timer->card->card_dev;
                        module_put(timer->module);
                        goto unlock;
                }
@@ -323,12 +325,15 @@ int snd_timer_open(struct snd_timer_instance **ti,
        timer->num_instances++;
        err = snd_timer_check_master(timeri);
        if (err < 0) {
-               snd_timer_close_locked(timeri);
+               snd_timer_close_locked(timeri, &card_dev_to_put);
                timeri = NULL;
        }
 
  unlock:
        mutex_unlock(&register_mutex);
+       /* put_device() is called after unlock for avoiding deadlock */
+       if (card_dev_to_put)
+               put_device(card_dev_to_put);
        *ti = timeri;
        return err;
 }
@@ -338,7 +343,8 @@ EXPORT_SYMBOL(snd_timer_open);
  * close a timer instance
  * call this with register_mutex down.
  */
-static int snd_timer_close_locked(struct snd_timer_instance *timeri)
+static int snd_timer_close_locked(struct snd_timer_instance *timeri,
+                                 struct device **card_devp_to_put)
 {
        struct snd_timer *timer = timeri->timer;
        struct snd_timer_instance *slave, *tmp;
@@ -395,7 +401,7 @@ static int snd_timer_close_locked(struct snd_timer_instance *timeri)
                        timer->hw.close(timer);
                /* release a card refcount for safe disconnection */
                if (timer->card)
-                       put_device(&timer->card->card_dev);
+                       *card_devp_to_put = &timer->card->card_dev;
                module_put(timer->module);
        }
 
@@ -407,14 +413,18 @@ static int snd_timer_close_locked(struct snd_timer_instance *timeri)
  */
 int snd_timer_close(struct snd_timer_instance *timeri)
 {
+       struct device *card_dev_to_put = NULL;
        int err;
 
        if (snd_BUG_ON(!timeri))
                return -ENXIO;
 
        mutex_lock(&register_mutex);
-       err = snd_timer_close_locked(timeri);
+       err = snd_timer_close_locked(timeri, &card_dev_to_put);
        mutex_unlock(&register_mutex);
+       /* put_device() is called after unlock for avoiding deadlock */
+       if (card_dev_to_put)
+               put_device(card_dev_to_put);
        return err;
 }
 EXPORT_SYMBOL(snd_timer_close);
index 32b864bee25f109b04c704274de4b2a543e56352..06d6a37cd8532427dbbd286e5085a592f5e2914b 100644 (file)
@@ -27,6 +27,8 @@
 #define SAFFIRE_CLOCK_SOURCE_SPDIF             1
 
 /* clock sources as returned from register of Saffire Pro 10 and 26 */
+#define SAFFIREPRO_CLOCK_SOURCE_SELECT_MASK    0x000000ff
+#define SAFFIREPRO_CLOCK_SOURCE_DETECT_MASK    0x0000ff00
 #define SAFFIREPRO_CLOCK_SOURCE_INTERNAL       0
 #define SAFFIREPRO_CLOCK_SOURCE_SKIP           1 /* never used on hardware */
 #define SAFFIREPRO_CLOCK_SOURCE_SPDIF          2
@@ -189,6 +191,7 @@ saffirepro_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id)
                map = saffirepro_clk_maps[1];
 
        /* In a case that this driver cannot handle the value of register. */
+       value &= SAFFIREPRO_CLOCK_SOURCE_SELECT_MASK;
        if (value >= SAFFIREPRO_CLOCK_SOURCE_COUNT || map[value] < 0) {
                err = -EIO;
                goto end;
index 73fee991bd75a500d25f074d78d6c71843505881..6c1497d9f52bac0e62b0cfce5bb0e59c64c70d31 100644 (file)
@@ -252,8 +252,7 @@ end:
        return err;
 }
 
-static unsigned int
-map_data_channels(struct snd_bebob *bebob, struct amdtp_stream *s)
+static int map_data_channels(struct snd_bebob *bebob, struct amdtp_stream *s)
 {
        unsigned int sec, sections, ch, channels;
        unsigned int pcm, midi, location;
index d3999e7b070542e8aeb3a435abf52f6f44b022a8..7e7be8e4dcf9c3d7dd170ad2cbea0b949ec7f9e1 100644 (file)
@@ -447,8 +447,6 @@ static void azx_int_disable(struct hdac_bus *bus)
        list_for_each_entry(azx_dev, &bus->stream_list, list)
                snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_INT_MASK, 0);
 
-       synchronize_irq(bus->irq);
-
        /* disable SIE for all streams */
        snd_hdac_chip_writeb(bus, INTCTL, 0);
 
index 240f4ca76391fbefa80074a182dc9ab88f4394e9..cf53fbd872ee34526d277bd4f479c1a5024b32b6 100644 (file)
@@ -1348,9 +1348,9 @@ static int azx_free(struct azx *chip)
        }
 
        if (bus->chip_init) {
-               azx_stop_chip(chip);
                azx_clear_irq_pending(chip);
                azx_stop_all_streams(chip);
+               azx_stop_chip(chip);
        }
 
        if (bus->irq >= 0)
@@ -2399,6 +2399,12 @@ static const struct pci_device_id azx_ids[] = {
        /* Icelake */
        { PCI_DEVICE(0x8086, 0x34c8),
          .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
+       /* Jasperlake */
+       { PCI_DEVICE(0x8086, 0x38c8),
+         .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
+       /* Tigerlake */
+       { PCI_DEVICE(0x8086, 0xa0c8),
+         .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
        /* Elkhart Lake */
        { PCI_DEVICE(0x8086, 0x4b55),
          .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
index 6d1fb7c11f17ed93b5ca4f2f12e295c3970b6ec4..b7a1abb3e2318ecc1051e6b8bbef49ea6fa46f73 100644 (file)
@@ -7604,7 +7604,7 @@ static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
        /* Delay enabling the HP amp, to let the mic-detection
         * state machine run.
         */
-       cancel_delayed_work_sync(&spec->unsol_hp_work);
+       cancel_delayed_work(&spec->unsol_hp_work);
        schedule_delayed_work(&spec->unsol_hp_work, msecs_to_jiffies(500));
        tbl = snd_hda_jack_tbl_get(codec, cb->nid);
        if (tbl)
index 795cbda32cbbc9c8fd31bc26557223a3245aff95..3c720703ebb8338c4ad9eef13ec5d90de9600866 100644 (file)
@@ -145,6 +145,7 @@ struct hdmi_spec {
        struct snd_array pins; /* struct hdmi_spec_per_pin */
        struct hdmi_pcm pcm_rec[16];
        struct mutex pcm_lock;
+       struct mutex bind_lock; /* for audio component binding */
        /* pcm_bitmap means which pcms have been assigned to pins*/
        unsigned long pcm_bitmap;
        int pcm_used;   /* counter of pcm_rec[] */
@@ -2258,7 +2259,7 @@ static int generic_hdmi_init(struct hda_codec *codec)
        struct hdmi_spec *spec = codec->spec;
        int pin_idx;
 
-       mutex_lock(&spec->pcm_lock);
+       mutex_lock(&spec->bind_lock);
        spec->use_jack_detect = !codec->jackpoll_interval;
        for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
                struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
@@ -2275,7 +2276,7 @@ static int generic_hdmi_init(struct hda_codec *codec)
                        snd_hda_jack_detect_enable_callback(codec, pin_nid,
                                                            jack_callback);
        }
-       mutex_unlock(&spec->pcm_lock);
+       mutex_unlock(&spec->bind_lock);
        return 0;
 }
 
@@ -2382,6 +2383,7 @@ static int alloc_generic_hdmi(struct hda_codec *codec)
        spec->ops = generic_standard_hdmi_ops;
        spec->dev_num = 1;      /* initialize to 1 */
        mutex_init(&spec->pcm_lock);
+       mutex_init(&spec->bind_lock);
        snd_hdac_register_chmap_ops(&codec->core, &spec->chmap);
 
        spec->chmap.ops.get_chmap = hdmi_get_chmap;
@@ -2451,7 +2453,7 @@ static void generic_acomp_notifier_set(struct drm_audio_component *acomp,
        int i;
 
        spec = container_of(acomp->audio_ops, struct hdmi_spec, drm_audio_ops);
-       mutex_lock(&spec->pcm_lock);
+       mutex_lock(&spec->bind_lock);
        spec->use_acomp_notifier = use_acomp;
        spec->codec->relaxed_resume = use_acomp;
        /* reprogram each jack detection logic depending on the notifier */
@@ -2461,7 +2463,7 @@ static void generic_acomp_notifier_set(struct drm_audio_component *acomp,
                                              get_pin(spec, i)->pin_nid,
                                              use_acomp);
        }
-       mutex_unlock(&spec->pcm_lock);
+       mutex_unlock(&spec->bind_lock);
 }
 
 /* enable / disable the notifier via master bind / unbind */
@@ -2849,6 +2851,18 @@ static int patch_i915_icl_hdmi(struct hda_codec *codec)
        return intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map));
 }
 
+static int patch_i915_tgl_hdmi(struct hda_codec *codec)
+{
+       /*
+        * pin to port mapping table where the value indicate the pin number and
+        * the index indicate the port number with 1 base.
+        */
+       static const int map[] = {0x4, 0x6, 0x8, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
+
+       return intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map));
+}
+
+
 /* Intel Baytrail and Braswell; with eld notifier */
 static int patch_i915_byt_hdmi(struct hda_codec *codec)
 {
@@ -4151,6 +4165,7 @@ HDA_CODEC_ENTRY(0x8086280b, "Kabylake HDMI",      patch_i915_hsw_hdmi),
 HDA_CODEC_ENTRY(0x8086280c, "Cannonlake HDMI", patch_i915_glk_hdmi),
 HDA_CODEC_ENTRY(0x8086280d, "Geminilake HDMI", patch_i915_glk_hdmi),
 HDA_CODEC_ENTRY(0x8086280f, "Icelake HDMI",    patch_i915_icl_hdmi),
+HDA_CODEC_ENTRY(0x80862812, "Tigerlake HDMI",  patch_i915_tgl_hdmi),
 HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI", patch_generic_hdmi),
 HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI",        patch_i915_byt_hdmi),
 HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI",   patch_i915_byt_hdmi),
index ce4f116597657e8a87db2aedd79cef2feba9efbd..80f66ba85f87664945777ef3fc7cf1abef4d63a6 100644 (file)
@@ -393,6 +393,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
        case 0x10ec0700:
        case 0x10ec0701:
        case 0x10ec0703:
+       case 0x10ec0711:
                alc_update_coef_idx(codec, 0x10, 1<<15, 0);
                break;
        case 0x10ec0662:
@@ -408,6 +409,9 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
        case 0x10ec0672:
                alc_update_coef_idx(codec, 0xd, 0, 1<<14); /* EAPD Ctrl */
                break;
+       case 0x10ec0623:
+               alc_update_coef_idx(codec, 0x19, 1<<13, 0);
+               break;
        case 0x10ec0668:
                alc_update_coef_idx(codec, 0x7, 3<<13, 0);
                break;
@@ -2919,6 +2923,7 @@ enum {
        ALC269_TYPE_ALC225,
        ALC269_TYPE_ALC294,
        ALC269_TYPE_ALC300,
+       ALC269_TYPE_ALC623,
        ALC269_TYPE_ALC700,
 };
 
@@ -2954,6 +2959,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
        case ALC269_TYPE_ALC225:
        case ALC269_TYPE_ALC294:
        case ALC269_TYPE_ALC300:
+       case ALC269_TYPE_ALC623:
        case ALC269_TYPE_ALC700:
                ssids = alc269_ssids;
                break;
@@ -7215,6 +7221,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x312f, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
        SND_PCI_QUIRK(0x17aa, 0x313c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
        SND_PCI_QUIRK(0x17aa, 0x3151, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
+       SND_PCI_QUIRK(0x17aa, 0x3176, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
+       SND_PCI_QUIRK(0x17aa, 0x3178, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
        SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
        SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
@@ -8016,9 +8024,13 @@ static int patch_alc269(struct hda_codec *codec)
                spec->codec_variant = ALC269_TYPE_ALC300;
                spec->gen.mixer_nid = 0; /* no loopback on ALC300 */
                break;
+       case 0x10ec0623:
+               spec->codec_variant = ALC269_TYPE_ALC623;
+               break;
        case 0x10ec0700:
        case 0x10ec0701:
        case 0x10ec0703:
+       case 0x10ec0711:
                spec->codec_variant = ALC269_TYPE_ALC700;
                spec->gen.mixer_nid = 0; /* ALC700 does not have any loopback mixer path */
                alc_update_coef_idx(codec, 0x4a, 1 << 15, 0); /* Combo jack auto trigger control */
@@ -9216,6 +9228,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
        HDA_CODEC_ENTRY(0x10ec0298, "ALC298", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0299, "ALC299", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0300, "ALC300", patch_alc269),
+       HDA_CODEC_ENTRY(0x10ec0623, "ALC623", patch_alc269),
        HDA_CODEC_REV_ENTRY(0x10ec0861, 0x100340, "ALC660", patch_alc861),
        HDA_CODEC_ENTRY(0x10ec0660, "ALC660-VD", patch_alc861vd),
        HDA_CODEC_ENTRY(0x10ec0861, "ALC861", patch_alc861),
@@ -9233,6 +9246,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
        HDA_CODEC_ENTRY(0x10ec0700, "ALC700", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0701, "ALC701", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0703, "ALC703", patch_alc269),
+       HDA_CODEC_ENTRY(0x10ec0711, "ALC711", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0867, "ALC891", patch_alc662),
        HDA_CODEC_ENTRY(0x10ec0880, "ALC880", patch_alc880),
        HDA_CODEC_ENTRY(0x10ec0882, "ALC882", patch_alc882),
index 91242b6f8ea7adf27e05f2883397f932a2f1688e..4570f662fb48b4090979be99b13087c3c0507a62 100644 (file)
@@ -410,8 +410,8 @@ static void hdac_hda_codec_remove(struct snd_soc_component *component)
                return;
        }
 
-       snd_hdac_ext_bus_link_put(hdev->bus, hlink);
        pm_runtime_disable(&hdev->dev);
+       snd_hdac_ext_bus_link_put(hdev->bus, hlink);
 }
 
 static const struct snd_soc_dapm_route hdac_hda_dapm_routes[] = {
index b5fd8f08726e0a500deaf0b332880ccc5dd83be4..f8b5b960e5970ef3182aaa14b528f09fab6f50be 100644 (file)
@@ -274,7 +274,7 @@ struct hdmi_codec_priv {
        uint8_t eld[MAX_ELD_BYTES];
        struct snd_pcm_chmap *chmap_info;
        unsigned int chmap_idx;
-       struct mutex lock;
+       unsigned long busy;
        struct snd_soc_jack *jack;
        unsigned int jack_status;
 };
@@ -390,8 +390,8 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream,
        struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
        int ret = 0;
 
-       ret = mutex_trylock(&hcp->lock);
-       if (!ret) {
+       ret = test_and_set_bit(0, &hcp->busy);
+       if (ret) {
                dev_err(dai->dev, "Only one simultaneous stream supported!\n");
                return -EINVAL;
        }
@@ -419,7 +419,7 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream,
 
 err:
        /* Release the exclusive lock on error */
-       mutex_unlock(&hcp->lock);
+       clear_bit(0, &hcp->busy);
        return ret;
 }
 
@@ -431,7 +431,7 @@ static void hdmi_codec_shutdown(struct snd_pcm_substream *substream,
        hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
        hcp->hcd.ops->audio_shutdown(dai->dev->parent, hcp->hcd.data);
 
-       mutex_unlock(&hcp->lock);
+       clear_bit(0, &hcp->busy);
 }
 
 static int hdmi_codec_hw_params(struct snd_pcm_substream *substream,
@@ -811,8 +811,6 @@ static int hdmi_codec_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        hcp->hcd = *hcd;
-       mutex_init(&hcp->lock);
-
        daidrv = devm_kcalloc(dev, dai_count, sizeof(*daidrv), GFP_KERNEL);
        if (!daidrv)
                return -ENOMEM;
index e609abcf3220e71f9c600cec0aebf71067fb2003..cae1def8902dd73ecc8f51ba28e354f7a8c6bd40 100644 (file)
@@ -901,16 +901,20 @@ static void max98373_slot_config(struct i2c_client *i2c,
                max98373->i_slot = value & 0xF;
        else
                max98373->i_slot = 1;
-
-       max98373->reset_gpio = of_get_named_gpio(dev->of_node,
+       if (dev->of_node) {
+               max98373->reset_gpio = of_get_named_gpio(dev->of_node,
                                                "maxim,reset-gpio", 0);
-       if (!gpio_is_valid(max98373->reset_gpio)) {
-               dev_err(dev, "Looking up %s property in node %s failed %d\n",
-                       "maxim,reset-gpio", dev->of_node->full_name,
-                       max98373->reset_gpio);
+               if (!gpio_is_valid(max98373->reset_gpio)) {
+                       dev_err(dev, "Looking up %s property in node %s failed %d\n",
+                               "maxim,reset-gpio", dev->of_node->full_name,
+                               max98373->reset_gpio);
+               } else {
+                       dev_dbg(dev, "maxim,reset-gpio=%d",
+                               max98373->reset_gpio);
+               }
        } else {
-               dev_dbg(dev, "maxim,reset-gpio=%d",
-                       max98373->reset_gpio);
+               /* this makes reset_gpio as invalid */
+               max98373->reset_gpio = -1;
        }
 
        if (!device_property_read_u32(dev, "maxim,spkfb-slot-no", &value))
@@ -956,11 +960,11 @@ static int max98373_i2c_probe(struct i2c_client *i2c,
 
        /* Power on device */
        if (gpio_is_valid(max98373->reset_gpio)) {
-               ret = gpio_request(max98373->reset_gpio, "MAX98373_RESET");
+               ret = devm_gpio_request(&i2c->dev, max98373->reset_gpio,
+                                       "MAX98373_RESET");
                if (ret) {
                        dev_err(&i2c->dev, "%s: Failed to request gpio %d\n",
                                __func__, max98373->reset_gpio);
-                       gpio_free(max98373->reset_gpio);
                        return -EINVAL;
                }
                gpio_direction_output(max98373->reset_gpio, 0);
index 667e9f73aba3850401d2164b9ca143affceb0cf6..e3d311fb510e0a7497fa0e0b7c26aef1204353ef 100644 (file)
@@ -306,7 +306,7 @@ struct pm8916_wcd_analog_priv {
 };
 
 static const char *const adc2_mux_text[] = { "ZERO", "INP2", "INP3" };
-static const char *const rdac2_mux_text[] = { "ZERO", "RX2", "RX1" };
+static const char *const rdac2_mux_text[] = { "RX1", "RX2" };
 static const char *const hph_text[] = { "ZERO", "Switch", };
 
 static const struct soc_enum hph_enum = SOC_ENUM_SINGLE_VIRT(
@@ -321,7 +321,7 @@ static const struct soc_enum adc2_enum = SOC_ENUM_SINGLE_VIRT(
 
 /* RDAC2 MUX */
 static const struct soc_enum rdac2_mux_enum = SOC_ENUM_SINGLE(
-                       CDC_D_CDC_CONN_HPHR_DAC_CTL, 0, 3, rdac2_mux_text);
+                       CDC_D_CDC_CONN_HPHR_DAC_CTL, 0, 2, rdac2_mux_text);
 
 static const struct snd_kcontrol_new spkr_switch[] = {
        SOC_DAPM_SINGLE("Switch", CDC_A_SPKR_DAC_CTL, 7, 1, 0)
index 9fa5d44fdc79f57a3b274393dea4cd7f08a4b2a5..58b2468fb2a7139b8d7dbb35085ecbe5acb8215f 100644 (file)
@@ -243,6 +243,10 @@ static const char *const rx_mix1_text[] = {
        "ZERO", "IIR1", "IIR2", "RX1", "RX2", "RX3"
 };
 
+static const char * const rx_mix2_text[] = {
+       "ZERO", "IIR1", "IIR2"
+};
+
 static const char *const dec_mux_text[] = {
        "ZERO", "ADC1", "ADC2", "ADC3", "DMIC1", "DMIC2"
 };
@@ -270,6 +274,16 @@ static const struct soc_enum rx3_mix1_inp_enum[] = {
        SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX3_B2_CTL, 0, 6, rx_mix1_text),
 };
 
+/* RX1 MIX2 */
+static const struct soc_enum rx_mix2_inp1_chain_enum =
+       SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX1_B3_CTL,
+               0, 3, rx_mix2_text);
+
+/* RX2 MIX2 */
+static const struct soc_enum rx2_mix2_inp1_chain_enum =
+       SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX2_B3_CTL,
+               0, 3, rx_mix2_text);
+
 /* DEC */
 static const struct soc_enum dec1_mux_enum = SOC_ENUM_SINGLE(
                                LPASS_CDC_CONN_TX_B1_CTL, 0, 6, dec_mux_text);
@@ -309,6 +323,10 @@ static const struct snd_kcontrol_new rx3_mix1_inp2_mux = SOC_DAPM_ENUM(
                                "RX3 MIX1 INP2 Mux", rx3_mix1_inp_enum[1]);
 static const struct snd_kcontrol_new rx3_mix1_inp3_mux = SOC_DAPM_ENUM(
                                "RX3 MIX1 INP3 Mux", rx3_mix1_inp_enum[2]);
+static const struct snd_kcontrol_new rx1_mix2_inp1_mux = SOC_DAPM_ENUM(
+                               "RX1 MIX2 INP1 Mux", rx_mix2_inp1_chain_enum);
+static const struct snd_kcontrol_new rx2_mix2_inp1_mux = SOC_DAPM_ENUM(
+                               "RX2 MIX2 INP1 Mux", rx2_mix2_inp1_chain_enum);
 
 /* Digital Gain control -38.4 dB to +38.4 dB in 0.3 dB steps */
 static const DECLARE_TLV_DB_SCALE(digital_gain, -3840, 30, 0);
@@ -740,6 +758,10 @@ static const struct snd_soc_dapm_widget msm8916_wcd_digital_dapm_widgets[] = {
                         &rx3_mix1_inp2_mux),
        SND_SOC_DAPM_MUX("RX3 MIX1 INP3", SND_SOC_NOPM, 0, 0,
                         &rx3_mix1_inp3_mux),
+       SND_SOC_DAPM_MUX("RX1 MIX2 INP1", SND_SOC_NOPM, 0, 0,
+                        &rx1_mix2_inp1_mux),
+       SND_SOC_DAPM_MUX("RX2 MIX2 INP1", SND_SOC_NOPM, 0, 0,
+                        &rx2_mix2_inp1_mux),
 
        SND_SOC_DAPM_MUX("CIC1 MUX", SND_SOC_NOPM, 0, 0, &cic1_mux),
        SND_SOC_DAPM_MUX("CIC2 MUX", SND_SOC_NOPM, 0, 0, &cic2_mux),
index 762595de956c15662c245acf825c2cafb212b528..c506c9305043e115711cbac86fb22e77734b0d54 100644 (file)
@@ -1770,6 +1770,9 @@ static int rt5651_detect_headset(struct snd_soc_component *component)
 
 static bool rt5651_support_button_press(struct rt5651_priv *rt5651)
 {
+       if (!rt5651->hp_jack)
+               return false;
+
        /* Button press support only works with internal jack-detection */
        return (rt5651->hp_jack->status & SND_JACK_MICROPHONE) &&
                rt5651->gpiod_hp_det == NULL;
index 1ef470700ed5fea954321884d705fc50ba9ccc23..c50b75ce82e0b727cd91fb0d17caf93088890da1 100644 (file)
@@ -995,6 +995,16 @@ static int rt5682_set_jack_detect(struct snd_soc_component *component,
 {
        struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
 
+       rt5682->hs_jack = hs_jack;
+
+       if (!hs_jack) {
+               regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2,
+                                  RT5682_JD1_EN_MASK, RT5682_JD1_DIS);
+               regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL,
+                                  RT5682_POW_JDH | RT5682_POW_JDL, 0);
+               return 0;
+       }
+
        switch (rt5682->pdata.jd_src) {
        case RT5682_JD1:
                snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_2,
@@ -1032,8 +1042,6 @@ static int rt5682_set_jack_detect(struct snd_soc_component *component,
                break;
        }
 
-       rt5682->hs_jack = hs_jack;
-
        return 0;
 }
 
index c3d06e8bc54f20293f6490a56669e920eeae3a29..d5fb7f5dd551cb834ad77ae9b99ca453d7264008 100644 (file)
@@ -533,13 +533,10 @@ static SOC_ENUM_SINGLE_DECL(dac_osr,
 static SOC_ENUM_SINGLE_DECL(adc_osr,
                            WM8994_OVERSAMPLING, 1, osr_text);
 
-static const struct snd_kcontrol_new wm8994_snd_controls[] = {
+static const struct snd_kcontrol_new wm8994_common_snd_controls[] = {
 SOC_DOUBLE_R_TLV("AIF1ADC1 Volume", WM8994_AIF1_ADC1_LEFT_VOLUME,
                 WM8994_AIF1_ADC1_RIGHT_VOLUME,
                 1, 119, 0, digital_tlv),
-SOC_DOUBLE_R_TLV("AIF1ADC2 Volume", WM8994_AIF1_ADC2_LEFT_VOLUME,
-                WM8994_AIF1_ADC2_RIGHT_VOLUME,
-                1, 119, 0, digital_tlv),
 SOC_DOUBLE_R_TLV("AIF2ADC Volume", WM8994_AIF2_ADC_LEFT_VOLUME,
                 WM8994_AIF2_ADC_RIGHT_VOLUME,
                 1, 119, 0, digital_tlv),
@@ -556,8 +553,6 @@ SOC_ENUM("AIF2DACR Source", aif2dacr_src),
 
 SOC_DOUBLE_R_TLV("AIF1DAC1 Volume", WM8994_AIF1_DAC1_LEFT_VOLUME,
                 WM8994_AIF1_DAC1_RIGHT_VOLUME, 1, 96, 0, digital_tlv),
-SOC_DOUBLE_R_TLV("AIF1DAC2 Volume", WM8994_AIF1_DAC2_LEFT_VOLUME,
-                WM8994_AIF1_DAC2_RIGHT_VOLUME, 1, 96, 0, digital_tlv),
 SOC_DOUBLE_R_TLV("AIF2DAC Volume", WM8994_AIF2_DAC_LEFT_VOLUME,
                 WM8994_AIF2_DAC_RIGHT_VOLUME, 1, 96, 0, digital_tlv),
 
@@ -565,17 +560,12 @@ SOC_SINGLE_TLV("AIF1 Boost Volume", WM8994_AIF1_CONTROL_2, 10, 3, 0, aif_tlv),
 SOC_SINGLE_TLV("AIF2 Boost Volume", WM8994_AIF2_CONTROL_2, 10, 3, 0, aif_tlv),
 
 SOC_SINGLE("AIF1DAC1 EQ Switch", WM8994_AIF1_DAC1_EQ_GAINS_1, 0, 1, 0),
-SOC_SINGLE("AIF1DAC2 EQ Switch", WM8994_AIF1_DAC2_EQ_GAINS_1, 0, 1, 0),
 SOC_SINGLE("AIF2 EQ Switch", WM8994_AIF2_EQ_GAINS_1, 0, 1, 0),
 
 WM8994_DRC_SWITCH("AIF1DAC1 DRC Switch", WM8994_AIF1_DRC1_1, 2),
 WM8994_DRC_SWITCH("AIF1ADC1L DRC Switch", WM8994_AIF1_DRC1_1, 1),
 WM8994_DRC_SWITCH("AIF1ADC1R DRC Switch", WM8994_AIF1_DRC1_1, 0),
 
-WM8994_DRC_SWITCH("AIF1DAC2 DRC Switch", WM8994_AIF1_DRC2_1, 2),
-WM8994_DRC_SWITCH("AIF1ADC2L DRC Switch", WM8994_AIF1_DRC2_1, 1),
-WM8994_DRC_SWITCH("AIF1ADC2R DRC Switch", WM8994_AIF1_DRC2_1, 0),
-
 WM8994_DRC_SWITCH("AIF2DAC DRC Switch", WM8994_AIF2_DRC_1, 2),
 WM8994_DRC_SWITCH("AIF2ADCL DRC Switch", WM8994_AIF2_DRC_1, 1),
 WM8994_DRC_SWITCH("AIF2ADCR DRC Switch", WM8994_AIF2_DRC_1, 0),
@@ -594,9 +584,6 @@ SOC_SINGLE("Sidetone HPF Switch", WM8994_SIDETONE, 6, 1, 0),
 SOC_ENUM("AIF1ADC1 HPF Mode", aif1adc1_hpf),
 SOC_DOUBLE("AIF1ADC1 HPF Switch", WM8994_AIF1_ADC1_FILTERS, 12, 11, 1, 0),
 
-SOC_ENUM("AIF1ADC2 HPF Mode", aif1adc2_hpf),
-SOC_DOUBLE("AIF1ADC2 HPF Switch", WM8994_AIF1_ADC2_FILTERS, 12, 11, 1, 0),
-
 SOC_ENUM("AIF2ADC HPF Mode", aif2adc_hpf),
 SOC_DOUBLE("AIF2ADC HPF Switch", WM8994_AIF2_ADC_FILTERS, 12, 11, 1, 0),
 
@@ -637,6 +624,24 @@ SOC_SINGLE("AIF2DAC 3D Stereo Switch", WM8994_AIF2_DAC_FILTERS_2,
           8, 1, 0),
 };
 
+/* Controls not available on WM1811 */
+static const struct snd_kcontrol_new wm8994_snd_controls[] = {
+SOC_DOUBLE_R_TLV("AIF1ADC2 Volume", WM8994_AIF1_ADC2_LEFT_VOLUME,
+                WM8994_AIF1_ADC2_RIGHT_VOLUME,
+                1, 119, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("AIF1DAC2 Volume", WM8994_AIF1_DAC2_LEFT_VOLUME,
+                WM8994_AIF1_DAC2_RIGHT_VOLUME, 1, 96, 0, digital_tlv),
+
+SOC_SINGLE("AIF1DAC2 EQ Switch", WM8994_AIF1_DAC2_EQ_GAINS_1, 0, 1, 0),
+
+WM8994_DRC_SWITCH("AIF1DAC2 DRC Switch", WM8994_AIF1_DRC2_1, 2),
+WM8994_DRC_SWITCH("AIF1ADC2L DRC Switch", WM8994_AIF1_DRC2_1, 1),
+WM8994_DRC_SWITCH("AIF1ADC2R DRC Switch", WM8994_AIF1_DRC2_1, 0),
+
+SOC_ENUM("AIF1ADC2 HPF Mode", aif1adc2_hpf),
+SOC_DOUBLE("AIF1ADC2 HPF Switch", WM8994_AIF1_ADC2_FILTERS, 12, 11, 1, 0),
+};
+
 static const struct snd_kcontrol_new wm8994_eq_controls[] = {
 SOC_SINGLE_TLV("AIF1DAC1 EQ1 Volume", WM8994_AIF1_DAC1_EQ_GAINS_1, 11, 31, 0,
               eq_tlv),
@@ -4258,13 +4263,15 @@ static int wm8994_component_probe(struct snd_soc_component *component)
        wm8994_handle_pdata(wm8994);
 
        wm_hubs_add_analogue_controls(component);
-       snd_soc_add_component_controls(component, wm8994_snd_controls,
-                            ARRAY_SIZE(wm8994_snd_controls));
+       snd_soc_add_component_controls(component, wm8994_common_snd_controls,
+                                      ARRAY_SIZE(wm8994_common_snd_controls));
        snd_soc_dapm_new_controls(dapm, wm8994_dapm_widgets,
                                  ARRAY_SIZE(wm8994_dapm_widgets));
 
        switch (control->type) {
        case WM8994:
+               snd_soc_add_component_controls(component, wm8994_snd_controls,
+                                              ARRAY_SIZE(wm8994_snd_controls));
                snd_soc_dapm_new_controls(dapm, wm8994_specific_dapm_widgets,
                                          ARRAY_SIZE(wm8994_specific_dapm_widgets));
                if (control->revision < 4) {
@@ -4284,8 +4291,10 @@ static int wm8994_component_probe(struct snd_soc_component *component)
                }
                break;
        case WM8958:
+               snd_soc_add_component_controls(component, wm8994_snd_controls,
+                                              ARRAY_SIZE(wm8994_snd_controls));
                snd_soc_add_component_controls(component, wm8958_snd_controls,
-                                    ARRAY_SIZE(wm8958_snd_controls));
+                                              ARRAY_SIZE(wm8958_snd_controls));
                snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets,
                                          ARRAY_SIZE(wm8958_dapm_widgets));
                if (control->revision < 1) {
index ae28d9907c30f58f2bd5a1ee8588b8b03fb9c399..9b8bb7bbe945daa4ad22db1264b44b0ac7f3a0f9 100644 (file)
@@ -1259,8 +1259,7 @@ static unsigned int wmfw_convert_flags(unsigned int in, unsigned int len)
        }
 
        if (in) {
-               if (in & WMFW_CTL_FLAG_READABLE)
-                       out |= rd;
+               out |= rd;
                if (in & WMFW_CTL_FLAG_WRITEABLE)
                        out |= wr;
                if (in & WMFW_CTL_FLAG_VOLATILE)
@@ -3697,11 +3696,16 @@ static int wm_adsp_buffer_parse_legacy(struct wm_adsp *dsp)
        u32 xmalg, addr, magic;
        int i, ret;
 
+       alg_region = wm_adsp_find_alg_region(dsp, WMFW_ADSP2_XM, dsp->fw_id);
+       if (!alg_region) {
+               adsp_err(dsp, "No algorithm region found\n");
+               return -EINVAL;
+       }
+
        buf = wm_adsp_buffer_alloc(dsp);
        if (!buf)
                return -ENOMEM;
 
-       alg_region = wm_adsp_find_alg_region(dsp, WMFW_ADSP2_XM, dsp->fw_id);
        xmalg = dsp->ops->sys_config_size / sizeof(__be32);
 
        addr = alg_region->base + xmalg + ALG_XM_FIELD(magic);
index a437567b8cee233a0dbebd52dfe1c70fe952dcce..4f6e58c3954a220fd0050c5d8c29089c0ee16622 100644 (file)
@@ -308,6 +308,9 @@ static const struct snd_soc_dapm_widget sof_widgets[] = {
        SND_SOC_DAPM_HP("Headphone Jack", NULL),
        SND_SOC_DAPM_MIC("Headset Mic", NULL),
        SND_SOC_DAPM_SPK("Spk", NULL),
+};
+
+static const struct snd_soc_dapm_widget dmic_widgets[] = {
        SND_SOC_DAPM_MIC("SoC DMIC", NULL),
 };
 
@@ -318,10 +321,6 @@ static const struct snd_soc_dapm_route sof_map[] = {
 
        /* other jacks */
        { "IN1P", NULL, "Headset Mic" },
-
-       /* digital mics */
-       {"DMic", NULL, "SoC DMIC"},
-
 };
 
 static const struct snd_soc_dapm_route speaker_map[] = {
@@ -329,6 +328,11 @@ static const struct snd_soc_dapm_route speaker_map[] = {
        { "Spk", NULL, "Speaker" },
 };
 
+static const struct snd_soc_dapm_route dmic_map[] = {
+       /* digital mics */
+       {"DMic", NULL, "SoC DMIC"},
+};
+
 static int speaker_codec_init(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_soc_card *card = rtd->card;
@@ -342,6 +346,28 @@ static int speaker_codec_init(struct snd_soc_pcm_runtime *rtd)
        return ret;
 }
 
+static int dmic_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_soc_card *card = rtd->card;
+       int ret;
+
+       ret = snd_soc_dapm_new_controls(&card->dapm, dmic_widgets,
+                                       ARRAY_SIZE(dmic_widgets));
+       if (ret) {
+               dev_err(card->dev, "DMic widget addition failed: %d\n", ret);
+               /* Don't need to add routes if widget addition failed */
+               return ret;
+       }
+
+       ret = snd_soc_dapm_add_routes(&card->dapm, dmic_map,
+                                     ARRAY_SIZE(dmic_map));
+
+       if (ret)
+               dev_err(card->dev, "DMic map addition failed: %d\n", ret);
+
+       return ret;
+}
+
 /* sof audio machine driver for rt5682 codec */
 static struct snd_soc_card sof_audio_card_rt5682 = {
        .name = "sof_rt5682",
@@ -445,6 +471,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
                links[id].name = "dmic01";
                links[id].cpus = &cpus[id];
                links[id].cpus->dai_name = "DMIC01 Pin";
+               links[id].init = dmic_init;
                if (dmic_be_num > 1) {
                        /* set up 2 BE links at most */
                        links[id + 1].name = "dmic16k";
@@ -576,6 +603,15 @@ static int sof_audio_probe(struct platform_device *pdev)
        /* need to get main clock from pmc */
        if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
                ctx->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
+               if (IS_ERR(ctx->mclk)) {
+                       ret = PTR_ERR(ctx->mclk);
+
+                       dev_err(&pdev->dev,
+                               "Failed to get MCLK from pmc_plt_clk_3: %d\n",
+                               ret);
+                       return ret;
+               }
+
                ret = clk_prepare_enable(ctx->mclk);
                if (ret < 0) {
                        dev_err(&pdev->dev,
@@ -621,8 +657,24 @@ static int sof_audio_probe(struct platform_device *pdev)
                                          &sof_audio_card_rt5682);
 }
 
+static int sof_rt5682_remove(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+       struct snd_soc_component *component = NULL;
+
+       for_each_card_components(card, component) {
+               if (!strcmp(component->name, rt5682_component[0].name)) {
+                       snd_soc_component_set_jack(component, NULL, NULL);
+                       break;
+               }
+       }
+
+       return 0;
+}
+
 static struct platform_driver sof_audio = {
        .probe = sof_audio_probe,
+       .remove = sof_rt5682_remove,
        .driver = {
                .name = "sof_rt5682",
                .pm = &snd_soc_pm_ops,
index 61226fefe1c4bc13bbb916faf56f5728d65ce0e9..2a4ffe945177ba150f03a066442688bb637a82da 100644 (file)
@@ -555,10 +555,6 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
                return PTR_ERR(priv->clk);
        }
 
-       err = clk_prepare_enable(priv->clk);
-       if (err < 0)
-               return err;
-
        priv->extclk = devm_clk_get(&pdev->dev, "extclk");
        if (IS_ERR(priv->extclk)) {
                if (PTR_ERR(priv->extclk) == -EPROBE_DEFER)
@@ -574,6 +570,10 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
                }
        }
 
+       err = clk_prepare_enable(priv->clk);
+       if (err < 0)
+               return err;
+
        /* Some sensible defaults - this reflects the powerup values */
        priv->ctl_play = KIRKWOOD_PLAYCTL_SIZE_24;
        priv->ctl_rec = KIRKWOOD_RECCTL_SIZE_24;
@@ -587,7 +587,7 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
                priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_128;
        }
 
-       err = devm_snd_soc_register_component(&pdev->dev, &kirkwood_soc_component,
+       err = snd_soc_register_component(&pdev->dev, &kirkwood_soc_component,
                                         soc_dai, 2);
        if (err) {
                dev_err(&pdev->dev, "snd_soc_register_component failed\n");
@@ -610,6 +610,7 @@ static int kirkwood_i2s_dev_remove(struct platform_device *pdev)
 {
        struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev);
 
+       snd_soc_unregister_component(&pdev->dev);
        if (!IS_ERR(priv->extclk))
                clk_disable_unprepare(priv->extclk);
        clk_disable_unprepare(priv->clk);
index af2d5a6124c8e122a8055d482b376d8df8be76c3..61c984f10d8e61199b7c02e287532039c6f3d9ed 100644 (file)
@@ -677,7 +677,7 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
        ret = rockchip_pcm_platform_register(&pdev->dev);
        if (ret) {
                dev_err(&pdev->dev, "Could not register PCM\n");
-               return ret;
+               goto err_suspend;
        }
 
        return 0;
index 0097df1fae662f1d5a25af1daf36ddfc5bfb20cc..e80b09143b63edf970e8921366cc074dd6c43ef9 100644 (file)
@@ -66,10 +66,13 @@ static int rk_jack_event(struct notifier_block *nb, unsigned long event,
        struct snd_soc_jack *jack = (struct snd_soc_jack *)data;
        struct snd_soc_dapm_context *dapm = &jack->card->dapm;
 
-       if (event & SND_JACK_MICROPHONE)
+       if (event & SND_JACK_MICROPHONE) {
                snd_soc_dapm_force_enable_pin(dapm, "MICBIAS");
-       else
+               snd_soc_dapm_force_enable_pin(dapm, "SHDN");
+       } else {
                snd_soc_dapm_disable_pin(dapm, "MICBIAS");
+               snd_soc_dapm_disable_pin(dapm, "SHDN");
+       }
 
        snd_soc_dapm_sync(dapm);
 
index c213913eb98488f709c097e6d91b9f298bba5399..fd8c6642fb0dfbceeeb8a9170461287643667289 100644 (file)
@@ -5,6 +5,7 @@
 //  Author: Claude <claude@insginal.co.kr>
 
 #include <linux/module.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 
@@ -74,6 +75,17 @@ static struct snd_soc_card arndale_rt5631 = {
        .num_links = ARRAY_SIZE(arndale_rt5631_dai),
 };
 
+static void arndale_put_of_nodes(struct snd_soc_card *card)
+{
+       struct snd_soc_dai_link *dai_link;
+       int i;
+
+       for_each_card_prelinks(card, i, dai_link) {
+               of_node_put(dai_link->cpus->of_node);
+               of_node_put(dai_link->codecs->of_node);
+       }
+}
+
 static int arndale_audio_probe(struct platform_device *pdev)
 {
        int n, ret;
@@ -103,18 +115,31 @@ static int arndale_audio_probe(struct platform_device *pdev)
                if (!arndale_rt5631_dai[0].codecs->of_node) {
                        dev_err(&pdev->dev,
                        "Property 'samsung,audio-codec' missing or invalid\n");
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto err_put_of_nodes;
                }
        }
 
        ret = devm_snd_soc_register_card(card->dev, card);
+       if (ret) {
+               dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret);
+               goto err_put_of_nodes;
+       }
+       return 0;
 
-       if (ret)
-               dev_err(&pdev->dev, "snd_soc_register_card() failed:%d\n", ret);
-
+err_put_of_nodes:
+       arndale_put_of_nodes(card);
        return ret;
 }
 
+static int arndale_audio_remove(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+       arndale_put_of_nodes(card);
+       return 0;
+}
+
 static const struct of_device_id samsung_arndale_rt5631_of_match[] __maybe_unused = {
        { .compatible = "samsung,arndale-rt5631", },
        { .compatible = "samsung,arndale-alc5631", },
@@ -129,6 +154,7 @@ static struct platform_driver arndale_audio_driver = {
                .of_match_table = of_match_ptr(samsung_arndale_rt5631_of_match),
        },
        .probe = arndale_audio_probe,
+       .remove = arndale_audio_remove,
 };
 
 module_platform_driver(arndale_audio_driver);
index bda5b958d0dc5c17b1681212fe5cb96377fd2b31..e9596c2096cd585334e6c99710cc6e3194a4f792 100644 (file)
@@ -761,6 +761,7 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
        }
 
        /* set format */
+       rdai->bit_clk_inv = 0;
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_I2S:
                rdai->sys_delay = 0;
index 0324a5c3961963b1d9315d1618161c8113891808..28f65eba2bb459fa354c03af97c455e3dd1270d8 100644 (file)
@@ -508,10 +508,10 @@ static struct rsnd_mod_ops rsnd_dmapp_ops = {
 #define RDMA_SSI_I_N(addr, i)  (addr ##_reg - 0x00300000 + (0x40 * i) + 0x8)
 #define RDMA_SSI_O_N(addr, i)  (addr ##_reg - 0x00300000 + (0x40 * i) + 0xc)
 
-#define RDMA_SSIU_I_N(addr, i, j) (addr ##_reg - 0x00441000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400))
+#define RDMA_SSIU_I_N(addr, i, j) (addr ##_reg - 0x00441000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 * ((i) / 9) * ((j) / 4)))
 #define RDMA_SSIU_O_N(addr, i, j) RDMA_SSIU_I_N(addr, i, j)
 
-#define RDMA_SSIU_I_P(addr, i, j) (addr ##_reg - 0x00141000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400))
+#define RDMA_SSIU_I_P(addr, i, j) (addr ##_reg - 0x00141000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 * ((i) / 9) * ((j) / 4)))
 #define RDMA_SSIU_O_P(addr, i, j) RDMA_SSIU_I_P(addr, i, j)
 
 #define RDMA_SRC_I_N(addr, i)  (addr ##_reg - 0x00500000 + (0x400 * i))
index e163dde5eab1d708a98b0767318811fa4f2491d8..b600d3eaaf5cd2c2c97c1a42e3d091f75970001a 100644 (file)
@@ -1070,7 +1070,7 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
                        return ret;
        }
 
-       snd_soc_dai_trigger(cpu_dai, substream, cmd);
+       ret = snd_soc_dai_trigger(cpu_dai, substream, cmd);
        if (ret < 0)
                return ret;
 
@@ -1097,7 +1097,7 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream,
                        return ret;
        }
 
-       snd_soc_dai_bespoke_trigger(cpu_dai, substream, cmd);
+       ret = snd_soc_dai_bespoke_trigger(cpu_dai, substream, cmd);
        if (ret < 0)
                return ret;
 
@@ -1146,6 +1146,7 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe,
 {
        struct snd_soc_dpcm *dpcm;
        unsigned long flags;
+       char *name;
 
        /* only add new dpcms */
        for_each_dpcm_be(fe, stream, dpcm) {
@@ -1171,9 +1172,15 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe,
                        stream ? "<-" : "->", be->dai_link->name);
 
 #ifdef CONFIG_DEBUG_FS
-       dpcm->debugfs_state = debugfs_create_dir(be->dai_link->name,
-                                                fe->debugfs_dpcm_root);
-       debugfs_create_u32("state", 0644, dpcm->debugfs_state, &dpcm->state);
+       name = kasprintf(GFP_KERNEL, "%s:%s", be->dai_link->name,
+                        stream ? "capture" : "playback");
+       if (name) {
+               dpcm->debugfs_state = debugfs_create_dir(name,
+                                                        fe->debugfs_dpcm_root);
+               debugfs_create_u32("state", 0644, dpcm->debugfs_state,
+                                  &dpcm->state);
+               kfree(name);
+       }
 #endif
        return 1;
 }
index aa9a1fca46fa7832271ff0d3919959f94dfaa0a4..0fd032914a318b39d46f89ac8af1435de11ebba1 100644 (file)
@@ -1582,7 +1582,7 @@ static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg,
 
        /* map user to kernel widget ID */
        template.id = get_widget_id(le32_to_cpu(w->id));
-       if (template.id < 0)
+       if ((int)template.id < 0)
                return template.id;
 
        /* strings are allocated here, but used and freed by the widget */
index a4983f90ff5b31694197b2d72c6e1cdf309e8fb9..2b8711eda362b97362ef2501080c099b7616bc52 100644 (file)
@@ -60,13 +60,16 @@ int snd_sof_volume_put(struct snd_kcontrol *kcontrol,
        struct snd_sof_dev *sdev = scontrol->sdev;
        struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
        unsigned int i, channels = scontrol->num_channels;
+       bool change = false;
+       u32 value;
 
        /* update each channel */
        for (i = 0; i < channels; i++) {
-               cdata->chanv[i].value =
-                       mixer_to_ipc(ucontrol->value.integer.value[i],
+               value = mixer_to_ipc(ucontrol->value.integer.value[i],
                                     scontrol->volume_table, sm->max + 1);
+               change = change || (value != cdata->chanv[i].value);
                cdata->chanv[i].channel = i;
+               cdata->chanv[i].value = value;
        }
 
        /* notify DSP of mixer updates */
@@ -76,8 +79,7 @@ int snd_sof_volume_put(struct snd_kcontrol *kcontrol,
                                              SOF_CTRL_TYPE_VALUE_CHAN_GET,
                                              SOF_CTRL_CMD_VOLUME,
                                              true);
-
-       return 0;
+       return change;
 }
 
 int snd_sof_switch_get(struct snd_kcontrol *kcontrol,
@@ -105,11 +107,15 @@ int snd_sof_switch_put(struct snd_kcontrol *kcontrol,
        struct snd_sof_dev *sdev = scontrol->sdev;
        struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
        unsigned int i, channels = scontrol->num_channels;
+       bool change = false;
+       u32 value;
 
        /* update each channel */
        for (i = 0; i < channels; i++) {
-               cdata->chanv[i].value = ucontrol->value.integer.value[i];
+               value = ucontrol->value.integer.value[i];
+               change = change || (value != cdata->chanv[i].value);
                cdata->chanv[i].channel = i;
+               cdata->chanv[i].value = value;
        }
 
        /* notify DSP of mixer updates */
@@ -120,7 +126,7 @@ int snd_sof_switch_put(struct snd_kcontrol *kcontrol,
                                              SOF_CTRL_CMD_SWITCH,
                                              true);
 
-       return 0;
+       return change;
 }
 
 int snd_sof_enum_get(struct snd_kcontrol *kcontrol,
@@ -148,11 +154,15 @@ int snd_sof_enum_put(struct snd_kcontrol *kcontrol,
        struct snd_sof_dev *sdev = scontrol->sdev;
        struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
        unsigned int i, channels = scontrol->num_channels;
+       bool change = false;
+       u32 value;
 
        /* update each channel */
        for (i = 0; i < channels; i++) {
-               cdata->chanv[i].value = ucontrol->value.enumerated.item[i];
+               value = ucontrol->value.enumerated.item[i];
+               change = change || (value != cdata->chanv[i].value);
                cdata->chanv[i].channel = i;
+               cdata->chanv[i].value = value;
        }
 
        /* notify DSP of enum updates */
@@ -163,7 +173,7 @@ int snd_sof_enum_put(struct snd_kcontrol *kcontrol,
                                              SOF_CTRL_CMD_ENUM,
                                              true);
 
-       return 0;
+       return change;
 }
 
 int snd_sof_bytes_get(struct snd_kcontrol *kcontrol,
index 54cd431faab705dd908ff5cde5a9d9b50ede8e68..5529e8eeca462a9bebf8c5e3494a0bca9c6df8cd 100644 (file)
@@ -152,8 +152,10 @@ static ssize_t sof_dfsentry_write(struct file *file, const char __user *buffer,
         */
        dentry = file->f_path.dentry;
        if (strcmp(dentry->d_name.name, "ipc_flood_count") &&
-           strcmp(dentry->d_name.name, "ipc_flood_duration_ms"))
-               return -EINVAL;
+           strcmp(dentry->d_name.name, "ipc_flood_duration_ms")) {
+               ret = -EINVAL;
+               goto out;
+       }
 
        if (!strcmp(dentry->d_name.name, "ipc_flood_duration_ms"))
                flood_duration_test = true;
index 479ba249e219af3ac4acbcd4f52622e51539d601..d62f51d33be148531916c887e6aa046328f5c2dc 100644 (file)
@@ -273,6 +273,16 @@ config SND_SOC_SOF_HDA_AUDIO_CODEC
          Say Y if you want to enable HDAudio codecs with SOF.
          If unsure select "N".
 
+config SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1
+       bool "SOF enable DMI Link L1"
+       help
+         This option enables DMI L1 for both playback and capture
+         and disables known workarounds for specific HDaudio platforms.
+         Only use to look into power optimizations on platforms not
+         affected by DMI L1 issues. This option is not recommended.
+         Say Y if you want to enable DMI Link L1
+         If unsure, select "N".
+
 endif ## SND_SOC_SOF_HDA_COMMON
 
 config SND_SOC_SOF_HDA_LINK_BASELINE
index e282179263e8346f18a24d36389c2a71c8db9f47..80e2826fb447b28524268ccbf598f5f73e75abd7 100644 (file)
@@ -37,6 +37,7 @@
 #define MBOX_SIZE       0x1000
 #define MBOX_DUMP_SIZE 0x30
 #define EXCEPT_OFFSET  0x800
+#define EXCEPT_MAX_HDR_SIZE    0x400
 
 /* DSP peripherals */
 #define DMAC0_OFFSET    0xFE000
@@ -228,6 +229,11 @@ static void bdw_get_registers(struct snd_sof_dev *sdev,
        /* note: variable AR register array is not read */
 
        /* then get panic info */
+       if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) {
+               dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n",
+                       xoops->arch_hdr.totalsize);
+               return;
+       }
        offset += xoops->arch_hdr.totalsize;
        sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info));
 
@@ -451,6 +457,7 @@ static int bdw_probe(struct snd_sof_dev *sdev)
        /* TODO: add offsets */
        sdev->mmio_bar = BDW_DSP_BAR;
        sdev->mailbox_bar = BDW_DSP_BAR;
+       sdev->dsp_oops_offset = MBOX_OFFSET;
 
        /* PCI base */
        mmio = platform_get_resource(pdev, IORESOURCE_MEM,
index 5e7a6aaa627a82490448b9a0ce549eb47b08264e..a1e514f7173952fe899923bd9ffda4009753674f 100644 (file)
@@ -28,6 +28,7 @@
 #define MBOX_OFFSET            0x144000
 #define MBOX_SIZE              0x1000
 #define EXCEPT_OFFSET          0x800
+#define EXCEPT_MAX_HDR_SIZE    0x400
 
 /* DSP peripherals */
 #define DMAC0_OFFSET           0x098000
@@ -126,6 +127,11 @@ static void byt_get_registers(struct snd_sof_dev *sdev,
        /* note: variable AR register array is not read */
 
        /* then get panic info */
+       if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) {
+               dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n",
+                       xoops->arch_hdr.totalsize);
+               return;
+       }
        offset += xoops->arch_hdr.totalsize;
        sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info));
 
index bc41028a7a01de3d101412ebec768aeb3aa21d6f..df1909e1d95060b0b4ddba11d0294b490dca4b03 100644 (file)
@@ -139,20 +139,16 @@ void hda_dsp_ctrl_misc_clock_gating(struct snd_sof_dev *sdev, bool enable)
  */
 int hda_dsp_ctrl_clock_power_gating(struct snd_sof_dev *sdev, bool enable)
 {
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
-       struct hdac_bus *bus = sof_to_bus(sdev);
-#endif
        u32 val;
 
        /* enable/disable audio dsp clock gating */
        val = enable ? PCI_CGCTL_ADSPDCGE : 0;
        snd_sof_pci_update_bits(sdev, PCI_CGCTL, PCI_CGCTL_ADSPDCGE, val);
 
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
-       /* enable/disable L1 support */
-       val = enable ? SOF_HDA_VS_EM2_L1SEN : 0;
-       snd_hdac_chip_updatel(bus, VS_EM2, SOF_HDA_VS_EM2_L1SEN, val);
-#endif
+       /* enable/disable DMI Link L1 support */
+       val = enable ? HDA_VS_INTEL_EM2_L1SEN : 0;
+       snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2,
+                               HDA_VS_INTEL_EM2_L1SEN, val);
 
        /* enable/disable audio dsp power gating */
        val = enable ? 0 : PCI_PGCTL_ADSPPGD;
index 6427f0b3a2f113b7a7a13e65ce66e3e9c7ac8fc0..65c2af3fcaab71ebc559d8e2a4a1b8e9b173b5d1 100644 (file)
@@ -44,6 +44,7 @@ static int cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format,
                return -ENODEV;
        }
        hstream = &dsp_stream->hstream;
+       hstream->substream = NULL;
 
        /* allocate DMA buffer */
        ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, &pci->dev, size, dmab);
index ad8d41f22e92ddcf958cd6ac7f4d13f789d8a5f8..0c11fceb28a7a234c1afde9b9c7bc52fe001bd53 100644 (file)
@@ -185,6 +185,17 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction)
                        direction == SNDRV_PCM_STREAM_PLAYBACK ?
                        "playback" : "capture");
 
+       /*
+        * Disable DMI Link L1 entry when capture stream is opened.
+        * Workaround to address a known issue with host DMA that results
+        * in xruns during pause/release in capture scenarios.
+        */
+       if (!IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1))
+               if (stream && direction == SNDRV_PCM_STREAM_CAPTURE)
+                       snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
+                                               HDA_VS_INTEL_EM2,
+                                               HDA_VS_INTEL_EM2_L1SEN, 0);
+
        return stream;
 }
 
@@ -193,23 +204,43 @@ int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag)
 {
        struct hdac_bus *bus = sof_to_bus(sdev);
        struct hdac_stream *s;
+       bool active_capture_stream = false;
+       bool found = false;
 
        spin_lock_irq(&bus->reg_lock);
 
-       /* find used stream */
+       /*
+        * close stream matching the stream tag
+        * and check if there are any open capture streams.
+        */
        list_for_each_entry(s, &bus->stream_list, list) {
-               if (s->direction == direction &&
-                   s->opened && s->stream_tag == stream_tag) {
+               if (!s->opened)
+                       continue;
+
+               if (s->direction == direction && s->stream_tag == stream_tag) {
                        s->opened = false;
-                       spin_unlock_irq(&bus->reg_lock);
-                       return 0;
+                       found = true;
+               } else if (s->direction == SNDRV_PCM_STREAM_CAPTURE) {
+                       active_capture_stream = true;
                }
        }
 
        spin_unlock_irq(&bus->reg_lock);
 
-       dev_dbg(sdev->dev, "stream_tag %d not opened!\n", stream_tag);
-       return -ENODEV;
+       /* Enable DMI L1 entry if there are no capture streams open */
+       if (!IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1))
+               if (!active_capture_stream)
+                       snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
+                                               HDA_VS_INTEL_EM2,
+                                               HDA_VS_INTEL_EM2_L1SEN,
+                                               HDA_VS_INTEL_EM2_L1SEN);
+
+       if (!found) {
+               dev_dbg(sdev->dev, "stream_tag %d not opened!\n", stream_tag);
+               return -ENODEV;
+       }
+
+       return 0;
 }
 
 int hda_dsp_stream_trigger(struct snd_sof_dev *sdev,
index c72e9a09eee16a03da41267f127fdf0dbfc1b95d..06e84679087bc6bcb81a9988195475e6f042a354 100644 (file)
@@ -35,6 +35,8 @@
 #define IS_CFL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa348)
 #define IS_CNL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9dc8)
 
+#define EXCEPT_MAX_HDR_SIZE    0x400
+
 /*
  * Debug
  */
@@ -131,6 +133,11 @@ static void hda_dsp_get_registers(struct snd_sof_dev *sdev,
        /* note: variable AR register array is not read */
 
        /* then get panic info */
+       if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) {
+               dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n",
+                       xoops->arch_hdr.totalsize);
+               return;
+       }
        offset += xoops->arch_hdr.totalsize;
        sof_block_read(sdev, sdev->mmio_bar, offset,
                       panic_info, sizeof(*panic_info));
index 5591841a1b6faf9a72aec8a94b9082e1561f1e75..23e430d3e056881853cc193e549ede0334b624da 100644 (file)
@@ -39,7 +39,6 @@
 #define SOF_HDA_WAKESTS                        0x0E
 #define SOF_HDA_WAKESTS_INT_MASK       ((1 << 8) - 1)
 #define SOF_HDA_RIRBSTS                        0x5d
-#define SOF_HDA_VS_EM2_L1SEN            BIT(13)
 
 /* SOF_HDA_GCTL register bist */
 #define SOF_HDA_GCTL_RESET             BIT(0)
 #define HDA_DSP_REG_HIPCIE             (HDA_DSP_IPC_BASE + 0x0C)
 #define HDA_DSP_REG_HIPCCTL            (HDA_DSP_IPC_BASE + 0x10)
 
+/* Intel Vendor Specific Registers */
+#define HDA_VS_INTEL_EM2               0x1030
+#define HDA_VS_INTEL_EM2_L1SEN         BIT(13)
+
 /*  HIPCI */
 #define HDA_DSP_REG_HIPCI_BUSY         BIT(31)
 #define HDA_DSP_REG_HIPCI_MSG_MASK     0x7FFFFFFF
index b2f359d2f7e530b3813ce2b78ae6175272f17e4b..086eeeab8679555b4b5fe87b2bc312fa4b5ef1ef 100644 (file)
@@ -572,8 +572,10 @@ static int sof_set_get_large_ctrl_data(struct snd_sof_dev *sdev,
        else
                err = sof_get_ctrl_copy_params(cdata->type, partdata, cdata,
                                               sparams);
-       if (err < 0)
+       if (err < 0) {
+               kfree(partdata);
                return err;
+       }
 
        msg_bytes = sparams->msg_bytes;
        pl_size = sparams->pl_size;
index d7f32745fefe42a793baf869c33318b57a9e44a0..9a9a381a908dee467665c979fecc7d31fb58e3bc 100644 (file)
@@ -546,10 +546,10 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev)
                                 msecs_to_jiffies(sdev->boot_timeout));
        if (ret == 0) {
                dev_err(sdev->dev, "error: firmware boot failure\n");
-               /* after this point FW_READY msg should be ignored */
-               sdev->boot_complete = true;
                snd_sof_dsp_dbg_dump(sdev, SOF_DBG_REGS | SOF_DBG_MBOX |
                        SOF_DBG_TEXT | SOF_DBG_PCI);
+               /* after this point FW_READY msg should be ignored */
+               sdev->boot_complete = true;
                return -EIO;
        }
 
index e3f6a6dc0f368af0614c1080cbfb678f9e832958..2b876d4974476bd359d4f530cabfeb92776b3164 100644 (file)
@@ -244,7 +244,7 @@ static int sof_pcm_hw_free(struct snd_pcm_substream *substream)
                snd_soc_rtdcom_lookup(rtd, DRV_NAME);
        struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
        struct snd_sof_pcm *spcm;
-       int ret;
+       int ret, err = 0;
 
        /* nothing to do for BE */
        if (rtd->dai_link->no_pcm)
@@ -254,26 +254,26 @@ static int sof_pcm_hw_free(struct snd_pcm_substream *substream)
        if (!spcm)
                return -EINVAL;
 
-       if (!spcm->prepared[substream->stream])
-               return 0;
-
        dev_dbg(sdev->dev, "pcm: free stream %d dir %d\n", spcm->pcm.pcm_id,
                substream->stream);
 
-       ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);
+       if (spcm->prepared[substream->stream]) {
+               ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);
+               if (ret < 0)
+                       err = ret;
+       }
 
        snd_pcm_lib_free_pages(substream);
 
        cancel_work_sync(&spcm->stream[substream->stream].period_elapsed_work);
 
-       if (ret < 0)
-               return ret;
-
        ret = snd_sof_pcm_platform_hw_free(sdev, substream);
-       if (ret < 0)
+       if (ret < 0) {
                dev_err(sdev->dev, "error: platform hw free failed\n");
+               err = ret;
+       }
 
-       return ret;
+       return err;
 }
 
 static int sof_pcm_prepare(struct snd_pcm_substream *substream)
@@ -323,6 +323,7 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        struct sof_ipc_stream stream;
        struct sof_ipc_reply reply;
        bool reset_hw_params = false;
+       bool ipc_first = false;
        int ret;
 
        /* nothing to do for BE */
@@ -343,6 +344,7 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_PAUSE;
+               ipc_first = true;
                break;
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_RELEASE;
@@ -363,6 +365,7 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_STOP:
                stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_STOP;
+               ipc_first = true;
                reset_hw_params = true;
                break;
        default:
@@ -370,12 +373,22 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
                return -EINVAL;
        }
 
-       snd_sof_pcm_platform_trigger(sdev, substream, cmd);
+       /*
+        * DMA and IPC sequence is different for start and stop. Need to send
+        * STOP IPC before stop DMA
+        */
+       if (!ipc_first)
+               snd_sof_pcm_platform_trigger(sdev, substream, cmd);
 
        /* send IPC to the DSP */
        ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream,
                                 sizeof(stream), &reply, sizeof(reply));
 
+       /* need to STOP DMA even if STOP IPC failed */
+       if (ipc_first)
+               snd_sof_pcm_platform_trigger(sdev, substream, cmd);
+
+       /* free PCM if reset_hw_params is set and the STOP IPC is successful */
        if (!ret && reset_hw_params)
                ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);
 
index fc85efbad378c7308e4c410b5a9e6f6d3683c07b..4452594c2e17adfa3f191e26bd4666c160524c20 100644 (file)
@@ -543,15 +543,16 @@ static int sof_control_load_bytes(struct snd_soc_component *scomp,
        struct soc_bytes_ext *sbe = (struct soc_bytes_ext *)kc->private_value;
        int max_size = sbe->max;
 
-       if (le32_to_cpu(control->priv.size) > max_size) {
+       /* init the get/put bytes data */
+       scontrol->size = sizeof(struct sof_ipc_ctrl_data) +
+               le32_to_cpu(control->priv.size);
+
+       if (scontrol->size > max_size) {
                dev_err(sdev->dev, "err: bytes data size %d exceeds max %d.\n",
-                       control->priv.size, max_size);
+                       scontrol->size, max_size);
                return -EINVAL;
        }
 
-       /* init the get/put bytes data */
-       scontrol->size = sizeof(struct sof_ipc_ctrl_data) +
-               le32_to_cpu(control->priv.size);
        scontrol->control_data = kzalloc(max_size, GFP_KERNEL);
        cdata = scontrol->control_data;
        if (!scontrol->control_data)
@@ -920,7 +921,9 @@ static void sof_parse_word_tokens(struct snd_soc_component *scomp,
                for (j = 0; j < count; j++) {
                        /* match token type */
                        if (!(tokens[j].type == SND_SOC_TPLG_TUPLE_TYPE_WORD ||
-                             tokens[j].type == SND_SOC_TPLG_TUPLE_TYPE_SHORT))
+                             tokens[j].type == SND_SOC_TPLG_TUPLE_TYPE_SHORT ||
+                             tokens[j].type == SND_SOC_TPLG_TUPLE_TYPE_BYTE ||
+                             tokens[j].type == SND_SOC_TPLG_TUPLE_TYPE_BOOL))
                                continue;
 
                        /* match token id */
index d7501f88aaa630afb61fe87352eb1bcb287b9700..48e629ac2d88b630778004f652cd84b4f3b53dbd 100644 (file)
@@ -505,10 +505,20 @@ static int stm32_sai_set_sysclk(struct snd_soc_dai *cpu_dai,
        if (dir == SND_SOC_CLOCK_OUT && sai->sai_mclk) {
                ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX,
                                         SAI_XCR1_NODIV,
-                                        (unsigned int)~SAI_XCR1_NODIV);
+                                        freq ? 0 : SAI_XCR1_NODIV);
                if (ret < 0)
                        return ret;
 
+               /* Assume shutdown if requested frequency is 0Hz */
+               if (!freq) {
+                       /* Release mclk rate only if rate was actually set */
+                       if (sai->mclk_rate) {
+                               clk_rate_exclusive_put(sai->sai_mclk);
+                               sai->mclk_rate = 0;
+                       }
+                       return 0;
+               }
+
                /* If master clock is used, set parent clock now */
                ret = stm32_sai_set_parent_clock(sai, freq);
                if (ret)
@@ -1093,15 +1103,6 @@ static void stm32_sai_shutdown(struct snd_pcm_substream *substream,
 
        regmap_update_bits(sai->regmap, STM_SAI_IMR_REGX, SAI_XIMR_MASK, 0);
 
-       regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, SAI_XCR1_NODIV,
-                          SAI_XCR1_NODIV);
-
-       /* Release mclk rate only if rate was actually set */
-       if (sai->mclk_rate) {
-               clk_rate_exclusive_put(sai->sai_mclk);
-               sai->mclk_rate = 0;
-       }
-
        clk_disable_unprepare(sai->sai_ck);
 
        spin_lock_irqsave(&sai->irq_lock, flags);
@@ -1217,6 +1218,16 @@ static int stm32_sai_pcm_process_spdif(struct snd_pcm_substream *substream,
        return 0;
 }
 
+/* No support of mmap in S/PDIF mode */
+static const struct snd_pcm_hardware stm32_sai_pcm_hw_spdif = {
+       .info = SNDRV_PCM_INFO_INTERLEAVED,
+       .buffer_bytes_max = 8 * PAGE_SIZE,
+       .period_bytes_min = 1024,
+       .period_bytes_max = PAGE_SIZE,
+       .periods_min = 2,
+       .periods_max = 8,
+};
+
 static const struct snd_pcm_hardware stm32_sai_pcm_hw = {
        .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP,
        .buffer_bytes_max = 8 * PAGE_SIZE,
@@ -1269,7 +1280,7 @@ static const struct snd_dmaengine_pcm_config stm32_sai_pcm_config = {
 };
 
 static const struct snd_dmaengine_pcm_config stm32_sai_pcm_config_spdif = {
-       .pcm_hardware = &stm32_sai_pcm_hw,
+       .pcm_hardware = &stm32_sai_pcm_hw_spdif,
        .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
        .process = stm32_sai_pcm_process_spdif,
 };
index a236350beb102504c6d0f2fbaac3ff40649844a0..2b0bc234e1b69f793b919e464eaa25175c18bd9a 100644 (file)
@@ -62,7 +62,7 @@ int sdma_pcm_platform_register(struct device *dev,
        config->chan_names[0] = txdmachan;
        config->chan_names[1] = rxdmachan;
 
-       return devm_snd_dmaengine_pcm_register(dev, config, 0);
+       return devm_snd_dmaengine_pcm_register(dev, config, flags);
 }
 EXPORT_SYMBOL_GPL(sdma_pcm_platform_register);
 
index fbfde996fee76df28b56439c0030fb1cb0de7da3..0bbe1201a6ac8c57c7ae533e516c92fe67f832a7 100644 (file)
@@ -1657,6 +1657,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
        case 0x23ba:  /* Playback Designs */
        case 0x25ce:  /* Mytek devices */
        case 0x278b:  /* Rotel? */
+       case 0x292b:  /* Gustard/Ess based devices */
        case 0x2ab6:  /* T+A devices */
        case 0x3842:  /* EVGA */
        case 0xc502:  /* HiBy devices */
index 3c8f73a0eb12254385f9b2ed007bafc46ee74109..a5e584b60dcd83efd9b6732980e72e074e160c31 100644 (file)
@@ -75,7 +75,7 @@ static bool validate_processing_unit(const void *p,
 
        if (d->bLength < sizeof(*d))
                return false;
-       len = d->bLength < sizeof(*d) + d->bNrInPins;
+       len = sizeof(*d) + d->bNrInPins;
        if (d->bLength < len)
                return false;
        switch (v->protocol) {
index a9731f8a480f3bca0785c94e870c74be6c191a67..2e8a30f06c74641cead87f4f460089f081c63ea7 100644 (file)
@@ -75,6 +75,7 @@
 #define SVM_EXIT_MWAIT         0x08b
 #define SVM_EXIT_MWAIT_COND    0x08c
 #define SVM_EXIT_XSETBV        0x08d
+#define SVM_EXIT_RDPRU         0x08e
 #define SVM_EXIT_NPF           0x400
 #define SVM_EXIT_AVIC_INCOMPLETE_IPI           0x401
 #define SVM_EXIT_AVIC_UNACCELERATED_ACCESS     0x402
index f01950aa7faedb951bfc8480536f9e4fe0a8b408..3eb8411ab60efb14e4890c711569bfe3259c8687 100644 (file)
@@ -86,6 +86,8 @@
 #define EXIT_REASON_PML_FULL            62
 #define EXIT_REASON_XSAVES              63
 #define EXIT_REASON_XRSTORS             64
+#define EXIT_REASON_UMWAIT              67
+#define EXIT_REASON_TPAUSE              68
 
 #define VMX_EXIT_REASONS \
        { EXIT_REASON_EXCEPTION_NMI,         "EXCEPTION_NMI" }, \
        { EXIT_REASON_RDSEED,                "RDSEED" }, \
        { EXIT_REASON_PML_FULL,              "PML_FULL" }, \
        { EXIT_REASON_XSAVES,                "XSAVES" }, \
-       { EXIT_REASON_XRSTORS,               "XRSTORS" }
+       { EXIT_REASON_XRSTORS,               "XRSTORS" }, \
+       { EXIT_REASON_UMWAIT,                "UMWAIT" }, \
+       { EXIT_REASON_TPAUSE,                "TPAUSE" }
 
 #define VMX_ABORT_SAVE_GUEST_MSR_FAIL        1
 #define VMX_ABORT_LOAD_HOST_PDPTE_FAIL       2
index 6ecdd10678260f278475787af8d7b1e61e970bae..1178d302757ea71977e95d6880445839434fcf4b 100644 (file)
@@ -3,7 +3,11 @@ include ../scripts/Makefile.include
 
 bindir ?= /usr/bin
 
-ifeq ($(srctree),)
+# This will work when gpio is built in tools env. where srctree
+# isn't set and when invoked from selftests build, where srctree
+# is set to ".". building_out_of_srctree is undefined for in srctree
+# builds
+ifndef building_out_of_srctree
 srctree := $(patsubst %/,%,$(dir $(CURDIR)))
 srctree := $(patsubst %/,%,$(dir $(srctree)))
 endif
index 233efbb1c81ca153c64693814d8518756284e1d0..52641d8ca9e83f25b983f3cc6be115c37bad2d98 100644 (file)
@@ -999,6 +999,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_ARM_PTRAUTH_GENERIC 172
 #define KVM_CAP_PMU_EVENT_FILTER 173
 #define KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 174
+#define KVM_CAP_HYPERV_DIRECT_TLBFLUSH 175
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1145,6 +1146,7 @@ struct kvm_dirty_tlb {
 #define KVM_REG_S390           0x5000000000000000ULL
 #define KVM_REG_ARM64          0x6000000000000000ULL
 #define KVM_REG_MIPS           0x7000000000000000ULL
+#define KVM_REG_RISCV          0x8000000000000000ULL
 
 #define KVM_REG_SIZE_SHIFT     52
 #define KVM_REG_SIZE_MASK      0x00f0000000000000ULL
index b3105ac1381a8d8651f7f2fbe6b700bd745ead01..99335e1f4a275b1dbc86219a6dee7701b18fd624 100644 (file)
 #define CLONE_NEWNET           0x40000000      /* New network namespace */
 #define CLONE_IO               0x80000000      /* Clone io context */
 
-/*
- * Arguments for the clone3 syscall
+#ifndef __ASSEMBLY__
+/**
+ * struct clone_args - arguments for the clone3 syscall
+ * @flags:       Flags for the new process as listed above.
+ *               All flags are valid except for CSIGNAL and
+ *               CLONE_DETACHED.
+ * @pidfd:       If CLONE_PIDFD is set, a pidfd will be
+ *               returned in this argument.
+ * @child_tid:   If CLONE_CHILD_SETTID is set, the TID of the
+ *               child process will be returned in the child's
+ *               memory.
+ * @parent_tid:  If CLONE_PARENT_SETTID is set, the TID of
+ *               the child process will be returned in the
+ *               parent's memory.
+ * @exit_signal: The exit_signal the parent process will be
+ *               sent when the child exits.
+ * @stack:       Specify the location of the stack for the
+ *               child process.
+ * @stack_size:  The size of the stack for the child process.
+ * @tls:         If CLONE_SETTLS is set, the tls descriptor
+ *               is set to tls.
+ *
+ * The structure is versioned by size and thus extensible.
+ * New struct members must go at the end of the struct and
+ * must be properly 64bit aligned.
  */
 struct clone_args {
        __aligned_u64 flags;
@@ -46,6 +69,9 @@ struct clone_args {
        __aligned_u64 stack_size;
        __aligned_u64 tls;
 };
+#endif
+
+#define CLONE_ARGS_SIZE_VER0 64 /* sizeof first published struct */
 
 /*
  * Scheduling policies
index 3542b6ab9813b5bf7d79a95aafbb1400cef13c2a..e69f44941aad9a7bed7f4a3cbc0d218f84985081 100644 (file)
@@ -2635,6 +2635,7 @@ static int build_cl_output(char *cl_sort, bool no_source)
        bool add_sym   = false;
        bool add_dso   = false;
        bool add_src   = false;
+       int ret = 0;
 
        if (!buf)
                return -ENOMEM;
@@ -2653,7 +2654,8 @@ static int build_cl_output(char *cl_sort, bool no_source)
                        add_dso = true;
                } else if (strcmp(tok, "offset")) {
                        pr_err("unrecognized sort token: %s\n", tok);
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto err;
                }
        }
 
@@ -2676,13 +2678,15 @@ static int build_cl_output(char *cl_sort, bool no_source)
                add_sym ? "symbol," : "",
                add_dso ? "dso," : "",
                add_src ? "cl_srcline," : "",
-               "node") < 0)
-               return -ENOMEM;
+               "node") < 0) {
+               ret = -ENOMEM;
+               goto err;
+       }
 
        c2c.show_src = add_src;
-
+err:
        free(buf);
-       return 0;
+       return ret;
 }
 
 static int setup_coalesce(const char *coalesce, bool no_source)
index 1e61e353f579bc6e6910eb9906485f2115eac69d..9661671cc26ec29029b895aa3a4c630a31e65cd0 100644 (file)
@@ -691,6 +691,7 @@ static char *compact_gfp_flags(char *gfp_flags)
                        new = realloc(new_flags, len + strlen(cpt) + 2);
                        if (new == NULL) {
                                free(new_flags);
+                               free(orig_flags);
                                return NULL;
                        }
 
index 1e148bbdf820f69efcd97fa07ec4befb993b1751..202cadaaf097bdbb0135bca174f7fa92bf208aa9 100644 (file)
@@ -2,7 +2,7 @@ jvmti-y += libjvmti.o
 jvmti-y += jvmti_agent.o
 
 # For strlcpy
-jvmti-y += libstring.o
+jvmti-y += libstring.o libctype.o
 
 CFLAGS_jvmti         = -fPIC -DPIC -I$(JDIR)/include -I$(JDIR)/include/linux
 CFLAGS_REMOVE_jvmti  = -Wmissing-declarations
@@ -15,3 +15,7 @@ CFLAGS_libstring.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PE
 $(OUTPUT)jvmti/libstring.o: ../lib/string.c FORCE
        $(call rule_mkdir)
        $(call if_changed_dep,cc_o_c)
+
+$(OUTPUT)jvmti/libctype.o: ../lib/ctype.c FORCE
+       $(call rule_mkdir)
+       $(call if_changed_dep,cc_o_c)
index 63e4349a772adb540556285da1c89cb165a44e7c..15e458e150bd8c9d17302c4cbb1dd0c875ef1f9b 100644 (file)
@@ -15,7 +15,9 @@ void test_attr__init(void);
 void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu,
                     int fd, int group_fd, unsigned long flags);
 
-#define HAVE_ATTR_TEST
+#ifndef HAVE_ATTR_TEST
+#define HAVE_ATTR_TEST 1
+#endif
 
 static inline int
 sys_perf_event_open(struct perf_event_attr *attr,
@@ -27,7 +29,7 @@ sys_perf_event_open(struct perf_event_attr *attr,
        fd = syscall(__NR_perf_event_open, attr, pid, cpu,
                     group_fd, flags);
 
-#ifdef HAVE_ATTR_TEST
+#if HAVE_ATTR_TEST
        if (unlikely(test_attr__enabled))
                test_attr__open(attr, pid, cpu, fd, group_fd, flags);
 #endif
index 4036c7f7b0fbcfa1c8c61ab115d71324fd3334b7..e42bf572358c7edd584ad43309f0e02a336dfebd 100644 (file)
@@ -1758,7 +1758,7 @@ static int symbol__disassemble_bpf(struct symbol *sym,
        info_node = perf_env__find_bpf_prog_info(dso->bpf_prog.env,
                                                 dso->bpf_prog.id);
        if (!info_node) {
-               return SYMBOL_ANNOTATE_ERRNO__BPF_MISSING_BTF;
+               ret = SYMBOL_ANNOTATE_ERRNO__BPF_MISSING_BTF;
                goto out;
        }
        info_linear = info_node->info_linear;
index 3fa0db1366676aa2ac047d6a5674e04c453837ba..47e03de7c2358a0d2c7150190a5b811b4ef7b133 100644 (file)
@@ -101,14 +101,16 @@ static int copyfile_mode_ns(const char *from, const char *to, mode_t mode,
        if (tofd < 0)
                goto out;
 
-       if (fchmod(tofd, mode))
-               goto out_close_to;
-
        if (st.st_size == 0) { /* /proc? do it slowly... */
                err = slow_copyfile(from, tmp, nsi);
+               if (!err && fchmod(tofd, mode))
+                       err = -1;
                goto out_close_to;
        }
 
+       if (fchmod(tofd, mode))
+               goto out_close_to;
+
        nsinfo__mountns_enter(nsi, &nsc);
        fromfd = open(from, O_RDONLY);
        nsinfo__mountns_exit(&nsc);
index d277a98e62df8f769dbf88e45b6b635b085050e6..de79c735e4411b182ce9da0d4d8baee120eaed15 100644 (file)
@@ -1659,7 +1659,7 @@ struct evsel *perf_evlist__reset_weak_group(struct evlist *evsel_list,
                        is_open = false;
                if (c2->leader == leader) {
                        if (is_open)
-                               perf_evsel__close(&evsel->core);
+                               perf_evsel__close(&c2->core);
                        c2->leader = c2;
                        c2->core.nr_members = 0;
                }
index 86d9396cb131cdca6731da256f3a10460827b6cf..becc2d1094237580901dfe0578ad63900cc77635 100644 (file)
@@ -1296,8 +1296,10 @@ static int build_mem_topology(struct memory_node *nodes, u64 size, u64 *cntp)
                        continue;
 
                if (WARN_ONCE(cnt >= size,
-                             "failed to write MEM_TOPOLOGY, way too many nodes\n"))
+                       "failed to write MEM_TOPOLOGY, way too many nodes\n")) {
+                       closedir(dir);
                        return -1;
+               }
 
                ret = memory_node__read(&nodes[cnt++], idx);
        }
index 679a1d75090ce10a9652f93479a0f233037ffc92..7b6eaf5e0bda51d512c3ab216b0ef224bd45b26d 100644 (file)
@@ -1625,7 +1625,7 @@ int hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
        return 0;
 }
 
-static int hist_entry__sort(struct hist_entry *a, struct hist_entry *b)
+static int64_t hist_entry__sort(struct hist_entry *a, struct hist_entry *b)
 {
        struct hists *hists = a->hists;
        struct perf_hpp_fmt *fmt;
index 15961854ba67d0d09fec7fd96f87035cb1ea53bf..741f040648b57b11d7e88cc3a68633916b359611 100644 (file)
@@ -539,10 +539,11 @@ static int perl_stop_script(void)
 
 static int perl_generate_script(struct tep_handle *pevent, const char *outfile)
 {
+       int i, not_first, count, nr_events;
+       struct tep_event **all_events;
        struct tep_event *event = NULL;
        struct tep_format_field *f;
        char fname[PATH_MAX];
-       int not_first, count;
        FILE *ofp;
 
        sprintf(fname, "%s.pl", outfile);
@@ -603,8 +604,11 @@ sub print_backtrace\n\
 }\n\n\
 ");
 
+       nr_events = tep_get_events_count(pevent);
+       all_events = tep_list_events(pevent, TEP_EVENT_SORT_ID);
 
-       while ((event = trace_find_next_event(pevent, event))) {
+       for (i = 0; all_events && i < nr_events; i++) {
+               event = all_events[i];
                fprintf(ofp, "sub %s::%s\n{\n", event->system, event->name);
                fprintf(ofp, "\tmy (");
 
index 5d341efc3237d6d5f423b5a9adf8b930ded91a58..93c03b39cd9cdb94fd85bd4a525346a6cea34af3 100644 (file)
@@ -1687,10 +1687,11 @@ static int python_stop_script(void)
 
 static int python_generate_script(struct tep_handle *pevent, const char *outfile)
 {
+       int i, not_first, count, nr_events;
+       struct tep_event **all_events;
        struct tep_event *event = NULL;
        struct tep_format_field *f;
        char fname[PATH_MAX];
-       int not_first, count;
        FILE *ofp;
 
        sprintf(fname, "%s.py", outfile);
@@ -1735,7 +1736,11 @@ static int python_generate_script(struct tep_handle *pevent, const char *outfile
        fprintf(ofp, "def trace_end():\n");
        fprintf(ofp, "\tprint(\"in trace_end\")\n\n");
 
-       while ((event = trace_find_next_event(pevent, event))) {
+       nr_events = tep_get_events_count(pevent);
+       all_events = tep_list_events(pevent, TEP_EVENT_SORT_ID);
+
+       for (i = 0; all_events && i < nr_events; i++) {
+               event = all_events[i];
                fprintf(ofp, "def %s__%s(", event->system, event->name);
                fprintf(ofp, "event_name, ");
                fprintf(ofp, "context, ");
index 5d6bfc70b210f0e7b185b2479212af9025a1e99d..9634f0ae57bea0d3fda57abdd6c4673282bffa00 100644 (file)
@@ -173,37 +173,6 @@ int parse_event_file(struct tep_handle *pevent,
        return tep_parse_event(pevent, buf, size, sys);
 }
 
-struct tep_event *trace_find_next_event(struct tep_handle *pevent,
-                                       struct tep_event *event)
-{
-       static int idx;
-       int events_count;
-       struct tep_event *all_events;
-
-       all_events = tep_get_first_event(pevent);
-       events_count = tep_get_events_count(pevent);
-       if (!pevent || !all_events || events_count < 1)
-               return NULL;
-
-       if (!event) {
-               idx = 0;
-               return all_events;
-       }
-
-       if (idx < events_count && event == (all_events + idx)) {
-               idx++;
-               if (idx == events_count)
-                       return NULL;
-               return (all_events + idx);
-       }
-
-       for (idx = 1; idx < events_count; idx++) {
-               if (event == (all_events + (idx - 1)))
-                       return (all_events + idx);
-       }
-       return NULL;
-}
-
 struct flag {
        const char *name;
        unsigned long long value;
index 2e158387b3d776cd1d1de974d2cae7e3260f0096..72fdf2a3577c04a7937c35e3d816338530b1107a 100644 (file)
@@ -47,8 +47,6 @@ void parse_saved_cmdline(struct tep_handle *pevent, char *file, unsigned int siz
 
 ssize_t trace_report(int fd, struct trace_event *tevent, bool repipe);
 
-struct tep_event *trace_find_next_event(struct tep_handle *pevent,
-                                       struct tep_event *event);
 unsigned long long read_size(struct tep_event *event, void *ptr, int size);
 unsigned long long eval_flag(const char *flag);
 
index 5eda6e19c94745e4df80a0df5c25b91919f47d2e..ae56c766eda16e0d51560fcea4532843d2c96bb8 100644 (file)
@@ -154,8 +154,10 @@ static int rm_rf_depth_pat(const char *path, int depth, const char **pat)
                if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
                        continue;
 
-               if (!match_pat(d->d_name, pat))
-                       return -2;
+               if (!match_pat(d->d_name, pat)) {
+                       ret =  -2;
+                       break;
+               }
 
                scnprintf(namebuf, sizeof(namebuf), "%s/%s",
                          path, d->d_name);
index 15a666329a34df435dad7021845c0cbb377fb615..1afa22c88e42a85e49a299eb1e0ff72f8fbbae3d 100755 (executable)
@@ -22,6 +22,7 @@ import os
 import pprint
 import random
 import re
+import stat
 import string
 import struct
 import subprocess
@@ -311,7 +312,11 @@ class DebugfsDir:
         for f in out.split():
             if f == "ports":
                 continue
+
             p = os.path.join(path, f)
+            if not os.stat(p).st_mode & stat.S_IRUSR:
+                continue
+
             if os.path.isfile(p):
                 _, out = cmd('cat %s/%s' % (path, f))
                 dfs[f] = out.strip()
index a320e3844b17f18afda20da8724af83ca32f9ae2..7c6e5b173f3342802b30419fdb3e2548788624a0 100644 (file)
@@ -161,9 +161,14 @@ static struct sysctl_test tests[] = {
                .descr = "ctx:file_pos sysctl:read read ok narrow",
                .insns = {
                        /* If (file_pos == X) */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
                        BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_1,
                                    offsetof(struct bpf_sysctl, file_pos)),
-                       BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0, 2),
+#else
+                       BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_1,
+                                   offsetof(struct bpf_sysctl, file_pos) + 3),
+#endif
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 4, 2),
 
                        /* return ALLOW; */
                        BPF_MOV64_IMM(BPF_REG_0, 1),
@@ -176,6 +181,7 @@ static struct sysctl_test tests[] = {
                .attach_type = BPF_CGROUP_SYSCTL,
                .sysctl = "kernel/ostype",
                .open_flags = O_RDONLY,
+               .seek = 4,
                .result = SUCCESS,
        },
        {
index f38567ef694b6e34cae650cad1676e1fe7391d6e..daa7d1b8d30925ea09a1357cd5cecae709bb7a39 100755 (executable)
@@ -59,7 +59,7 @@ ip netns exec ${NS_SRC} tc filter add dev veth_src egress \
 
 # start the listener
 ip netns exec ${NS_DST} bash -c \
-       "nc -4 -l -s ${IP_DST} -p 9000 >/dev/null &"
+       "nc -4 -l -p 9000 >/dev/null &"
 declare -i NC_PID=$!
 sleep 1
 
index b35da375530afb1a3d2166aeac07c49f4cff11a7..409c1fa75e03575c2c04736b325b0484ae8fd65a 100644 (file)
@@ -1,4 +1,5 @@
 /s390x/sync_regs_test
+/s390x/memop
 /x86_64/cr4_cpuid_sync_test
 /x86_64/evmcs_test
 /x86_64/hyperv_cpuid
@@ -9,6 +10,7 @@
 /x86_64/state_test
 /x86_64/sync_regs_test
 /x86_64/vmx_close_while_nested_test
+/x86_64/vmx_dirty_log_test
 /x86_64/vmx_set_nested_state_test
 /x86_64/vmx_tsc_adjust_test
 /clear_dirty_log_test
index 6ae5a47fe067dd0a7fb0e753ca766ed8c0a745a5..f52e0ba84fedb0fe364998bda8da1e9d8f21ee1f 100644 (file)
@@ -580,6 +580,8 @@ bool prepare_for_vmx_operation(struct vmx_pages *vmx);
 void prepare_vmcs(struct vmx_pages *vmx, void *guest_rip, void *guest_rsp);
 bool load_vmcs(struct vmx_pages *vmx);
 
+void nested_vmx_check_supported(void);
+
 void nested_pg_map(struct vmx_pages *vmx, struct kvm_vm *vm,
                   uint64_t nested_paddr, uint64_t paddr, uint32_t eptp_memslot);
 void nested_map(struct vmx_pages *vmx, struct kvm_vm *vm,
index fab8f6b0bf52a6d9a68d4d4125c9897123b9e48d..f6ec97b7eaef67b6cbce47f1d6a7fa0fb3ef1e0e 100644 (file)
@@ -376,6 +376,16 @@ void prepare_vmcs(struct vmx_pages *vmx, void *guest_rip, void *guest_rsp)
        init_vmcs_guest_state(guest_rip, guest_rsp);
 }
 
+void nested_vmx_check_supported(void)
+{
+       struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1);
+
+       if (!(entry->ecx & CPUID_VMX)) {
+               fprintf(stderr, "nested VMX not enabled, skipping test\n");
+               exit(KSFT_SKIP);
+       }
+}
+
 void nested_pg_map(struct vmx_pages *vmx, struct kvm_vm *vm,
                   uint64_t nested_paddr, uint64_t paddr, uint32_t eptp_memslot)
 {
index 11c2a70a7b87a5df60772eefee2284be3376eaf1..5c82242562943fe36e14ff3bb24a4745a16ce76b 100644 (file)
 
 #define VCPU_ID 5
 
+#define UCALL_PIO_PORT ((uint16_t)0x1000)
+
+/*
+ * ucall is embedded here to protect against compiler reshuffling registers
+ * before calling a function. In this test we only need to get KVM_EXIT_IO
+ * vmexit and preserve RBX, no additional information is needed.
+ */
 void guest_code(void)
 {
-       /*
-        * use a callee-save register, otherwise the compiler
-        * saves it around the call to GUEST_SYNC.
-        */
-       register u32 stage asm("rbx");
-       for (;;) {
-               GUEST_SYNC(0);
-               stage++;
-               asm volatile ("" : : "r" (stage));
-       }
+       asm volatile("1: in %[port], %%al\n"
+                    "add $0x1, %%rbx\n"
+                    "jmp 1b"
+                    : : [port] "d" (UCALL_PIO_PORT) : "rax", "rbx");
 }
 
 static void compare_regs(struct kvm_regs *left, struct kvm_regs *right)
index 3b0ffe01dacd06e986bb1a66999af64ef5a75dae..5dfb53546a266d3681e32d7e2fd1fcb42fb3166f 100644 (file)
@@ -53,12 +53,8 @@ static void l1_guest_code(struct vmx_pages *vmx_pages)
 int main(int argc, char *argv[])
 {
        vm_vaddr_t vmx_pages_gva;
-       struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1);
 
-       if (!(entry->ecx & CPUID_VMX)) {
-               fprintf(stderr, "nested VMX not enabled, skipping test\n");
-               exit(KSFT_SKIP);
-       }
+       nested_vmx_check_supported();
 
        vm = vm_create_default(VCPU_ID, 0, (void *) l1_guest_code);
        vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
index 0bca1cfe2c1e237d72f6017b58f3987947098a28..a223a640125843fde425c0a7b530b4f7c094500c 100644 (file)
@@ -78,6 +78,8 @@ int main(int argc, char *argv[])
        struct ucall uc;
        bool done = false;
 
+       nested_vmx_check_supported();
+
        /* Create VM */
        vm = vm_create_default(VCPU_ID, 0, l1_guest_code);
        vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
index 853e370e8a3942c559925f37d0387e68a81aeef0..9ef7fab39d4878b937a435dce9fa7859dc687f39 100644 (file)
@@ -224,7 +224,6 @@ int main(int argc, char *argv[])
 {
        struct kvm_vm *vm;
        struct kvm_nested_state state;
-       struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1);
 
        have_evmcs = kvm_check_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS);
 
@@ -237,10 +236,7 @@ int main(int argc, char *argv[])
         * AMD currently does not implement set_nested_state, so for now we
         * just early out.
         */
-       if (!(entry->ecx & CPUID_VMX)) {
-               fprintf(stderr, "nested VMX not enabled, skipping test\n");
-               exit(KSFT_SKIP);
-       }
+       nested_vmx_check_supported();
 
        vm = vm_create_default(VCPU_ID, 0, 0);
 
@@ -271,12 +267,7 @@ int main(int argc, char *argv[])
        state.flags = KVM_STATE_NESTED_RUN_PENDING;
        test_nested_state_expect_einval(vm, &state);
 
-       /*
-        * TODO: When SVM support is added for KVM_SET_NESTED_STATE
-        *       add tests here to support it like VMX.
-        */
-       if (entry->ecx & CPUID_VMX)
-               test_vmx_nested_state(vm);
+       test_vmx_nested_state(vm);
 
        kvm_vm_free(vm);
        return 0;
index f36c10eba71edc6b4b1786d4976a4a11e774c20b..5590fd2bcf87d450e22946ab378620d043094533 100644 (file)
@@ -128,12 +128,8 @@ static void report(int64_t val)
 int main(int argc, char *argv[])
 {
        vm_vaddr_t vmx_pages_gva;
-       struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1);
 
-       if (!(entry->ecx & CPUID_VMX)) {
-               fprintf(stderr, "nested VMX not enabled, skipping test\n");
-               exit(KSFT_SKIP);
-       }
+       nested_vmx_check_supported();
 
        vm = vm_create_default(VCPU_ID, 0, (void *) l1_guest_code);
        vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
index c4ba0ff4a53faefa225ef847fcb544f6cea6510d..76c1897e6352fefd9f5962549a7ac937c249b883 100755 (executable)
@@ -1438,6 +1438,27 @@ ipv4_addr_metric_test()
        fi
        log_test $rc 0 "Prefix route with metric on link up"
 
+       # explicitly check for metric changes on edge scenarios
+       run_cmd "$IP addr flush dev dummy2"
+       run_cmd "$IP addr add dev dummy2 172.16.104.0/24 metric 259"
+       run_cmd "$IP addr change dev dummy2 172.16.104.0/24 metric 260"
+       rc=$?
+       if [ $rc -eq 0 ]; then
+               check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.0 metric 260"
+               rc=$?
+       fi
+       log_test $rc 0 "Modify metric of .0/24 address"
+
+       run_cmd "$IP addr flush dev dummy2"
+       run_cmd "$IP addr add dev dummy2 172.16.104.1/32 peer 172.16.104.2 metric 260"
+       run_cmd "$IP addr change dev dummy2 172.16.104.1/32 peer 172.16.104.2 metric 261"
+       rc=$?
+       if [ $rc -eq 0 ]; then
+               check_route "172.16.104.2 dev dummy2 proto kernel scope link src 172.16.104.1 metric 261"
+               rc=$?
+       fi
+       log_test $rc 0 "Modify metric of address with peer route"
+
        $IP li del dummy1
        $IP li del dummy2
        cleanup
old mode 100644 (file)
new mode 100755 (executable)
index fe3230c5598639f30586142fac2f1eda851c7c3d..fb7a59ed759ebbef223bfe92e85acd33c0b4c597 100644 (file)
@@ -129,7 +129,7 @@ static void test(int *rcv_fds, int count, int proto)
 {
        struct epoll_event ev;
        int epfd, i, test_fd;
-       uint16_t test_family;
+       int test_family;
        socklen_t len;
 
        epfd = epoll_create(1);
@@ -146,6 +146,7 @@ static void test(int *rcv_fds, int count, int proto)
        send_from_v4(proto);
 
        test_fd = receive_once(epfd, proto);
+       len = sizeof(test_family);
        if (getsockopt(test_fd, SOL_SOCKET, SO_DOMAIN, &test_family, &len))
                error(1, errno, "failed to read socket domain");
        if (test_family != AF_INET)
index 4c285b6e1db8c1713b70e6be5092b780bb5e0d6a..1c8f194d655647bd4b308fc6b007893382fe2cde 100644 (file)
@@ -898,6 +898,114 @@ TEST_F(tls, nonblocking)
        }
 }
 
+static void
+test_mutliproc(struct __test_metadata *_metadata, struct _test_data_tls *self,
+              bool sendpg, unsigned int n_readers, unsigned int n_writers)
+{
+       const unsigned int n_children = n_readers + n_writers;
+       const size_t data = 6 * 1000 * 1000;
+       const size_t file_sz = data / 100;
+       size_t read_bias, write_bias;
+       int i, fd, child_id;
+       char buf[file_sz];
+       pid_t pid;
+
+       /* Only allow multiples for simplicity */
+       ASSERT_EQ(!(n_readers % n_writers) || !(n_writers % n_readers), true);
+       read_bias = n_writers / n_readers ?: 1;
+       write_bias = n_readers / n_writers ?: 1;
+
+       /* prep a file to send */
+       fd = open("/tmp/", O_TMPFILE | O_RDWR, 0600);
+       ASSERT_GE(fd, 0);
+
+       memset(buf, 0xac, file_sz);
+       ASSERT_EQ(write(fd, buf, file_sz), file_sz);
+
+       /* spawn children */
+       for (child_id = 0; child_id < n_children; child_id++) {
+               pid = fork();
+               ASSERT_NE(pid, -1);
+               if (!pid)
+                       break;
+       }
+
+       /* parent waits for all children */
+       if (pid) {
+               for (i = 0; i < n_children; i++) {
+                       int status;
+
+                       wait(&status);
+                       EXPECT_EQ(status, 0);
+               }
+
+               return;
+       }
+
+       /* Split threads for reading and writing */
+       if (child_id < n_readers) {
+               size_t left = data * read_bias;
+               char rb[8001];
+
+               while (left) {
+                       int res;
+
+                       res = recv(self->cfd, rb,
+                                  left > sizeof(rb) ? sizeof(rb) : left, 0);
+
+                       EXPECT_GE(res, 0);
+                       left -= res;
+               }
+       } else {
+               size_t left = data * write_bias;
+
+               while (left) {
+                       int res;
+
+                       ASSERT_EQ(lseek(fd, 0, SEEK_SET), 0);
+                       if (sendpg)
+                               res = sendfile(self->fd, fd, NULL,
+                                              left > file_sz ? file_sz : left);
+                       else
+                               res = send(self->fd, buf,
+                                          left > file_sz ? file_sz : left, 0);
+
+                       EXPECT_GE(res, 0);
+                       left -= res;
+               }
+       }
+}
+
+TEST_F(tls, mutliproc_even)
+{
+       test_mutliproc(_metadata, self, false, 6, 6);
+}
+
+TEST_F(tls, mutliproc_readers)
+{
+       test_mutliproc(_metadata, self, false, 4, 12);
+}
+
+TEST_F(tls, mutliproc_writers)
+{
+       test_mutliproc(_metadata, self, false, 10, 2);
+}
+
+TEST_F(tls, mutliproc_sendpage_even)
+{
+       test_mutliproc(_metadata, self, true, 6, 6);
+}
+
+TEST_F(tls, mutliproc_sendpage_readers)
+{
+       test_mutliproc(_metadata, self, true, 4, 12);
+}
+
+TEST_F(tls, mutliproc_sendpage_writers)
+{
+       test_mutliproc(_metadata, self, true, 10, 2);
+}
+
 TEST_F(tls, control_msg)
 {
        if (self->notls)
index cb3fc09645c482a526e2817250469611a5697010..485cf06ef013f0183d695b35099f4409d9c5f6f4 100644 (file)
@@ -71,7 +71,7 @@ int main(int argc, char **argv)
                        flags |= MAP_SHARED;
                        break;
                case 'H':
-                       flags |= MAP_HUGETLB;
+                       flags |= (MAP_HUGETLB | MAP_ANONYMOUS);
                        break;
                default:
                        return -1;
index 051d7d3f443b4f6663d38b5c190f9293ac51f359..927a151fa9aa9e52c5c721f20c34d1682575b17f 100644 (file)
@@ -69,7 +69,7 @@ int read_usb_vudc_device(struct udev_device *sdev, struct usbip_usb_device *dev)
        FILE *fd = NULL;
        struct udev_device *plat;
        const char *speed;
-       int ret = 0;
+       size_t ret;
 
        plat = udev_device_get_parent(sdev);
        path = udev_device_get_syspath(plat);
@@ -79,8 +79,10 @@ int read_usb_vudc_device(struct udev_device *sdev, struct usbip_usb_device *dev)
        if (!fd)
                return -1;
        ret = fread((char *) &descr, sizeof(descr), 1, fd);
-       if (ret < 0)
+       if (ret != 1) {
+               err("Cannot read vudc device descr file: %s", strerror(errno));
                goto err;
+       }
        fclose(fd);
 
        copy_descr_attr(dev, &descr, bDeviceClass);
index 362a01886bab9ef64ca89b61de1ff93ddf26e1bb..8731dfeced8b7ea4f2bb19e19d833330914be2d8 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 #include <linux/perf_event.h>
+#include <linux/perf/arm_pmu.h>
 #include <linux/uaccess.h>
 #include <asm/kvm_emulate.h>
 #include <kvm/arm_pmu.h>
@@ -146,8 +147,7 @@ u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx)
        if (kvm_pmu_pmc_is_chained(pmc) &&
            kvm_pmu_idx_is_high_counter(select_idx))
                counter = upper_32_bits(counter);
-
-       else if (!kvm_pmu_idx_is_64bit(vcpu, select_idx))
+       else if (select_idx != ARMV8_PMU_CYCLE_IDX)
                counter = lower_32_bits(counter);
 
        return counter;
@@ -193,7 +193,7 @@ static void kvm_pmu_release_perf_event(struct kvm_pmc *pmc)
  */
 static void kvm_pmu_stop_counter(struct kvm_vcpu *vcpu, struct kvm_pmc *pmc)
 {
-       u64 counter, reg;
+       u64 counter, reg, val;
 
        pmc = kvm_pmu_get_canonical_pmc(pmc);
        if (!pmc->perf_event)
@@ -201,16 +201,19 @@ static void kvm_pmu_stop_counter(struct kvm_vcpu *vcpu, struct kvm_pmc *pmc)
 
        counter = kvm_pmu_get_pair_counter_value(vcpu, pmc);
 
-       if (kvm_pmu_pmc_is_chained(pmc)) {
-               reg = PMEVCNTR0_EL0 + pmc->idx;
-               __vcpu_sys_reg(vcpu, reg) = lower_32_bits(counter);
-               __vcpu_sys_reg(vcpu, reg + 1) = upper_32_bits(counter);
+       if (pmc->idx == ARMV8_PMU_CYCLE_IDX) {
+               reg = PMCCNTR_EL0;
+               val = counter;
        } else {
-               reg = (pmc->idx == ARMV8_PMU_CYCLE_IDX)
-                      ? PMCCNTR_EL0 : PMEVCNTR0_EL0 + pmc->idx;
-               __vcpu_sys_reg(vcpu, reg) = lower_32_bits(counter);
+               reg = PMEVCNTR0_EL0 + pmc->idx;
+               val = lower_32_bits(counter);
        }
 
+       __vcpu_sys_reg(vcpu, reg) = val;
+
+       if (kvm_pmu_pmc_is_chained(pmc))
+               __vcpu_sys_reg(vcpu, reg + 1) = upper_32_bits(counter);
+
        kvm_pmu_release_perf_event(pmc);
 }
 
@@ -440,8 +443,25 @@ static void kvm_pmu_perf_overflow(struct perf_event *perf_event,
                                  struct pt_regs *regs)
 {
        struct kvm_pmc *pmc = perf_event->overflow_handler_context;
+       struct arm_pmu *cpu_pmu = to_arm_pmu(perf_event->pmu);
        struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc);
        int idx = pmc->idx;
+       u64 period;
+
+       cpu_pmu->pmu.stop(perf_event, PERF_EF_UPDATE);
+
+       /*
+        * Reset the sample period to the architectural limit,
+        * i.e. the point where the counter overflows.
+        */
+       period = -(local64_read(&perf_event->count));
+
+       if (!kvm_pmu_idx_is_64bit(vcpu, pmc->idx))
+               period &= GENMASK(31, 0);
+
+       local64_set(&perf_event->hw.period_left, 0);
+       perf_event->attr.sample_period = period;
+       perf_event->hw.sample_period = period;
 
        __vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(idx);
 
@@ -449,6 +469,8 @@ static void kvm_pmu_perf_overflow(struct perf_event *perf_event,
                kvm_make_request(KVM_REQ_IRQ_PENDING, vcpu);
                kvm_vcpu_kick(vcpu);
        }
+
+       cpu_pmu->pmu.start(perf_event, PERF_EF_RELOAD);
 }
 
 /**
@@ -567,12 +589,12 @@ static void kvm_pmu_create_perf_event(struct kvm_vcpu *vcpu, u64 select_idx)
                 * high counter.
                 */
                attr.sample_period = (-counter) & GENMASK(63, 0);
+               if (kvm_pmu_counter_is_enabled(vcpu, pmc->idx + 1))
+                       attr.config1 |= PERF_ATTR_CFG1_KVM_PMU_CHAINED;
+
                event = perf_event_create_kernel_counter(&attr, -1, current,
                                                         kvm_pmu_perf_overflow,
                                                         pmc + 1);
-
-               if (kvm_pmu_counter_is_enabled(vcpu, pmc->idx + 1))
-                       attr.config1 |= PERF_ATTR_CFG1_KVM_PMU_CHAINED;
        } else {
                /* The initial sample period (overflow count) of an event. */
                if (kvm_pmu_idx_is_64bit(vcpu, pmc->idx))
index fd68fbe0a75d2f24594c2ab0a89ba7923b12e3eb..d6f0696d98efe4738b470e4a92ca24ca33d54d61 100644 (file)
@@ -627,8 +627,9 @@ static int kvm_create_vm_debugfs(struct kvm *kvm, int fd)
 
 static struct kvm *kvm_create_vm(unsigned long type)
 {
-       int r, i;
        struct kvm *kvm = kvm_arch_alloc_vm();
+       int r = -ENOMEM;
+       int i;
 
        if (!kvm)
                return ERR_PTR(-ENOMEM);
@@ -640,44 +641,45 @@ static struct kvm *kvm_create_vm(unsigned long type)
        mutex_init(&kvm->lock);
        mutex_init(&kvm->irq_lock);
        mutex_init(&kvm->slots_lock);
-       refcount_set(&kvm->users_count, 1);
        INIT_LIST_HEAD(&kvm->devices);
 
-       r = kvm_arch_init_vm(kvm, type);
-       if (r)
-               goto out_err_no_disable;
-
-       r = hardware_enable_all();
-       if (r)
-               goto out_err_no_disable;
-
-#ifdef CONFIG_HAVE_KVM_IRQFD
-       INIT_HLIST_HEAD(&kvm->irq_ack_notifier_list);
-#endif
-
        BUILD_BUG_ON(KVM_MEM_SLOTS_NUM > SHRT_MAX);
 
-       r = -ENOMEM;
        for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) {
                struct kvm_memslots *slots = kvm_alloc_memslots();
+
                if (!slots)
-                       goto out_err_no_srcu;
+                       goto out_err_no_arch_destroy_vm;
                /* Generations must be different for each address space. */
                slots->generation = i;
                rcu_assign_pointer(kvm->memslots[i], slots);
        }
 
-       if (init_srcu_struct(&kvm->srcu))
-               goto out_err_no_srcu;
-       if (init_srcu_struct(&kvm->irq_srcu))
-               goto out_err_no_irq_srcu;
        for (i = 0; i < KVM_NR_BUSES; i++) {
                rcu_assign_pointer(kvm->buses[i],
                        kzalloc(sizeof(struct kvm_io_bus), GFP_KERNEL_ACCOUNT));
                if (!kvm->buses[i])
-                       goto out_err;
+                       goto out_err_no_arch_destroy_vm;
        }
 
+       refcount_set(&kvm->users_count, 1);
+       r = kvm_arch_init_vm(kvm, type);
+       if (r)
+               goto out_err_no_arch_destroy_vm;
+
+       r = hardware_enable_all();
+       if (r)
+               goto out_err_no_disable;
+
+#ifdef CONFIG_HAVE_KVM_IRQFD
+       INIT_HLIST_HEAD(&kvm->irq_ack_notifier_list);
+#endif
+
+       if (init_srcu_struct(&kvm->srcu))
+               goto out_err_no_srcu;
+       if (init_srcu_struct(&kvm->irq_srcu))
+               goto out_err_no_irq_srcu;
+
        r = kvm_init_mmu_notifier(kvm);
        if (r)
                goto out_err;
@@ -697,7 +699,9 @@ out_err_no_irq_srcu:
 out_err_no_srcu:
        hardware_disable_all();
 out_err_no_disable:
-       refcount_set(&kvm->users_count, 0);
+       kvm_arch_destroy_vm(kvm);
+       WARN_ON_ONCE(!refcount_dec_and_test(&kvm->users_count));
+out_err_no_arch_destroy_vm:
        for (i = 0; i < KVM_NR_BUSES; i++)
                kfree(kvm_get_bus(kvm, i));
        for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++)
@@ -2360,20 +2364,23 @@ out:
        kvm_arch_vcpu_unblocking(vcpu);
        block_ns = ktime_to_ns(cur) - ktime_to_ns(start);
 
-       if (!vcpu_valid_wakeup(vcpu))
-               shrink_halt_poll_ns(vcpu);
-       else if (halt_poll_ns) {
-               if (block_ns <= vcpu->halt_poll_ns)
-                       ;
-               /* we had a long block, shrink polling */
-               else if (vcpu->halt_poll_ns && block_ns > halt_poll_ns)
+       if (!kvm_arch_no_poll(vcpu)) {
+               if (!vcpu_valid_wakeup(vcpu)) {
                        shrink_halt_poll_ns(vcpu);
-               /* we had a short halt and our poll time is too small */
-               else if (vcpu->halt_poll_ns < halt_poll_ns &&
-                       block_ns < halt_poll_ns)
-                       grow_halt_poll_ns(vcpu);
-       } else
-               vcpu->halt_poll_ns = 0;
+               } else if (halt_poll_ns) {
+                       if (block_ns <= vcpu->halt_poll_ns)
+                               ;
+                       /* we had a long block, shrink polling */
+                       else if (vcpu->halt_poll_ns && block_ns > halt_poll_ns)
+                               shrink_halt_poll_ns(vcpu);
+                       /* we had a short halt and our poll time is too small */
+                       else if (vcpu->halt_poll_ns < halt_poll_ns &&
+                               block_ns < halt_poll_ns)
+                               grow_halt_poll_ns(vcpu);
+               } else {
+                       vcpu->halt_poll_ns = 0;
+               }
+       }
 
        trace_kvm_vcpu_wakeup(block_ns, waited, vcpu_valid_wakeup(vcpu));
        kvm_arch_vcpu_block_finish(vcpu);