Merge 5.14-rc7 into char-misc-next
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 24 Aug 2021 13:24:21 +0000 (15:24 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 24 Aug 2021 13:24:21 +0000 (15:24 +0200)
We need the char/misc fixes in here as well.

Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
488 files changed:
Documentation/bpf/libbpf/libbpf_naming_convention.rst
Documentation/devicetree/bindings/iio/st,st-sensors.yaml
Documentation/devicetree/bindings/riscv/sifive-l2-cache.yaml
Documentation/gpu/rfc/i915_gem_lmem.rst
Documentation/i2c/index.rst
Documentation/networking/nf_conntrack-sysctl.rst
Documentation/userspace-api/seccomp_filter.rst
Documentation/virt/kvm/locking.rst
MAINTAINERS
Makefile
arch/arc/Kconfig
arch/arc/include/asm/checksum.h
arch/arc/include/asm/perf_event.h
arch/arc/kernel/fpu.c
arch/arc/kernel/unwind.c
arch/arc/kernel/vmlinux.lds.S
arch/arm/configs/nhk8815_defconfig
arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
arch/arm64/Makefile
arch/arm64/boot/dts/qcom/msm8992-bullhead-rev-101.dts
arch/arm64/boot/dts/qcom/msm8994-angler-rev-101.dts
arch/arm64/boot/dts/qcom/sc7280.dtsi
arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
arch/arm64/include/asm/el2_setup.h
arch/arm64/kvm/arm.c
arch/arm64/kvm/hyp/nvhe/mem_protect.c
arch/powerpc/include/asm/book3s/32/kup.h
arch/powerpc/include/asm/interrupt.h
arch/powerpc/include/asm/irq.h
arch/powerpc/include/asm/ptrace.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/head_book3s_32.S
arch/powerpc/kernel/head_booke.h
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/kprobes.c
arch/powerpc/kernel/sysfs.c
arch/powerpc/kernel/time.c
arch/powerpc/kernel/traps.c
arch/powerpc/mm/pageattr.c
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/sysdev/xive/common.c
arch/riscv/kernel/Makefile
arch/riscv/kernel/setup.c
arch/riscv/mm/init.c
arch/s390/pci/pci.c
arch/s390/pci/pci_bus.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/svm.h
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/apic/msi.c
arch/x86/kernel/cpu/resctrl/monitor.c
arch/x86/kernel/hpet.c
arch/x86/kvm/cpuid.c
arch/x86/kvm/hyperv.c
arch/x86/kvm/mmu/mmu.c
arch/x86/kvm/mmu/tdp_mmu.c
arch/x86/kvm/svm/nested.c
arch/x86/kvm/svm/svm.c
arch/x86/kvm/vmx/nested.c
arch/x86/kvm/vmx/vmx.h
arch/x86/tools/chkobjdump.awk
block/Kconfig.iosched
block/Makefile
block/blk-cgroup.c
block/blk-core.c
block/blk-flush.c
block/blk-iocost.c
block/blk-mq.c
block/blk.h
block/mq-deadline-cgroup.c [deleted file]
block/mq-deadline-cgroup.h [deleted file]
block/mq-deadline-main.c [deleted file]
block/mq-deadline.c [new file with mode: 0644]
crypto/Kconfig
drivers/acpi/nfit/core.c
drivers/acpi/prmt.c
drivers/acpi/x86/s2idle.c
drivers/base/core.c
drivers/block/nbd.c
drivers/block/virtio_blk.c
drivers/bus/ti-sysc.c
drivers/clk/imx/clk-imx6q.c
drivers/clk/qcom/gdsc.c
drivers/cpufreq/armada-37xx-cpufreq.c
drivers/cpufreq/cpufreq-dt-platdev.c
drivers/cpufreq/scmi-cpufreq.c
drivers/dax/super.c
drivers/firmware/efi/libstub/arm64-stub.c
drivers/firmware/efi/libstub/randomalloc.c
drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h
drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
drivers/gpu/drm/amd/amdkfd/kfd_svm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/core/dc_vm_helper.c
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.h
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c
drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
drivers/gpu/drm/amd/include/atomfirmware.h
drivers/gpu/drm/amd/pm/inc/smu_v13_0_1_pmfw.h
drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
drivers/gpu/drm/drm_ioc32.c
drivers/gpu/drm/i915/display/intel_ddi.c
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/display/intel_display_power.c
drivers/gpu/drm/i915/display/intel_dp_link_training.c
drivers/gpu/drm/i915/gvt/handlers.c
drivers/gpu/drm/i915/gvt/mmio_context.c
drivers/gpu/drm/i915/i915_gpu_error.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/mediatek/mtk_disp_color.c
drivers/gpu/drm/mediatek/mtk_disp_ovl.c
drivers/gpu/drm/mediatek/mtk_dpi.c
drivers/gpu/drm/mediatek/mtk_drm_crtc.c
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
drivers/gpu/drm/mediatek/mtk_drm_plane.c
drivers/gpu/drm/meson/meson_registers.h
drivers/gpu/drm/meson/meson_viu.c
drivers/gpu/drm/nouveau/dispnv50/disp.c
drivers/gpu/drm/nouveau/dispnv50/head.c
drivers/gpu/drm/nouveau/dispnv50/head.h
drivers/gpu/drm/nouveau/include/nvif/cl0080.h
drivers/gpu/drm/nouveau/include/nvif/class.h
drivers/gpu/drm/nouveau/include/nvif/client.h
drivers/gpu/drm/nouveau/include/nvif/driver.h
drivers/gpu/drm/nouveau/include/nvkm/core/client.h
drivers/gpu/drm/nouveau/include/nvkm/core/ioctl.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h
drivers/gpu/drm/nouveau/nouveau_abi16.c
drivers/gpu/drm/nouveau/nouveau_chan.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nouveau_mem.c
drivers/gpu/drm/nouveau/nouveau_nvif.c
drivers/gpu/drm/nouveau/nouveau_svm.c
drivers/gpu/drm/nouveau/nouveau_usif.c
drivers/gpu/drm/nouveau/nvif/client.c
drivers/gpu/drm/nouveau/nvif/object.c
drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
drivers/gpu/drm/nouveau/nvkm/engine/dma/user.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild
drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h
drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c [deleted file]
drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c [deleted file]
drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/umem.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/umem.h
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/ummu.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c
drivers/gpu/drm/ttm/ttm_device.c
drivers/i2c/busses/i2c-bcm-iproc.c
drivers/i2c/i2c-dev.c
drivers/iio/accel/Kconfig
drivers/iio/accel/fxls8962af-core.c
drivers/iio/adc/palmas_gpadc.c
drivers/iio/adc/ti-ads7950.c
drivers/iio/humidity/hdc100x.c
drivers/iio/imu/adis.c
drivers/infiniband/hw/mlx5/cq.c
drivers/infiniband/hw/mlx5/devx.c
drivers/interconnect/qcom/icc-rpmh.c
drivers/iommu/dma-iommu.c
drivers/iommu/intel/pasid.c
drivers/iommu/intel/pasid.h
drivers/iommu/intel/svm.c
drivers/iommu/iommu.c
drivers/ipack/carriers/tpci200.c
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/mmci_stm32_sdmmc.c
drivers/mmc/host/sdhci-iproc.c
drivers/mmc/host/sdhci-msm.c
drivers/mtd/chips/cfi_cmdset_0002.c
drivers/mtd/devices/mchp48l640.c
drivers/mtd/mtd_blkdevs.c
drivers/mtd/mtdcore.c
drivers/mtd/nand/raw/nand_base.c
drivers/net/bareudp.c
drivers/net/can/m_can/m_can.c
drivers/net/dsa/hirschmann/hellcreek.c
drivers/net/dsa/lan9303-core.c
drivers/net/dsa/lantiq_gswip.c
drivers/net/dsa/microchip/ksz8795.c
drivers/net/dsa/microchip/ksz8795_reg.h
drivers/net/dsa/microchip/ksz_common.h
drivers/net/dsa/mt7530.c
drivers/net/dsa/qca/ar9331.c
drivers/net/dsa/sja1105/sja1105_main.c
drivers/net/dsa/sja1105/sja1105_mdio.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h
drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h
drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
drivers/net/ethernet/intel/i40e/i40e_txrx.c
drivers/net/ethernet/intel/iavf/iavf.h
drivers/net/ethernet/intel/iavf/iavf_main.c
drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
drivers/net/ethernet/intel/ice/ice.h
drivers/net/ethernet/intel/ice/ice_main.c
drivers/net/ethernet/intel/ice/ice_ptp.c
drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c
drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c
drivers/net/ethernet/marvell/mvpp2/mvpp2.h
drivers/net/ethernet/marvell/prestera/prestera_switchdev.c
drivers/net/ethernet/mellanox/mlx5/core/cq.c
drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/eq.c
drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c
drivers/net/ethernet/mellanox/mlx5/core/esw/sample.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c
drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
drivers/net/ethernet/microchip/sparx5/sparx5_mactable.c
drivers/net/ethernet/mscc/ocelot.c
drivers/net/ethernet/mscc/ocelot_io.c
drivers/net/ethernet/qlogic/qed/qed_ll2.c
drivers/net/ethernet/qlogic/qed/qed_rdma.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
drivers/net/ethernet/realtek/r8169_main.c
drivers/net/ethernet/rocker/rocker_main.c
drivers/net/ethernet/rocker/rocker_ofdpa.c
drivers/net/ethernet/ti/am65-cpsw-switchdev.c
drivers/net/ethernet/ti/cpsw_new.c
drivers/net/ethernet/ti/cpsw_priv.h
drivers/net/ethernet/ti/cpsw_switchdev.c
drivers/net/hamradio/6pack.c
drivers/net/ieee802154/mac802154_hwsim.c
drivers/net/mdio/mdio-mux.c
drivers/net/pcs/pcs-xpcs.c
drivers/net/phy/micrel.c
drivers/net/ppp/ppp_generic.c
drivers/net/usb/asix_common.c
drivers/net/usb/r8152.c
drivers/net/virtio_net.c
drivers/net/vrf.c
drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
drivers/net/wireless/intel/iwlwifi/pcie/drv.c
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
drivers/net/wireless/mediatek/mt76/mt7921/mcu.h
drivers/net/wwan/iosm/iosm_ipc_chnl_cfg.c
drivers/net/wwan/mhi_wwan_ctrl.c
drivers/net/wwan/wwan_core.c
drivers/nvdimm/namespace_devs.c
drivers/opp/core.c
drivers/opp/of.c
drivers/pci/controller/pci-ixp4xx.c
drivers/pci/msi.c
drivers/pci/pci-sysfs.c
drivers/pci/quirks.c
drivers/pinctrl/intel/pinctrl-tigerlake.c
drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
drivers/pinctrl/pinctrl-amd.c
drivers/pinctrl/pinctrl-k210.c
drivers/pinctrl/qcom/Kconfig
drivers/pinctrl/sunxi/pinctrl-sunxi.c
drivers/platform/x86/Kconfig
drivers/platform/x86/asus-nb-wmi.c
drivers/platform/x86/dual_accel_detect.h [new file with mode: 0644]
drivers/platform/x86/gigabyte-wmi.c
drivers/platform/x86/intel-hid.c
drivers/platform/x86/intel-vbtn.c
drivers/platform/x86/pcengines-apuv2.c
drivers/platform/x86/thinkpad_acpi.c
drivers/ptp/Kconfig
drivers/ptp/ptp_sysfs.c
drivers/s390/net/qeth_l2_main.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/mpt3sas/mpt3sas_base.c
drivers/scsi/storvsc_drv.c
drivers/slimbus/messaging.c
drivers/slimbus/qcom-ngd-ctrl.c
drivers/soc/fsl/qe/qe_ic.c
drivers/usb/dwc3/gadget.c
drivers/usb/typec/tcpm/tcpm.c
drivers/vdpa/ifcvf/ifcvf_main.c
drivers/vdpa/mlx5/core/mr.c
drivers/vdpa/mlx5/net/mlx5_vnet.c
drivers/vdpa/vdpa_sim/vdpa_sim.c
drivers/vdpa/virtio_pci/vp_vdpa.c
drivers/vhost/vdpa.c
drivers/vhost/vhost.c
drivers/vhost/vringh.c
drivers/virtio/virtio.c
drivers/virtio/virtio_pci_common.c
drivers/virtio/virtio_ring.c
drivers/virtio/virtio_vdpa.c
drivers/xen/events/events_base.c
fs/btrfs/inode.c
fs/ceph/caps.c
fs/ceph/mds_client.c
fs/ceph/snap.c
fs/ceph/super.h
fs/cifs/cifsglob.h
fs/cifs/dir.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/misc.c
fs/cifs/smb2pdu.c
fs/configfs/file.c
fs/dax.c
fs/fuse/dax.c
fs/io-wq.c
fs/io_uring.c
fs/namespace.c
fs/notify/fanotify/fanotify_user.c
fs/notify/inotify/inotify_user.c
fs/overlayfs/export.c
fs/overlayfs/file.c
fs/overlayfs/readdir.c
fs/pipe.c
include/asm-generic/vmlinux.lds.h
include/linux/bpf-cgroup.h
include/linux/device.h
include/linux/inetdevice.h
include/linux/irq.h
include/linux/kfence.h
include/linux/memcontrol.h
include/linux/mlx5/driver.h
include/linux/mlx5/mlx5_ifc_vdpa.h
include/linux/msi.h
include/linux/netfilter/ipset/ip_set.h
include/linux/once.h
include/linux/pipe_fs_i.h
include/linux/security.h
include/linux/vdpa.h
include/linux/virtio.h
include/linux/vringh.h
include/net/flow_offload.h
include/net/netns/conntrack.h
include/net/psample.h
include/trace/events/mmflags.h
include/uapi/linux/neighbour.h
include/uapi/linux/netfilter/nfnetlink_hook.h
init/main.c
kernel/bpf/core.c
kernel/bpf/hashtab.c
kernel/bpf/helpers.c
kernel/bpf/verifier.c
kernel/cfi.c
kernel/cgroup/rstat.c
kernel/irq/chip.c
kernel/irq/msi.c
kernel/irq/timings.c
kernel/locking/rtmutex.c
kernel/seccomp.c
kernel/trace/Kconfig
kernel/trace/bpf_trace.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_events_hist.c
kernel/trace/trace_osnoise.c
kernel/ucount.c
lib/devmem_is_allowed.c
lib/once.c
mm/gup.c
mm/hugetlb.c
mm/kmemleak.c
mm/madvise.c
mm/memcontrol.c
mm/memory-failure.c
mm/page_alloc.c
mm/shmem.c
mm/slub.c
mm/swap_state.c
mm/vmscan.c
net/bpf/test_run.c
net/bridge/br.c
net/bridge/br_fdb.c
net/bridge/br_if.c
net/bridge/br_private.h
net/bridge/netfilter/nf_conntrack_bridge.c
net/core/link_watch.c
net/core/page_pool.c
net/dccp/dccp.h
net/dsa/slave.c
net/ieee802154/socket.c
net/ipv4/igmp.c
net/ipv4/tcp_bbr.c
net/mac80211/main.c
net/mptcp/options.c
net/mptcp/pm_netlink.c
net/netfilter/ipset/ip_set_hash_ip.c
net/netfilter/ipset/ip_set_hash_ipmark.c
net/netfilter/ipset/ip_set_hash_ipport.c
net/netfilter/ipset/ip_set_hash_ipportip.c
net/netfilter/ipset/ip_set_hash_ipportnet.c
net/netfilter/ipset/ip_set_hash_net.c
net/netfilter/ipset/ip_set_hash_netiface.c
net/netfilter/ipset/ip_set_hash_netnet.c
net/netfilter/ipset/ip_set_hash_netport.c
net/netfilter/ipset/ip_set_hash_netportnet.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_proto_tcp.c
net/netfilter/nf_conntrack_proto_udp.c
net/netfilter/nf_conntrack_standalone.c
net/netfilter/nf_flow_table_core.c
net/netfilter/nfnetlink_hook.c
net/openvswitch/flow.c
net/openvswitch/vport.c
net/rds/ib_frmr.c
net/sched/act_mirred.c
net/sched/sch_cake.c
net/smc/af_smc.c
net/smc/smc_core.c
net/smc/smc_core.h
net/smc/smc_llc.c
net/smc/smc_tx.c
net/smc/smc_wr.c
net/tipc/link.c
net/tipc/socket.c
net/vmw_vsock/virtio_transport.c
security/security.c
sound/core/pcm_native.c
sound/firewire/oxfw/oxfw-stream.c
sound/firewire/oxfw/oxfw.c
sound/firewire/oxfw/oxfw.h
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_via.c
sound/soc/Kconfig
sound/soc/amd/acp-da7219-max98357a.c
sound/soc/amd/acp-pcm-dma.c
sound/soc/amd/raven/acp3x-pcm-dma.c
sound/soc/amd/renoir/acp3x-pdm-dma.c
sound/soc/amd/renoir/rn-pci-acp3x.c
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/cs42l42.c
sound/soc/codecs/cs42l42.h
sound/soc/codecs/nau8824.c
sound/soc/codecs/rt5682.c
sound/soc/codecs/tlv320aic31xx.c
sound/soc/codecs/tlv320aic32x4.c
sound/soc/codecs/wm_adsp.c
sound/soc/intel/atom/sst-mfld-platform-pcm.c
sound/soc/intel/boards/sof_da7219_max98373.c
sound/soc/kirkwood/kirkwood-dma.c
sound/soc/soc-component.c
sound/soc/sof/intel/Kconfig
sound/soc/sof/intel/hda-ipc.c
sound/soc/sof/intel/hda.c
sound/soc/uniphier/aio-dma.c
sound/soc/xilinx/xlnx_formatter_pcm.c
tools/io_uring/io_uring-cp.c
tools/lib/bpf/btf.c
tools/lib/bpf/libbpf_probes.c
tools/testing/nvdimm/test/nfit.c
tools/testing/selftests/bpf/verifier/dead_code.c
tools/testing/selftests/sgx/sigstruct.c
tools/virtio/Makefile
tools/virtio/linux/spinlock.h [new file with mode: 0644]
tools/virtio/linux/virtio.h

index 3de1d51..6bf9c5a 100644 (file)
@@ -108,7 +108,7 @@ This bump in ABI version is at most once per kernel development cycle.
 
 For example, if current state of ``libbpf.map`` is:
 
-.. code-block:: c
+.. code-block:: none
 
         LIBBPF_0.0.1 {
                global:
@@ -121,7 +121,7 @@ For example, if current state of ``libbpf.map`` is:
 , and a new symbol ``bpf_func_c`` is being introduced, then
 ``libbpf.map`` should be changed like this:
 
-.. code-block:: c
+.. code-block:: none
 
         LIBBPF_0.0.1 {
                global:
index b2a1e42..71de563 100644 (file)
@@ -152,47 +152,6 @@ allOf:
           maxItems: 1
         st,drdy-int-pin: false
 
-  - if:
-      properties:
-        compatible:
-          enum:
-            # Two intertial interrupts i.e. accelerometer/gyro interrupts
-            - st,h3lis331dl-accel
-            - st,l3g4200d-gyro
-            - st,l3g4is-gyro
-            - st,l3gd20-gyro
-            - st,l3gd20h-gyro
-            - st,lis2de12
-            - st,lis2dw12
-            - st,lis2hh12
-            - st,lis2dh12-accel
-            - st,lis331dl-accel
-            - st,lis331dlh-accel
-            - st,lis3de
-            - st,lis3dh-accel
-            - st,lis3dhh
-            - st,lis3mdl-magn
-            - st,lng2dm-accel
-            - st,lps331ap-press
-            - st,lsm303agr-accel
-            - st,lsm303dlh-accel
-            - st,lsm303dlhc-accel
-            - st,lsm303dlm-accel
-            - st,lsm330-accel
-            - st,lsm330-gyro
-            - st,lsm330d-accel
-            - st,lsm330d-gyro
-            - st,lsm330dl-accel
-            - st,lsm330dl-gyro
-            - st,lsm330dlc-accel
-            - st,lsm330dlc-gyro
-            - st,lsm9ds0-gyro
-            - st,lsm9ds1-magn
-    then:
-      properties:
-        interrupts:
-          maxItems: 2
-
 required:
   - compatible
   - reg
index 1d38ff7..2b1f916 100644 (file)
@@ -24,10 +24,10 @@ allOf:
 select:
   properties:
     compatible:
-      items:
-        enum:
-            - sifive,fu540-c000-ccache
-            - sifive,fu740-c000-ccache
+      contains:
+        enum:
+          - sifive,fu540-c000-ccache
+          - sifive,fu740-c000-ccache
 
   required:
     - compatible
index 675ba86..b421a3c 100644 (file)
@@ -18,114 +18,5 @@ real, with all the uAPI bits is:
         * Route shmem backend over to TTM SYSTEM for discrete
         * TTM purgeable object support
         * Move i915 buddy allocator over to TTM
-        * MMAP ioctl mode(see `I915 MMAP`_)
-        * SET/GET ioctl caching(see `I915 SET/GET CACHING`_)
 * Send RFC(with mesa-dev on cc) for final sign off on the uAPI
 * Add pciid for DG1 and turn on uAPI for real
-
-New object placement and region query uAPI
-==========================================
-Starting from DG1 we need to give userspace the ability to allocate buffers from
-device local-memory. Currently the driver supports gem_create, which can place
-buffers in system memory via shmem, and the usual assortment of other
-interfaces, like dumb buffers and userptr.
-
-To support this new capability, while also providing a uAPI which will work
-beyond just DG1, we propose to offer three new bits of uAPI:
-
-DRM_I915_QUERY_MEMORY_REGIONS
------------------------------
-New query ID which allows userspace to discover the list of supported memory
-regions(like system-memory and local-memory) for a given device. We identify
-each region with a class and instance pair, which should be unique. The class
-here would be DEVICE or SYSTEM, and the instance would be zero, on platforms
-like DG1.
-
-Side note: The class/instance design is borrowed from our existing engine uAPI,
-where we describe every physical engine in terms of its class, and the
-particular instance, since we can have more than one per class.
-
-In the future we also want to expose more information which can further
-describe the capabilities of a region.
-
-.. kernel-doc:: include/uapi/drm/i915_drm.h
-        :functions: drm_i915_gem_memory_class drm_i915_gem_memory_class_instance drm_i915_memory_region_info drm_i915_query_memory_regions
-
-GEM_CREATE_EXT
---------------
-New ioctl which is basically just gem_create but now allows userspace to provide
-a chain of possible extensions. Note that if we don't provide any extensions and
-set flags=0 then we get the exact same behaviour as gem_create.
-
-Side note: We also need to support PXP[1] in the near future, which is also
-applicable to integrated platforms, and adds its own gem_create_ext extension,
-which basically lets userspace mark a buffer as "protected".
-
-.. kernel-doc:: include/uapi/drm/i915_drm.h
-        :functions: drm_i915_gem_create_ext
-
-I915_GEM_CREATE_EXT_MEMORY_REGIONS
-----------------------------------
-Implemented as an extension for gem_create_ext, we would now allow userspace to
-optionally provide an immutable list of preferred placements at creation time,
-in priority order, for a given buffer object.  For the placements we expect
-them each to use the class/instance encoding, as per the output of the regions
-query. Having the list in priority order will be useful in the future when
-placing an object, say during eviction.
-
-.. kernel-doc:: include/uapi/drm/i915_drm.h
-        :functions: drm_i915_gem_create_ext_memory_regions
-
-One fair criticism here is that this seems a little over-engineered[2]. If we
-just consider DG1 then yes, a simple gem_create.flags or something is totally
-all that's needed to tell the kernel to allocate the buffer in local-memory or
-whatever. However looking to the future we need uAPI which can also support
-upcoming Xe HP multi-tile architecture in a sane way, where there can be
-multiple local-memory instances for a given device, and so using both class and
-instance in our uAPI to describe regions is desirable, although specifically
-for DG1 it's uninteresting, since we only have a single local-memory instance.
-
-Existing uAPI issues
-====================
-Some potential issues we still need to resolve.
-
-I915 MMAP
----------
-In i915 there are multiple ways to MMAP GEM object, including mapping the same
-object using different mapping types(WC vs WB), i.e multiple active mmaps per
-object. TTM expects one MMAP at most for the lifetime of the object. If it
-turns out that we have to backpedal here, there might be some potential
-userspace fallout.
-
-I915 SET/GET CACHING
---------------------
-In i915 we have set/get_caching ioctl. TTM doesn't let us to change this, but
-DG1 doesn't support non-snooped pcie transactions, so we can just always
-allocate as WB for smem-only buffers.  If/when our hw gains support for
-non-snooped pcie transactions then we must fix this mode at allocation time as
-a new GEM extension.
-
-This is related to the mmap problem, because in general (meaning, when we're
-not running on intel cpus) the cpu mmap must not, ever, be inconsistent with
-allocation mode.
-
-Possible idea is to let the kernel picks the mmap mode for userspace from the
-following table:
-
-smem-only: WB. Userspace does not need to call clflush.
-
-smem+lmem: We only ever allow a single mode, so simply allocate this as uncached
-memory, and always give userspace a WC mapping. GPU still does snooped access
-here(assuming we can't turn it off like on DG1), which is a bit inefficient.
-
-lmem only: always WC
-
-This means on discrete you only get a single mmap mode, all others must be
-rejected. That's probably going to be a new default mode or something like
-that.
-
-Links
-=====
-[1] https://patchwork.freedesktop.org/series/86798/
-
-[2] https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5599#note_553791
index 8b76217..6270f1f 100644 (file)
@@ -17,6 +17,7 @@ Introduction
    busses/index
    i2c-topology
    muxes/i2c-mux-gpio
+   i2c-sysfs
 
 Writing device drivers
 ======================
index d31ed6c..024d784 100644 (file)
@@ -191,19 +191,9 @@ nf_flowtable_tcp_timeout - INTEGER (seconds)
         TCP connections may be offloaded from nf conntrack to nf flow table.
         Once aged, the connection is returned to nf conntrack with tcp pickup timeout.
 
-nf_flowtable_tcp_pickup - INTEGER (seconds)
-        default 120
-
-        TCP connection timeout after being aged from nf flow table offload.
-
 nf_flowtable_udp_timeout - INTEGER (seconds)
         default 30
 
         Control offload timeout for udp connections.
         UDP connections may be offloaded from nf conntrack to nf flow table.
         Once aged, the connection is returned to nf conntrack with udp pickup timeout.
-
-nf_flowtable_udp_pickup - INTEGER (seconds)
-        default 30
-
-        UDP connection timeout after being aged from nf flow table offload.
index d612198..539e9d4 100644 (file)
@@ -263,7 +263,7 @@ Userspace can also add file descriptors to the notifying process via
 ``ioctl(SECCOMP_IOCTL_NOTIF_ADDFD)``. The ``id`` member of
 ``struct seccomp_notif_addfd`` should be the same ``id`` as in
 ``struct seccomp_notif``. The ``newfd_flags`` flag may be used to set flags
-like O_EXEC on the file descriptor in the notifying process. If the supervisor
+like O_CLOEXEC on the file descriptor in the notifying process. If the supervisor
 wants to inject the file descriptor with a specific number, the
 ``SECCOMP_ADDFD_FLAG_SETFD`` flag can be used, and set the ``newfd`` member to
 the specific number to use. If that file descriptor is already open in the
index 35eca37..88fa495 100644 (file)
@@ -25,10 +25,10 @@ On x86:
 
 - vcpu->mutex is taken outside kvm->arch.hyperv.hv_lock
 
-- kvm->arch.mmu_lock is an rwlock.  kvm->arch.tdp_mmu_pages_lock is
-  taken inside kvm->arch.mmu_lock, and cannot be taken without already
-  holding kvm->arch.mmu_lock (typically with ``read_lock``, otherwise
-  there's no need to take kvm->arch.tdp_mmu_pages_lock at all).
+- kvm->arch.mmu_lock is an rwlock.  kvm->arch.tdp_mmu_pages_lock and
+  kvm->arch.mmu_unsync_pages_lock are taken inside kvm->arch.mmu_lock, and
+  cannot be taken without already holding kvm->arch.mmu_lock (typically with
+  ``read_lock`` for the TDP MMU, thus the need for additional spinlocks).
 
 Everything else is a leaf: no other lock is taken inside the critical
 sections.
index c9467d2..c6b8a72 100644 (file)
@@ -3866,6 +3866,16 @@ L:       bcm-kernel-feedback-list@broadcom.com
 S:     Maintained
 F:     drivers/mtd/nand/raw/brcmnand/
 
+BROADCOM STB PCIE DRIVER
+M:     Jim Quinlan <jim2101024@gmail.com>
+M:     Nicolas Saenz Julienne <nsaenz@kernel.org>
+M:     Florian Fainelli <f.fainelli@gmail.com>
+M:     bcm-kernel-feedback-list@broadcom.com
+L:     linux-pci@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml
+F:     drivers/pci/controller/pcie-brcmstb.c
+
 BROADCOM SYSTEMPORT ETHERNET DRIVER
 M:     Florian Fainelli <f.fainelli@gmail.com>
 L:     bcm-kernel-feedback-list@broadcom.com
@@ -4498,7 +4508,7 @@ L:        clang-built-linux@googlegroups.com
 S:     Supported
 W:     https://clangbuiltlinux.github.io/
 B:     https://github.com/ClangBuiltLinux/linux/issues
-C:     irc://chat.freenode.net/clangbuiltlinux
+C:     irc://irc.libera.chat/clangbuiltlinux
 F:     Documentation/kbuild/llvm.rst
 F:     include/linux/compiler-clang.h
 F:     scripts/clang-tools/
@@ -11327,7 +11337,7 @@ W:      https://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
 F:     drivers/media/radio/radio-maxiradio*
 
-MCAB MICROCHIP CAN BUS ANALYZER TOOL DRIVER
+MCBA MICROCHIP CAN BUS ANALYZER TOOL DRIVER
 R:     Yasushi SHOJI <yashi@spacecubics.com>
 L:     linux-can@vger.kernel.org
 S:     Maintained
@@ -14430,6 +14440,13 @@ S:     Maintained
 F:     Documentation/devicetree/bindings/pci/hisilicon-histb-pcie.txt
 F:     drivers/pci/controller/dwc/pcie-histb.c
 
+PCIE DRIVER FOR INTEL LGM GW SOC
+M:     Rahul Tanwar <rtanwar@maxlinear.com>
+L:     linux-pci@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/pci/intel-gw-pcie.yaml
+F:     drivers/pci/controller/dwc/pcie-intel-gw.c
+
 PCIE DRIVER FOR MEDIATEK
 M:     Ryder Lee <ryder.lee@mediatek.com>
 M:     Jianjun Wang <jianjun.wang@mediatek.com>
@@ -15803,7 +15820,7 @@ F:      Documentation/devicetree/bindings/i2c/renesas,iic-emev2.yaml
 F:     drivers/i2c/busses/i2c-emev2.c
 
 RENESAS ETHERNET DRIVERS
-R:     Sergei Shtylyov <sergei.shtylyov@gmail.com>
+R:     Sergey Shtylyov <s.shtylyov@omp.ru>
 L:     netdev@vger.kernel.org
 L:     linux-renesas-soc@vger.kernel.org
 F:     Documentation/devicetree/bindings/net/renesas,*.yaml
@@ -17815,7 +17832,7 @@ F:      include/linux/sync_file.h
 F:     include/uapi/linux/sync_file.h
 
 SYNOPSYS ARC ARCHITECTURE
-M:     Vineet Gupta <vgupta@synopsys.com>
+M:     Vineet Gupta <vgupta@kernel.org>
 L:     linux-snps-arc@lists.infradead.org
 S:     Supported
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc.git
@@ -20017,7 +20034,8 @@ F:      Documentation/devicetree/bindings/extcon/wlf,arizona.yaml
 F:     Documentation/devicetree/bindings/mfd/wlf,arizona.yaml
 F:     Documentation/devicetree/bindings/mfd/wm831x.txt
 F:     Documentation/devicetree/bindings/regulator/wlf,arizona.yaml
-F:     Documentation/devicetree/bindings/sound/wlf,arizona.yaml
+F:     Documentation/devicetree/bindings/sound/wlf,*.yaml
+F:     Documentation/devicetree/bindings/sound/wm*
 F:     Documentation/hwmon/wm83??.rst
 F:     arch/arm/mach-s3c/mach-crag6410*
 F:     drivers/clk/clk-wm83*.c
index eae1314..80aa851 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 14
 SUBLEVEL = 0
-EXTRAVERSION = -rc5
+EXTRAVERSION = -rc7
 NAME = Opossums on Parade
 
 # *DOCUMENTATION*
index d8f51eb..b5bf68e 100644 (file)
@@ -409,7 +409,7 @@ choice
        help
          Depending on the configuration, CPU can contain DSP registers
          (ACC0_GLO, ACC0_GHI, DSP_BFLY0, DSP_CTRL, DSP_FFT_CTRL).
-         Bellow is options describing how to handle these registers in
+         Below are options describing how to handle these registers in
          interrupt entry / exit and in context switch.
 
 config ARC_DSP_NONE
index 69debd7..0b48580 100644 (file)
@@ -24,7 +24,7 @@
  */
 static inline __sum16 csum_fold(__wsum s)
 {
-       unsigned r = s << 16 | s >> 16; /* ror */
+       unsigned int r = s << 16 | s >> 16;     /* ror */
        s = ~s;
        s -= r;
        return s >> 16;
index 30b9ae5..e1971d3 100644 (file)
@@ -123,7 +123,7 @@ static const char * const arc_pmu_ev_hw_map[] = {
 #define C(_x)                  PERF_COUNT_HW_CACHE_##_x
 #define CACHE_OP_UNSUPPORTED   0xffff
 
-static const unsigned arc_pmu_cache_map[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
+static const unsigned int arc_pmu_cache_map[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
        [C(L1D)] = {
                [C(OP_READ)] = {
                        [C(RESULT_ACCESS)]      = PERF_COUNT_ARC_LDC,
index c67c0f0..ec64021 100644 (file)
@@ -57,23 +57,26 @@ void fpu_save_restore(struct task_struct *prev, struct task_struct *next)
 
 void fpu_init_task(struct pt_regs *regs)
 {
+       const unsigned int fwe = 0x80000000;
+
        /* default rounding mode */
        write_aux_reg(ARC_REG_FPU_CTRL, 0x100);
 
-       /* set "Write enable" to allow explicit write to exception flags */
-       write_aux_reg(ARC_REG_FPU_STATUS, 0x80000000);
+       /* Initialize to zero: setting requires FWE be set */
+       write_aux_reg(ARC_REG_FPU_STATUS, fwe);
 }
 
 void fpu_save_restore(struct task_struct *prev, struct task_struct *next)
 {
        struct arc_fpu *save = &prev->thread.fpu;
        struct arc_fpu *restore = &next->thread.fpu;
+       const unsigned int fwe = 0x80000000;
 
        save->ctrl = read_aux_reg(ARC_REG_FPU_CTRL);
        save->status = read_aux_reg(ARC_REG_FPU_STATUS);
 
        write_aux_reg(ARC_REG_FPU_CTRL, restore->ctrl);
-       write_aux_reg(ARC_REG_FPU_STATUS, restore->status);
+       write_aux_reg(ARC_REG_FPU_STATUS, (fwe | restore->status));
 }
 
 #endif
index 47bab67..9e28058 100644 (file)
@@ -260,7 +260,7 @@ static void init_unwind_hdr(struct unwind_table *table,
 {
        const u8 *ptr;
        unsigned long tableSize = table->size, hdrSize;
-       unsigned n;
+       unsigned int n;
        const u32 *fde;
        struct {
                u8 version;
@@ -462,7 +462,7 @@ static uleb128_t get_uleb128(const u8 **pcur, const u8 *end)
 {
        const u8 *cur = *pcur;
        uleb128_t value;
-       unsigned shift;
+       unsigned int shift;
 
        for (shift = 0, value = 0; cur < end; shift += 7) {
                if (shift + 7 > 8 * sizeof(value)
@@ -483,7 +483,7 @@ static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
 {
        const u8 *cur = *pcur;
        sleb128_t value;
-       unsigned shift;
+       unsigned int shift;
 
        for (shift = 0, value = 0; cur < end; shift += 7) {
                if (shift + 7 > 8 * sizeof(value)
@@ -609,7 +609,7 @@ static unsigned long read_pointer(const u8 **pLoc, const void *end,
 static signed fde_pointer_type(const u32 *cie)
 {
        const u8 *ptr = (const u8 *)(cie + 2);
-       unsigned version = *ptr;
+       unsigned int version = *ptr;
 
        if (*++ptr) {
                const char *aug;
@@ -904,7 +904,7 @@ int arc_unwind(struct unwind_frame_info *frame)
        const u8 *ptr = NULL, *end = NULL;
        unsigned long pc = UNW_PC(frame) - frame->call_frame;
        unsigned long startLoc = 0, endLoc = 0, cfa;
-       unsigned i;
+       unsigned int i;
        signed ptrType = -1;
        uleb128_t retAddrReg = 0;
        const struct unwind_table *table;
index e2146a8..529ae50 100644 (file)
@@ -88,6 +88,8 @@ SECTIONS
                CPUIDLE_TEXT
                LOCK_TEXT
                KPROBES_TEXT
+               IRQENTRY_TEXT
+               SOFTIRQENTRY_TEXT
                *(.fixup)
                *(.gnu.warning)
        }
index 3f35761..23595fc 100644 (file)
@@ -15,8 +15,6 @@ CONFIG_SLAB=y
 CONFIG_ARCH_NOMADIK=y
 CONFIG_MACH_NOMADIK_8815NHK=y
 CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
@@ -52,9 +50,9 @@ CONFIG_MTD_BLOCK=y
 CONFIG_MTD_ONENAND=y
 CONFIG_MTD_ONENAND_VERIFY_WRITE=y
 CONFIG_MTD_ONENAND_GENERIC=y
-CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC=y
 CONFIG_MTD_RAW_NAND=y
 CONFIG_MTD_NAND_FSMC=y
+CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=y
 CONFIG_BLK_DEV_RAM=y
@@ -97,6 +95,7 @@ CONFIG_REGULATOR=y
 CONFIG_DRM=y
 CONFIG_DRM_PANEL_TPO_TPG110=y
 CONFIG_DRM_PL111=y
+CONFIG_FB=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
 CONFIG_BACKLIGHT_PWM=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
@@ -136,9 +135,8 @@ CONFIG_NLS_ISO8859_15=y
 CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=y
 CONFIG_CRYPTO_DES=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_DEBUG_PREEMPT is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
index abb07f1..74e63d4 100644 (file)
 /*
  * PCI Control/Status Registers
  */
-#define IXP4XX_PCI_CSR(x) ((volatile u32 *)(IXP4XX_PCI_CFG_BASE_VIRT+(x)))
-
-#define PCI_NP_AD               IXP4XX_PCI_CSR(PCI_NP_AD_OFFSET)
-#define PCI_NP_CBE              IXP4XX_PCI_CSR(PCI_NP_CBE_OFFSET)
-#define PCI_NP_WDATA            IXP4XX_PCI_CSR(PCI_NP_WDATA_OFFSET)
-#define PCI_NP_RDATA            IXP4XX_PCI_CSR(PCI_NP_RDATA_OFFSET)
-#define PCI_CRP_AD_CBE          IXP4XX_PCI_CSR(PCI_CRP_AD_CBE_OFFSET)
-#define PCI_CRP_WDATA           IXP4XX_PCI_CSR(PCI_CRP_WDATA_OFFSET)
-#define PCI_CRP_RDATA           IXP4XX_PCI_CSR(PCI_CRP_RDATA_OFFSET)
-#define PCI_CSR                 IXP4XX_PCI_CSR(PCI_CSR_OFFSET) 
-#define PCI_ISR                 IXP4XX_PCI_CSR(PCI_ISR_OFFSET)
-#define PCI_INTEN               IXP4XX_PCI_CSR(PCI_INTEN_OFFSET)
-#define PCI_DMACTRL             IXP4XX_PCI_CSR(PCI_DMACTRL_OFFSET)
-#define PCI_AHBMEMBASE          IXP4XX_PCI_CSR(PCI_AHBMEMBASE_OFFSET)
-#define PCI_AHBIOBASE           IXP4XX_PCI_CSR(PCI_AHBIOBASE_OFFSET)
-#define PCI_PCIMEMBASE          IXP4XX_PCI_CSR(PCI_PCIMEMBASE_OFFSET)
-#define PCI_AHBDOORBELL         IXP4XX_PCI_CSR(PCI_AHBDOORBELL_OFFSET)
-#define PCI_PCIDOORBELL         IXP4XX_PCI_CSR(PCI_PCIDOORBELL_OFFSET)
-#define PCI_ATPDMA0_AHBADDR     IXP4XX_PCI_CSR(PCI_ATPDMA0_AHBADDR_OFFSET)
-#define PCI_ATPDMA0_PCIADDR     IXP4XX_PCI_CSR(PCI_ATPDMA0_PCIADDR_OFFSET)
-#define PCI_ATPDMA0_LENADDR     IXP4XX_PCI_CSR(PCI_ATPDMA0_LENADDR_OFFSET)
-#define PCI_ATPDMA1_AHBADDR     IXP4XX_PCI_CSR(PCI_ATPDMA1_AHBADDR_OFFSET)
-#define PCI_ATPDMA1_PCIADDR     IXP4XX_PCI_CSR(PCI_ATPDMA1_PCIADDR_OFFSET)
-#define PCI_ATPDMA1_LENADDR     IXP4XX_PCI_CSR(PCI_ATPDMA1_LENADDR_OFFSET)
+#define _IXP4XX_PCI_CSR(x) ((volatile u32 *)(IXP4XX_PCI_CFG_BASE_VIRT+(x)))
+
+#define PCI_NP_AD               _IXP4XX_PCI_CSR(PCI_NP_AD_OFFSET)
+#define PCI_NP_CBE              _IXP4XX_PCI_CSR(PCI_NP_CBE_OFFSET)
+#define PCI_NP_WDATA            _IXP4XX_PCI_CSR(PCI_NP_WDATA_OFFSET)
+#define PCI_NP_RDATA            _IXP4XX_PCI_CSR(PCI_NP_RDATA_OFFSET)
+#define PCI_CRP_AD_CBE          _IXP4XX_PCI_CSR(PCI_CRP_AD_CBE_OFFSET)
+#define PCI_CRP_WDATA           _IXP4XX_PCI_CSR(PCI_CRP_WDATA_OFFSET)
+#define PCI_CRP_RDATA           _IXP4XX_PCI_CSR(PCI_CRP_RDATA_OFFSET)
+#define PCI_CSR                 _IXP4XX_PCI_CSR(PCI_CSR_OFFSET) 
+#define PCI_ISR                 _IXP4XX_PCI_CSR(PCI_ISR_OFFSET)
+#define PCI_INTEN               _IXP4XX_PCI_CSR(PCI_INTEN_OFFSET)
+#define PCI_DMACTRL             _IXP4XX_PCI_CSR(PCI_DMACTRL_OFFSET)
+#define PCI_AHBMEMBASE          _IXP4XX_PCI_CSR(PCI_AHBMEMBASE_OFFSET)
+#define PCI_AHBIOBASE           _IXP4XX_PCI_CSR(PCI_AHBIOBASE_OFFSET)
+#define PCI_PCIMEMBASE          _IXP4XX_PCI_CSR(PCI_PCIMEMBASE_OFFSET)
+#define PCI_AHBDOORBELL         _IXP4XX_PCI_CSR(PCI_AHBDOORBELL_OFFSET)
+#define PCI_PCIDOORBELL         _IXP4XX_PCI_CSR(PCI_PCIDOORBELL_OFFSET)
+#define PCI_ATPDMA0_AHBADDR     _IXP4XX_PCI_CSR(PCI_ATPDMA0_AHBADDR_OFFSET)
+#define PCI_ATPDMA0_PCIADDR     _IXP4XX_PCI_CSR(PCI_ATPDMA0_PCIADDR_OFFSET)
+#define PCI_ATPDMA0_LENADDR     _IXP4XX_PCI_CSR(PCI_ATPDMA0_LENADDR_OFFSET)
+#define PCI_ATPDMA1_AHBADDR     _IXP4XX_PCI_CSR(PCI_ATPDMA1_AHBADDR_OFFSET)
+#define PCI_ATPDMA1_PCIADDR     _IXP4XX_PCI_CSR(PCI_ATPDMA1_PCIADDR_OFFSET)
+#define PCI_ATPDMA1_LENADDR     _IXP4XX_PCI_CSR(PCI_ATPDMA1_LENADDR_OFFSET)
 
 /*
  * PCI register values and bit definitions 
index 7b668db..1110d38 100644 (file)
@@ -183,6 +183,8 @@ endif
 # We use MRPROPER_FILES and CLEAN_FILES now
 archclean:
        $(Q)$(MAKE) $(clean)=$(boot)
+       $(Q)$(MAKE) $(clean)=arch/arm64/kernel/vdso
+       $(Q)$(MAKE) $(clean)=arch/arm64/kernel/vdso32
 
 ifeq ($(KBUILD_EXTMOD),)
 # We need to generate vdso-offsets.h before compiling certain files in kernel/.
index 23cdcc9..1ccca83 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /* Copyright (c) 2015, LGE Inc. All rights reserved.
  * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2021, Petr Vorel <petr.vorel@gmail.com>
  */
 
 /dts-v1/;
@@ -9,6 +10,9 @@
 #include "pm8994.dtsi"
 #include "pmi8994.dtsi"
 
+/* cont_splash_mem has different memory mapping */
+/delete-node/ &cont_splash_mem;
+
 / {
        model = "LG Nexus 5X";
        compatible = "lg,bullhead", "qcom,msm8992";
@@ -17,6 +21,9 @@
        qcom,board-id = <0xb64 0>;
        qcom,pmic-id = <0x10009 0x1000A 0x0 0x0>;
 
+       /* Bullhead firmware doesn't support PSCI */
+       /delete-node/ psci;
+
        aliases {
                serial0 = &blsp1_uart2;
        };
                        ftrace-size = <0x10000>;
                        pmsg-size = <0x20000>;
                };
+
+               cont_splash_mem: memory@3400000 {
+                       reg = <0 0x03400000 0 0x1200000>;
+                       no-map;
+               };
        };
 };
 
index ffe1a9b..c096b77 100644 (file)
@@ -1,12 +1,16 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /* Copyright (c) 2015, Huawei Inc. All rights reserved.
  * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2021, Petr Vorel <petr.vorel@gmail.com>
  */
 
 /dts-v1/;
 
 #include "msm8994.dtsi"
 
+/* Angler's firmware does not report where the memory is allocated */
+/delete-node/ &cont_splash_mem;
+
 / {
        model = "Huawei Nexus 6P";
        compatible = "huawei,angler", "qcom,msm8994";
index a8c274a..188c576 100644 (file)
                                           &BIG_CPU_SLEEP_1
                                           &CLUSTER_SLEEP_0>;
                        next-level-cache = <&L2_700>;
-                       qcom,freq-domain = <&cpufreq_hw 1>;
+                       qcom,freq-domain = <&cpufreq_hw 2>;
                        #cooling-cells = <2>;
                        L2_700: l2-cache {
                                compatible = "cache";
index 4d052e3..eb6b1d1 100644 (file)
@@ -69,7 +69,7 @@
                };
                rmtfs_upper_guard: memory@f5d01000 {
                        no-map;
-                       reg = <0 0xf5d01000 0 0x2000>;
+                       reg = <0 0xf5d01000 0 0x1000>;
                };
 
                /*
@@ -78,7 +78,7 @@
                 */
                removed_region: memory@88f00000 {
                        no-map;
-                       reg = <0 0x88f00000 0 0x200000>;
+                       reg = <0 0x88f00000 0 0x1c00000>;
                };
 
                ramoops: ramoops@ac300000 {
index c2a709a..d7591a4 100644 (file)
                left_spkr: wsa8810-left{
                        compatible = "sdw10217211000";
                        reg = <0 3>;
-                       powerdown-gpios = <&wcdgpio 2 GPIO_ACTIVE_HIGH>;
+                       powerdown-gpios = <&wcdgpio 1 GPIO_ACTIVE_HIGH>;
                        #thermal-sensor-cells = <0>;
                        sound-name-prefix = "SpkrLeft";
                        #sound-dai-cells = <0>;
 
                right_spkr: wsa8810-right{
                        compatible = "sdw10217211000";
-                       powerdown-gpios = <&wcdgpio 3 GPIO_ACTIVE_HIGH>;
+                       powerdown-gpios = <&wcdgpio 2 GPIO_ACTIVE_HIGH>;
                        reg = <0 4>;
                        #thermal-sensor-cells = <0>;
                        sound-name-prefix = "SpkrRight";
index 21fa330..b83fb24 100644 (file)
@@ -33,8 +33,7 @@
  * EL2.
  */
 .macro __init_el2_timers
-       mrs     x0, cnthctl_el2
-       orr     x0, x0, #3                      // Enable EL1 physical timers
+       mov     x0, #3                          // Enable EL1 physical timers
        msr     cnthctl_el2, x0
        msr     cntvoff_el2, xzr                // Clear virtual offset
 .endm
index e9a2b8f..0ca72f5 100644 (file)
@@ -94,10 +94,14 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
                kvm->arch.return_nisv_io_abort_to_user = true;
                break;
        case KVM_CAP_ARM_MTE:
-               if (!system_supports_mte() || kvm->created_vcpus)
-                       return -EINVAL;
-               r = 0;
-               kvm->arch.mte_enabled = true;
+               mutex_lock(&kvm->lock);
+               if (!system_supports_mte() || kvm->created_vcpus) {
+                       r = -EINVAL;
+               } else {
+                       r = 0;
+                       kvm->arch.mte_enabled = true;
+               }
+               mutex_unlock(&kvm->lock);
                break;
        default:
                r = -EINVAL;
index d938ce9..a6ce991 100644 (file)
@@ -193,7 +193,7 @@ static bool range_is_memory(u64 start, u64 end)
 {
        struct kvm_mem_range r1, r2;
 
-       if (!find_mem_range(start, &r1) || !find_mem_range(end, &r2))
+       if (!find_mem_range(start, &r1) || !find_mem_range(end - 1, &r2))
                return false;
        if (r1.start != r2.start)
                return false;
index 6420112..d4b145b 100644 (file)
@@ -4,6 +4,8 @@
 
 #include <asm/bug.h>
 #include <asm/book3s/32/mmu-hash.h>
+#include <asm/mmu.h>
+#include <asm/synch.h>
 
 #ifndef __ASSEMBLY__
 
@@ -28,6 +30,15 @@ static inline void kuep_lock(void)
                return;
 
        update_user_segments(mfsr(0) | SR_NX);
+       /*
+        * This isync() shouldn't be necessary as the kernel is not excepted to
+        * run any instruction in userspace soon after the update of segments,
+        * but hash based cores (at least G3) seem to exhibit a random
+        * behaviour when the 'isync' is not there. 603 cores don't have this
+        * behaviour so don't do the 'isync' as it saves several CPU cycles.
+        */
+       if (mmu_has_feature(MMU_FTR_HPTE_TABLE))
+               isync();        /* Context sync required after mtsr() */
 }
 
 static inline void kuep_unlock(void)
@@ -36,6 +47,15 @@ static inline void kuep_unlock(void)
                return;
 
        update_user_segments(mfsr(0) & ~SR_NX);
+       /*
+        * This isync() shouldn't be necessary as a 'rfi' will soon be executed
+        * to return to userspace, but hash based cores (at least G3) seem to
+        * exhibit a random behaviour when the 'isync' is not there. 603 cores
+        * don't have this behaviour so don't do the 'isync' as it saves several
+        * CPU cycles.
+        */
+       if (mmu_has_feature(MMU_FTR_HPTE_TABLE))
+               isync();        /* Context sync required after mtsr() */
 }
 
 #ifdef CONFIG_PPC_KUAP
index d4bdf7d..6b800d3 100644 (file)
@@ -583,6 +583,9 @@ DECLARE_INTERRUPT_HANDLER_NMI(hmi_exception_realmode);
 
 DECLARE_INTERRUPT_HANDLER_ASYNC(TAUException);
 
+/* irq.c */
+DECLARE_INTERRUPT_HANDLER_ASYNC(do_IRQ);
+
 void __noreturn unrecoverable_exception(struct pt_regs *regs);
 
 void replay_system_reset(void);
index 4982f37..2b32785 100644 (file)
@@ -52,7 +52,7 @@ extern void *mcheckirq_ctx[NR_CPUS];
 extern void *hardirq_ctx[NR_CPUS];
 extern void *softirq_ctx[NR_CPUS];
 
-extern void do_IRQ(struct pt_regs *regs);
+void __do_IRQ(struct pt_regs *regs);
 extern void __init init_IRQ(void);
 extern void __do_irq(struct pt_regs *regs);
 
index 3e5d470..14422e8 100644 (file)
@@ -70,6 +70,22 @@ struct pt_regs
                unsigned long __pad[4]; /* Maintain 16 byte interrupt stack alignment */
        };
 #endif
+#if defined(CONFIG_PPC32) && defined(CONFIG_BOOKE)
+       struct { /* Must be a multiple of 16 bytes */
+               unsigned long mas0;
+               unsigned long mas1;
+               unsigned long mas2;
+               unsigned long mas3;
+               unsigned long mas6;
+               unsigned long mas7;
+               unsigned long srr0;
+               unsigned long srr1;
+               unsigned long csrr0;
+               unsigned long csrr1;
+               unsigned long dsrr0;
+               unsigned long dsrr1;
+       };
+#endif
 };
 #endif
 
index a47eefa..5bee245 100644 (file)
@@ -309,24 +309,21 @@ int main(void)
        STACK_PT_REGS_OFFSET(STACK_REGS_IAMR, iamr);
 #endif
 
-#if defined(CONFIG_PPC32)
-#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
-       DEFINE(EXC_LVL_SIZE, STACK_EXC_LVL_FRAME_SIZE);
-       DEFINE(MAS0, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas0));
+#if defined(CONFIG_PPC32) && defined(CONFIG_BOOKE)
+       STACK_PT_REGS_OFFSET(MAS0, mas0);
        /* we overload MMUCR for 44x on MAS0 since they are mutually exclusive */
-       DEFINE(MMUCR, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas0));
-       DEFINE(MAS1, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas1));
-       DEFINE(MAS2, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas2));
-       DEFINE(MAS3, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas3));
-       DEFINE(MAS6, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas6));
-       DEFINE(MAS7, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas7));
-       DEFINE(_SRR0, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, srr0));
-       DEFINE(_SRR1, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, srr1));
-       DEFINE(_CSRR0, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, csrr0));
-       DEFINE(_CSRR1, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, csrr1));
-       DEFINE(_DSRR0, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, dsrr0));
-       DEFINE(_DSRR1, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, dsrr1));
-#endif
+       STACK_PT_REGS_OFFSET(MMUCR, mas0);
+       STACK_PT_REGS_OFFSET(MAS1, mas1);
+       STACK_PT_REGS_OFFSET(MAS2, mas2);
+       STACK_PT_REGS_OFFSET(MAS3, mas3);
+       STACK_PT_REGS_OFFSET(MAS6, mas6);
+       STACK_PT_REGS_OFFSET(MAS7, mas7);
+       STACK_PT_REGS_OFFSET(_SRR0, srr0);
+       STACK_PT_REGS_OFFSET(_SRR1, srr1);
+       STACK_PT_REGS_OFFSET(_CSRR0, csrr0);
+       STACK_PT_REGS_OFFSET(_CSRR1, csrr1);
+       STACK_PT_REGS_OFFSET(_DSRR0, dsrr0);
+       STACK_PT_REGS_OFFSET(_DSRR1, dsrr1);
 #endif
 
        /* About the CPU features table */
index 764edd8..68e5c0a 100644 (file)
@@ -300,7 +300,7 @@ ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_HPTE_TABLE)
        EXCEPTION_PROLOG_1
        EXCEPTION_PROLOG_2 INTERRUPT_DATA_STORAGE DataAccess handle_dar_dsisr=1
        prepare_transfer_to_handler
-       lwz     r5, _DSISR(r11)
+       lwz     r5, _DSISR(r1)
        andis.  r0, r5, DSISR_DABRMATCH@h
        bne-    1f
        bl      do_page_fault
index 87b806e..e550342 100644 (file)
@@ -168,20 +168,18 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV)
 /* only on e500mc */
 #define DBG_STACK_BASE         dbgirq_ctx
 
-#define EXC_LVL_FRAME_OVERHEAD (THREAD_SIZE - INT_FRAME_SIZE - EXC_LVL_SIZE)
-
 #ifdef CONFIG_SMP
 #define BOOKE_LOAD_EXC_LEVEL_STACK(level)              \
        mfspr   r8,SPRN_PIR;                            \
        slwi    r8,r8,2;                                \
        addis   r8,r8,level##_STACK_BASE@ha;            \
        lwz     r8,level##_STACK_BASE@l(r8);            \
-       addi    r8,r8,EXC_LVL_FRAME_OVERHEAD;
+       addi    r8,r8,THREAD_SIZE - INT_FRAME_SIZE;
 #else
 #define BOOKE_LOAD_EXC_LEVEL_STACK(level)              \
        lis     r8,level##_STACK_BASE@ha;               \
        lwz     r8,level##_STACK_BASE@l(r8);            \
-       addi    r8,r8,EXC_LVL_FRAME_OVERHEAD;
+       addi    r8,r8,THREAD_SIZE - INT_FRAME_SIZE;
 #endif
 
 /*
@@ -208,7 +206,7 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV)
        mtmsr   r11;                                                    \
        mfspr   r11,SPRN_SPRG_THREAD;   /* if from user, start at top of   */\
        lwz     r11, TASK_STACK - THREAD(r11); /* this thread's kernel stack */\
-       addi    r11,r11,EXC_LVL_FRAME_OVERHEAD; /* allocate stack frame    */\
+       addi    r11,r11,THREAD_SIZE - INT_FRAME_SIZE;   /* allocate stack frame    */\
        beq     1f;                                                          \
        /* COMING FROM USER MODE */                                          \
        stw     r9,_CCR(r11);           /* save CR                         */\
@@ -516,24 +514,5 @@ label:
        bl      kernel_fp_unavailable_exception;                              \
        b       interrupt_return
 
-#else /* __ASSEMBLY__ */
-struct exception_regs {
-       unsigned long mas0;
-       unsigned long mas1;
-       unsigned long mas2;
-       unsigned long mas3;
-       unsigned long mas6;
-       unsigned long mas7;
-       unsigned long srr0;
-       unsigned long srr1;
-       unsigned long csrr0;
-       unsigned long csrr1;
-       unsigned long dsrr0;
-       unsigned long dsrr1;
-};
-
-/* ensure this structure is always sized to a multiple of the stack alignment */
-#define STACK_EXC_LVL_FRAME_SIZE       ALIGN(sizeof (struct exception_regs), 16)
-
 #endif /* __ASSEMBLY__ */
 #endif /* __HEAD_BOOKE_H__ */
index 91e63ea..551b653 100644 (file)
@@ -750,7 +750,7 @@ void __do_irq(struct pt_regs *regs)
        trace_irq_exit(regs);
 }
 
-DEFINE_INTERRUPT_HANDLER_ASYNC(do_IRQ)
+void __do_IRQ(struct pt_regs *regs)
 {
        struct pt_regs *old_regs = set_irq_regs(regs);
        void *cursp, *irqsp, *sirqsp;
@@ -774,6 +774,11 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(do_IRQ)
        set_irq_regs(old_regs);
 }
 
+DEFINE_INTERRUPT_HANDLER_ASYNC(do_IRQ)
+{
+       __do_IRQ(regs);
+}
+
 static void *__init alloc_vm_stack(void)
 {
        return __vmalloc_node(THREAD_SIZE, THREAD_ALIGN, THREADINFO_GFP,
index cbc28d1..7a7cd6b 100644 (file)
@@ -292,7 +292,8 @@ int kprobe_handler(struct pt_regs *regs)
        if (user_mode(regs))
                return 0;
 
-       if (!(regs->msr & MSR_IR) || !(regs->msr & MSR_DR))
+       if (!IS_ENABLED(CONFIG_BOOKE) &&
+           (!(regs->msr & MSR_IR) || !(regs->msr & MSR_DR)))
                return 0;
 
        /*
index 5ff0e55..defecb3 100644 (file)
@@ -1167,7 +1167,7 @@ static int __init topology_init(void)
                 * CPU.  For instance, the boot cpu might never be valid
                 * for hotplugging.
                 */
-               if (smp_ops->cpu_offline_self)
+               if (smp_ops && smp_ops->cpu_offline_self)
                        c->hotpluggable = 1;
 #endif
 
index e45ce42..c487ba5 100644 (file)
@@ -586,7 +586,7 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(timer_interrupt)
 
 #if defined(CONFIG_PPC32) && defined(CONFIG_PPC_PMAC)
        if (atomic_read(&ppc_n_lost_interrupts) != 0)
-               do_IRQ(regs);
+               __do_IRQ(regs);
 #endif
 
        old_regs = set_irq_regs(regs);
index dfbce52..d56254f 100644 (file)
@@ -1104,7 +1104,7 @@ DEFINE_INTERRUPT_HANDLER(RunModeException)
        _exception(SIGTRAP, regs, TRAP_UNK, 0);
 }
 
-DEFINE_INTERRUPT_HANDLER(single_step_exception)
+static void __single_step_exception(struct pt_regs *regs)
 {
        clear_single_step(regs);
        clear_br_trace(regs);
@@ -1121,6 +1121,11 @@ DEFINE_INTERRUPT_HANDLER(single_step_exception)
        _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
 }
 
+DEFINE_INTERRUPT_HANDLER(single_step_exception)
+{
+       __single_step_exception(regs);
+}
+
 /*
  * After we have successfully emulated an instruction, we have to
  * check if the instruction was being single-stepped, and if so,
@@ -1130,7 +1135,7 @@ DEFINE_INTERRUPT_HANDLER(single_step_exception)
 static void emulate_single_step(struct pt_regs *regs)
 {
        if (single_stepping(regs))
-               single_step_exception(regs);
+               __single_step_exception(regs);
 }
 
 static inline int __parse_fpscr(unsigned long fpscr)
index 0876216..edea388 100644 (file)
 /*
  * Updates the attributes of a page in three steps:
  *
- * 1. invalidate the page table entry
- * 2. flush the TLB
- * 3. install the new entry with the updated attributes
- *
- * Invalidating the pte means there are situations where this will not work
- * when in theory it should.
- * For example:
- * - removing write from page whilst it is being executed
- * - setting a page read-only whilst it is being read by another CPU
+ * 1. take the page_table_lock
+ * 2. install the new entry with the updated attributes
+ * 3. flush the TLB
  *
+ * This sequence is safe against concurrent updates, and also allows updating the
+ * attributes of a page currently being executed or accessed.
  */
 static int change_page_attr(pte_t *ptep, unsigned long addr, void *data)
 {
@@ -36,9 +32,7 @@ static int change_page_attr(pte_t *ptep, unsigned long addr, void *data)
 
        spin_lock(&init_mm.page_table_lock);
 
-       /* invalidate the PTE so it's safe to modify */
-       pte = ptep_get_and_clear(&init_mm, addr, ptep);
-       flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
+       pte = ptep_get(ptep);
 
        /* modify the PTE bits as desired, then apply */
        switch (action) {
@@ -59,11 +53,14 @@ static int change_page_attr(pte_t *ptep, unsigned long addr, void *data)
                break;
        }
 
-       set_pte_at(&init_mm, addr, ptep, pte);
+       pte_update(&init_mm, addr, ptep, ~0UL, pte_val(pte), 0);
 
        /* See ptesync comment in radix__set_pte_at() */
        if (radix_enabled())
                asm volatile("ptesync": : :"memory");
+
+       flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
+
        spin_unlock(&init_mm.page_table_lock);
 
        return 0;
index 6b08866..0dfaa6a 100644 (file)
@@ -539,9 +539,10 @@ static void init_cpu_char_feature_flags(struct h_cpu_char_result *result)
         * H_CPU_BEHAV_FAVOUR_SECURITY_H could be set only if
         * H_CPU_BEHAV_FAVOUR_SECURITY is.
         */
-       if (!(result->behaviour & H_CPU_BEHAV_FAVOUR_SECURITY))
+       if (!(result->behaviour & H_CPU_BEHAV_FAVOUR_SECURITY)) {
                security_ftr_clear(SEC_FTR_FAVOUR_SECURITY);
-       else if (result->behaviour & H_CPU_BEHAV_FAVOUR_SECURITY_H)
+               pseries_security_flavor = 0;
+       } else if (result->behaviour & H_CPU_BEHAV_FAVOUR_SECURITY_H)
                pseries_security_flavor = 1;
        else
                pseries_security_flavor = 2;
index dbdbbc2..8183ca3 100644 (file)
@@ -67,6 +67,7 @@ static struct irq_domain *xive_irq_domain;
 static struct xive_ipi_desc {
        unsigned int irq;
        char name[16];
+       atomic_t started;
 } *xive_ipis;
 
 /*
@@ -1120,7 +1121,7 @@ static const struct irq_domain_ops xive_ipi_irq_domain_ops = {
        .alloc  = xive_ipi_irq_domain_alloc,
 };
 
-static int __init xive_request_ipi(void)
+static int __init xive_init_ipis(void)
 {
        struct fwnode_handle *fwnode;
        struct irq_domain *ipi_domain;
@@ -1144,10 +1145,6 @@ static int __init xive_request_ipi(void)
                struct xive_ipi_desc *xid = &xive_ipis[node];
                struct xive_ipi_alloc_info info = { node };
 
-               /* Skip nodes without CPUs */
-               if (cpumask_empty(cpumask_of_node(node)))
-                       continue;
-
                /*
                 * Map one IPI interrupt per node for all cpus of that node.
                 * Since the HW interrupt number doesn't have any meaning,
@@ -1159,11 +1156,6 @@ static int __init xive_request_ipi(void)
                xid->irq = ret;
 
                snprintf(xid->name, sizeof(xid->name), "IPI-%d", node);
-
-               ret = request_irq(xid->irq, xive_muxed_ipi_action,
-                                 IRQF_PERCPU | IRQF_NO_THREAD, xid->name, NULL);
-
-               WARN(ret < 0, "Failed to request IPI %d: %d\n", xid->irq, ret);
        }
 
        return ret;
@@ -1178,6 +1170,22 @@ out:
        return ret;
 }
 
+static int xive_request_ipi(unsigned int cpu)
+{
+       struct xive_ipi_desc *xid = &xive_ipis[early_cpu_to_node(cpu)];
+       int ret;
+
+       if (atomic_inc_return(&xid->started) > 1)
+               return 0;
+
+       ret = request_irq(xid->irq, xive_muxed_ipi_action,
+                         IRQF_PERCPU | IRQF_NO_THREAD,
+                         xid->name, NULL);
+
+       WARN(ret < 0, "Failed to request IPI %d: %d\n", xid->irq, ret);
+       return ret;
+}
+
 static int xive_setup_cpu_ipi(unsigned int cpu)
 {
        unsigned int xive_ipi_irq = xive_ipi_cpu_to_irq(cpu);
@@ -1192,6 +1200,9 @@ static int xive_setup_cpu_ipi(unsigned int cpu)
        if (xc->hw_ipi != XIVE_BAD_IRQ)
                return 0;
 
+       /* Register the IPI */
+       xive_request_ipi(cpu);
+
        /* Grab an IPI from the backend, this will populate xc->hw_ipi */
        if (xive_ops->get_ipi(cpu, xc))
                return -EIO;
@@ -1231,6 +1242,8 @@ static void xive_cleanup_cpu_ipi(unsigned int cpu, struct xive_cpu *xc)
        if (xc->hw_ipi == XIVE_BAD_IRQ)
                return;
 
+       /* TODO: clear IPI mapping */
+
        /* Mask the IPI */
        xive_do_source_set_mask(&xc->ipi_data, true);
 
@@ -1253,7 +1266,7 @@ void __init xive_smp_probe(void)
        smp_ops->cause_ipi = xive_cause_ipi;
 
        /* Register the IPI */
-       xive_request_ipi();
+       xive_init_ipis();
 
        /* Allocate and setup IPI for the boot CPU */
        xive_setup_cpu_ipi(smp_processor_id());
index d3081e4..3397dda 100644 (file)
@@ -11,7 +11,7 @@ endif
 CFLAGS_syscall_table.o += $(call cc-option,-Wno-override-init,)
 
 ifdef CONFIG_KEXEC
-AFLAGS_kexec_relocate.o := -mcmodel=medany -mno-relax
+AFLAGS_kexec_relocate.o := -mcmodel=medany $(call cc-option,-mno-relax)
 endif
 
 extra-y += head.o
index 18bd0e4..120b2f6 100644 (file)
@@ -229,8 +229,8 @@ static void __init init_resources(void)
        }
 
        /* Clean-up any unused pre-allocated resources */
-       mem_res_sz = (num_resources - res_idx + 1) * sizeof(*mem_res);
-       memblock_free(__pa(mem_res), mem_res_sz);
+       if (res_idx >= 0)
+               memblock_free(__pa(mem_res), (res_idx + 1) * sizeof(*mem_res));
        return;
 
  error:
index 88134cc..7cb4f39 100644 (file)
@@ -197,7 +197,7 @@ static void __init setup_bootmem(void)
         * if end of dram is equal to maximum addressable memory.  For 64-bit
         * kernel, this problem can't happen here as the end of the virtual
         * address space is occupied by the kernel mapping then this check must
-        * be done in create_kernel_page_table.
+        * be done as soon as the kernel mapping base address is determined.
         */
        max_mapped_addr = __pa(~(ulong)0);
        if (max_mapped_addr == (phys_ram_end - 1))
index b0993e0..8fcb7ec 100644 (file)
@@ -560,9 +560,12 @@ static void zpci_cleanup_bus_resources(struct zpci_dev *zdev)
 
 int pcibios_add_device(struct pci_dev *pdev)
 {
+       struct zpci_dev *zdev = to_zpci(pdev);
        struct resource *res;
        int i;
 
+       /* The pdev has a reference to the zdev via its bus */
+       zpci_zdev_get(zdev);
        if (pdev->is_physfn)
                pdev->no_vf_scan = 1;
 
@@ -582,7 +585,10 @@ int pcibios_add_device(struct pci_dev *pdev)
 
 void pcibios_release_device(struct pci_dev *pdev)
 {
+       struct zpci_dev *zdev = to_zpci(pdev);
+
        zpci_unmap_resources(pdev);
+       zpci_zdev_put(zdev);
 }
 
 int pcibios_enable_device(struct pci_dev *pdev, int mask)
index b877a97..e359d26 100644 (file)
@@ -22,6 +22,11 @@ static inline void zpci_zdev_put(struct zpci_dev *zdev)
        kref_put(&zdev->kref, zpci_release_device);
 }
 
+static inline void zpci_zdev_get(struct zpci_dev *zdev)
+{
+       kref_get(&zdev->kref);
+}
+
 int zpci_alloc_domain(int domain);
 void zpci_free_domain(int domain);
 int zpci_setup_bus_resources(struct zpci_dev *zdev,
index 974cbfb..af6ce8d 100644 (file)
@@ -1038,6 +1038,13 @@ struct kvm_arch {
        struct list_head lpage_disallowed_mmu_pages;
        struct kvm_page_track_notifier_node mmu_sp_tracker;
        struct kvm_page_track_notifier_head track_notifier_head;
+       /*
+        * Protects marking pages unsync during page faults, as TDP MMU page
+        * faults only take mmu_lock for read.  For simplicity, the unsync
+        * pages lock is always taken when marking pages unsync regardless of
+        * whether mmu_lock is held for read or write.
+        */
+       spinlock_t mmu_unsync_pages_lock;
 
        struct list_head assigned_dev_head;
        struct iommu_domain *iommu_domain;
index e322676..b00dbc5 100644 (file)
@@ -184,6 +184,8 @@ struct __attribute__ ((__packed__)) vmcb_control_area {
 #define V_IGN_TPR_SHIFT 20
 #define V_IGN_TPR_MASK (1 << V_IGN_TPR_SHIFT)
 
+#define V_IRQ_INJECTION_BITS_MASK (V_IRQ_MASK | V_INTR_PRIO_MASK | V_IGN_TPR_MASK)
+
 #define V_INTR_MASKING_SHIFT 24
 #define V_INTR_MASKING_MASK (1 << V_INTR_MASKING_SHIFT)
 
index d5c691a..39224e0 100644 (file)
@@ -1986,7 +1986,8 @@ static struct irq_chip ioapic_chip __read_mostly = {
        .irq_set_affinity       = ioapic_set_affinity,
        .irq_retrigger          = irq_chip_retrigger_hierarchy,
        .irq_get_irqchip_state  = ioapic_irq_get_chip_state,
-       .flags                  = IRQCHIP_SKIP_SET_WAKE,
+       .flags                  = IRQCHIP_SKIP_SET_WAKE |
+                                 IRQCHIP_AFFINITY_PRE_STARTUP,
 };
 
 static struct irq_chip ioapic_ir_chip __read_mostly = {
@@ -1999,7 +2000,8 @@ static struct irq_chip ioapic_ir_chip __read_mostly = {
        .irq_set_affinity       = ioapic_set_affinity,
        .irq_retrigger          = irq_chip_retrigger_hierarchy,
        .irq_get_irqchip_state  = ioapic_irq_get_chip_state,
-       .flags                  = IRQCHIP_SKIP_SET_WAKE,
+       .flags                  = IRQCHIP_SKIP_SET_WAKE |
+                                 IRQCHIP_AFFINITY_PRE_STARTUP,
 };
 
 static inline void init_IO_APIC_traps(void)
index 44ebe25..dbacb9e 100644 (file)
@@ -58,11 +58,13 @@ msi_set_affinity(struct irq_data *irqd, const struct cpumask *mask, bool force)
         *   The quirk bit is not set in this case.
         * - The new vector is the same as the old vector
         * - The old vector is MANAGED_IRQ_SHUTDOWN_VECTOR (interrupt starts up)
+        * - The interrupt is not yet started up
         * - The new destination CPU is the same as the old destination CPU
         */
        if (!irqd_msi_nomask_quirk(irqd) ||
            cfg->vector == old_cfg.vector ||
            old_cfg.vector == MANAGED_IRQ_SHUTDOWN_VECTOR ||
+           !irqd_is_started(irqd) ||
            cfg->dest_apicid == old_cfg.dest_apicid) {
                irq_msi_update_msg(irqd, cfg);
                return ret;
@@ -150,7 +152,8 @@ static struct irq_chip pci_msi_controller = {
        .irq_ack                = irq_chip_ack_parent,
        .irq_retrigger          = irq_chip_retrigger_hierarchy,
        .irq_set_affinity       = msi_set_affinity,
-       .flags                  = IRQCHIP_SKIP_SET_WAKE,
+       .flags                  = IRQCHIP_SKIP_SET_WAKE |
+                                 IRQCHIP_AFFINITY_PRE_STARTUP,
 };
 
 int pci_msi_prepare(struct irq_domain *domain, struct device *dev, int nvec,
@@ -219,7 +222,8 @@ static struct irq_chip pci_msi_ir_controller = {
        .irq_mask               = pci_msi_mask_irq,
        .irq_ack                = irq_chip_ack_parent,
        .irq_retrigger          = irq_chip_retrigger_hierarchy,
-       .flags                  = IRQCHIP_SKIP_SET_WAKE,
+       .flags                  = IRQCHIP_SKIP_SET_WAKE |
+                                 IRQCHIP_AFFINITY_PRE_STARTUP,
 };
 
 static struct msi_domain_info pci_msi_ir_domain_info = {
@@ -273,7 +277,8 @@ static struct irq_chip dmar_msi_controller = {
        .irq_retrigger          = irq_chip_retrigger_hierarchy,
        .irq_compose_msi_msg    = dmar_msi_compose_msg,
        .irq_write_msi_msg      = dmar_msi_write_msg,
-       .flags                  = IRQCHIP_SKIP_SET_WAKE,
+       .flags                  = IRQCHIP_SKIP_SET_WAKE |
+                                 IRQCHIP_AFFINITY_PRE_STARTUP,
 };
 
 static int dmar_msi_init(struct irq_domain *domain,
index f07c10b..57e4bb6 100644 (file)
@@ -285,15 +285,14 @@ static u64 mbm_overflow_count(u64 prev_msr, u64 cur_msr, unsigned int width)
        return chunks >>= shift;
 }
 
-static int __mon_event_count(u32 rmid, struct rmid_read *rr)
+static u64 __mon_event_count(u32 rmid, struct rmid_read *rr)
 {
        struct mbm_state *m;
        u64 chunks, tval;
 
        tval = __rmid_read(rmid, rr->evtid);
        if (tval & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL)) {
-               rr->val = tval;
-               return -EINVAL;
+               return tval;
        }
        switch (rr->evtid) {
        case QOS_L3_OCCUP_EVENT_ID:
@@ -305,12 +304,6 @@ static int __mon_event_count(u32 rmid, struct rmid_read *rr)
        case QOS_L3_MBM_LOCAL_EVENT_ID:
                m = &rr->d->mbm_local[rmid];
                break;
-       default:
-               /*
-                * Code would never reach here because
-                * an invalid event id would fail the __rmid_read.
-                */
-               return -EINVAL;
        }
 
        if (rr->first) {
@@ -361,23 +354,29 @@ void mon_event_count(void *info)
        struct rdtgroup *rdtgrp, *entry;
        struct rmid_read *rr = info;
        struct list_head *head;
+       u64 ret_val;
 
        rdtgrp = rr->rgrp;
 
-       if (__mon_event_count(rdtgrp->mon.rmid, rr))
-               return;
+       ret_val = __mon_event_count(rdtgrp->mon.rmid, rr);
 
        /*
-        * For Ctrl groups read data from child monitor groups.
+        * For Ctrl groups read data from child monitor groups and
+        * add them together. Count events which are read successfully.
+        * Discard the rmid_read's reporting errors.
         */
        head = &rdtgrp->mon.crdtgrp_list;
 
        if (rdtgrp->type == RDTCTRL_GROUP) {
                list_for_each_entry(entry, head, mon.crdtgrp_list) {
-                       if (__mon_event_count(entry->mon.rmid, rr))
-                               return;
+                       if (__mon_event_count(entry->mon.rmid, rr) == 0)
+                               ret_val = 0;
                }
        }
+
+       /* Report error if none of rmid_reads are successful */
+       if (ret_val)
+               rr->val = ret_val;
 }
 
 /*
index 08651a4..42fc41d 100644 (file)
@@ -508,7 +508,7 @@ static struct irq_chip hpet_msi_controller __ro_after_init = {
        .irq_set_affinity = msi_domain_set_affinity,
        .irq_retrigger = irq_chip_retrigger_hierarchy,
        .irq_write_msi_msg = hpet_msi_write_msg,
-       .flags = IRQCHIP_SKIP_SET_WAKE,
+       .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_AFFINITY_PRE_STARTUP,
 };
 
 static int hpet_msi_init(struct irq_domain *domain,
index 739be5d..fe03bd9 100644 (file)
@@ -208,30 +208,6 @@ static void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
        kvm_mmu_after_set_cpuid(vcpu);
 }
 
-static int is_efer_nx(void)
-{
-       return host_efer & EFER_NX;
-}
-
-static void cpuid_fix_nx_cap(struct kvm_vcpu *vcpu)
-{
-       int i;
-       struct kvm_cpuid_entry2 *e, *entry;
-
-       entry = NULL;
-       for (i = 0; i < vcpu->arch.cpuid_nent; ++i) {
-               e = &vcpu->arch.cpuid_entries[i];
-               if (e->function == 0x80000001) {
-                       entry = e;
-                       break;
-               }
-       }
-       if (entry && cpuid_entry_has(entry, X86_FEATURE_NX) && !is_efer_nx()) {
-               cpuid_entry_clear(entry, X86_FEATURE_NX);
-               printk(KERN_INFO "kvm: guest NX capability removed\n");
-       }
-}
-
 int cpuid_query_maxphyaddr(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpuid_entry2 *best;
@@ -302,7 +278,6 @@ int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
        vcpu->arch.cpuid_entries = e2;
        vcpu->arch.cpuid_nent = cpuid->nent;
 
-       cpuid_fix_nx_cap(vcpu);
        kvm_update_cpuid_runtime(vcpu);
        kvm_vcpu_after_set_cpuid(vcpu);
 
@@ -401,7 +376,6 @@ static __always_inline void kvm_cpu_cap_mask(enum cpuid_leafs leaf, u32 mask)
 
 void kvm_set_cpu_caps(void)
 {
-       unsigned int f_nx = is_efer_nx() ? F(NX) : 0;
 #ifdef CONFIG_X86_64
        unsigned int f_gbpages = F(GBPAGES);
        unsigned int f_lm = F(LM);
@@ -515,7 +489,7 @@ void kvm_set_cpu_caps(void)
                F(CX8) | F(APIC) | 0 /* Reserved */ | F(SYSCALL) |
                F(MTRR) | F(PGE) | F(MCA) | F(CMOV) |
                F(PAT) | F(PSE36) | 0 /* Reserved */ |
-               f_nx | 0 /* Reserved */ | F(MMXEXT) | F(MMX) |
+               F(NX) | 0 /* Reserved */ | F(MMXEXT) | F(MMX) |
                F(FXSR) | F(FXSR_OPT) | f_gbpages | F(RDTSCP) |
                0 /* Reserved */ | f_lm | F(3DNOWEXT) | F(3DNOW)
        );
index 0b38f94..41d2a53 100644 (file)
@@ -1933,7 +1933,7 @@ ret_success:
 void kvm_hv_set_cpuid(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpuid_entry2 *entry;
-       struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu);
+       struct kvm_vcpu_hv *hv_vcpu;
 
        entry = kvm_find_cpuid_entry(vcpu, HYPERV_CPUID_INTERFACE, 0);
        if (entry && entry->eax == HYPERV_CPUID_SIGNATURE_EAX) {
index c4f4fa2..47b7652 100644 (file)
@@ -2535,6 +2535,7 @@ static void kvm_unsync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
 int mmu_try_to_unsync_pages(struct kvm_vcpu *vcpu, gfn_t gfn, bool can_unsync)
 {
        struct kvm_mmu_page *sp;
+       bool locked = false;
 
        /*
         * Force write-protection if the page is being tracked.  Note, the page
@@ -2557,9 +2558,34 @@ int mmu_try_to_unsync_pages(struct kvm_vcpu *vcpu, gfn_t gfn, bool can_unsync)
                if (sp->unsync)
                        continue;
 
+               /*
+                * TDP MMU page faults require an additional spinlock as they
+                * run with mmu_lock held for read, not write, and the unsync
+                * logic is not thread safe.  Take the spinklock regardless of
+                * the MMU type to avoid extra conditionals/parameters, there's
+                * no meaningful penalty if mmu_lock is held for write.
+                */
+               if (!locked) {
+                       locked = true;
+                       spin_lock(&vcpu->kvm->arch.mmu_unsync_pages_lock);
+
+                       /*
+                        * Recheck after taking the spinlock, a different vCPU
+                        * may have since marked the page unsync.  A false
+                        * positive on the unprotected check above is not
+                        * possible as clearing sp->unsync _must_ hold mmu_lock
+                        * for write, i.e. unsync cannot transition from 0->1
+                        * while this CPU holds mmu_lock for read (or write).
+                        */
+                       if (READ_ONCE(sp->unsync))
+                               continue;
+               }
+
                WARN_ON(sp->role.level != PG_LEVEL_4K);
                kvm_unsync_page(vcpu, sp);
        }
+       if (locked)
+               spin_unlock(&vcpu->kvm->arch.mmu_unsync_pages_lock);
 
        /*
         * We need to ensure that the marking of unsync pages is visible
@@ -5537,6 +5563,8 @@ void kvm_mmu_init_vm(struct kvm *kvm)
 {
        struct kvm_page_track_notifier_node *node = &kvm->arch.mmu_sp_tracker;
 
+       spin_lock_init(&kvm->arch.mmu_unsync_pages_lock);
+
        if (!kvm_mmu_init_tdp_mmu(kvm))
                /*
                 * No smp_load/store wrappers needed here as we are in
index 0853370..d80cb12 100644 (file)
@@ -43,6 +43,7 @@ void kvm_mmu_uninit_tdp_mmu(struct kvm *kvm)
        if (!kvm->arch.tdp_mmu_enabled)
                return;
 
+       WARN_ON(!list_empty(&kvm->arch.tdp_mmu_pages));
        WARN_ON(!list_empty(&kvm->arch.tdp_mmu_roots));
 
        /*
@@ -81,8 +82,6 @@ static void tdp_mmu_free_sp_rcu_callback(struct rcu_head *head)
 void kvm_tdp_mmu_put_root(struct kvm *kvm, struct kvm_mmu_page *root,
                          bool shared)
 {
-       gfn_t max_gfn = 1ULL << (shadow_phys_bits - PAGE_SHIFT);
-
        kvm_lockdep_assert_mmu_lock_held(kvm, shared);
 
        if (!refcount_dec_and_test(&root->tdp_mmu_root_count))
@@ -94,7 +93,7 @@ void kvm_tdp_mmu_put_root(struct kvm *kvm, struct kvm_mmu_page *root,
        list_del_rcu(&root->link);
        spin_unlock(&kvm->arch.tdp_mmu_pages_lock);
 
-       zap_gfn_range(kvm, root, 0, max_gfn, false, false, shared);
+       zap_gfn_range(kvm, root, 0, -1ull, false, false, shared);
 
        call_rcu(&root->rcu_head, tdp_mmu_free_sp_rcu_callback);
 }
@@ -724,13 +723,29 @@ static bool zap_gfn_range(struct kvm *kvm, struct kvm_mmu_page *root,
                          gfn_t start, gfn_t end, bool can_yield, bool flush,
                          bool shared)
 {
+       gfn_t max_gfn_host = 1ULL << (shadow_phys_bits - PAGE_SHIFT);
+       bool zap_all = (start == 0 && end >= max_gfn_host);
        struct tdp_iter iter;
 
+       /*
+        * No need to try to step down in the iterator when zapping all SPTEs,
+        * zapping the top-level non-leaf SPTEs will recurse on their children.
+        */
+       int min_level = zap_all ? root->role.level : PG_LEVEL_4K;
+
+       /*
+        * Bound the walk at host.MAXPHYADDR, guest accesses beyond that will
+        * hit a #PF(RSVD) and never get to an EPT Violation/Misconfig / #NPF,
+        * and so KVM will never install a SPTE for such addresses.
+        */
+       end = min(end, max_gfn_host);
+
        kvm_lockdep_assert_mmu_lock_held(kvm, shared);
 
        rcu_read_lock();
 
-       tdp_root_for_each_pte(iter, root, start, end) {
+       for_each_tdp_pte_min_level(iter, root->spt, root->role.level,
+                                  min_level, start, end) {
 retry:
                if (can_yield &&
                    tdp_mmu_iter_cond_resched(kvm, &iter, flush, shared)) {
@@ -744,9 +759,10 @@ retry:
                /*
                 * If this is a non-last-level SPTE that covers a larger range
                 * than should be zapped, continue, and zap the mappings at a
-                * lower level.
+                * lower level, except when zapping all SPTEs.
                 */
-               if ((iter.gfn < start ||
+               if (!zap_all &&
+                   (iter.gfn < start ||
                     iter.gfn + KVM_PAGES_PER_HPAGE(iter.level) > end) &&
                    !is_last_spte(iter.old_spte, iter.level))
                        continue;
@@ -794,12 +810,11 @@ bool __kvm_tdp_mmu_zap_gfn_range(struct kvm *kvm, int as_id, gfn_t start,
 
 void kvm_tdp_mmu_zap_all(struct kvm *kvm)
 {
-       gfn_t max_gfn = 1ULL << (shadow_phys_bits - PAGE_SHIFT);
        bool flush = false;
        int i;
 
        for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++)
-               flush = kvm_tdp_mmu_zap_gfn_range(kvm, i, 0, max_gfn,
+               flush = kvm_tdp_mmu_zap_gfn_range(kvm, i, 0, -1ull,
                                                  flush, false);
 
        if (flush)
@@ -838,7 +853,6 @@ static struct kvm_mmu_page *next_invalidated_root(struct kvm *kvm,
  */
 void kvm_tdp_mmu_zap_invalidated_roots(struct kvm *kvm)
 {
-       gfn_t max_gfn = 1ULL << (shadow_phys_bits - PAGE_SHIFT);
        struct kvm_mmu_page *next_root;
        struct kvm_mmu_page *root;
        bool flush = false;
@@ -854,8 +868,7 @@ void kvm_tdp_mmu_zap_invalidated_roots(struct kvm *kvm)
 
                rcu_read_unlock();
 
-               flush = zap_gfn_range(kvm, root, 0, max_gfn, true, flush,
-                                     true);
+               flush = zap_gfn_range(kvm, root, 0, -1ull, true, flush, true);
 
                /*
                 * Put the reference acquired in
index 61738ff..e551547 100644 (file)
@@ -158,6 +158,9 @@ void recalc_intercepts(struct vcpu_svm *svm)
        /* If SMI is not intercepted, ignore guest SMI intercept as well  */
        if (!intercept_smi)
                vmcb_clr_intercept(c, INTERCEPT_SMI);
+
+       vmcb_set_intercept(c, INTERCEPT_VMLOAD);
+       vmcb_set_intercept(c, INTERCEPT_VMSAVE);
 }
 
 static void copy_vmcb_control_area(struct vmcb_control_area *dst,
@@ -503,7 +506,11 @@ static void nested_vmcb02_prepare_save(struct vcpu_svm *svm, struct vmcb *vmcb12
 
 static void nested_vmcb02_prepare_control(struct vcpu_svm *svm)
 {
-       const u32 mask = V_INTR_MASKING_MASK | V_GIF_ENABLE_MASK | V_GIF_MASK;
+       const u32 int_ctl_vmcb01_bits =
+               V_INTR_MASKING_MASK | V_GIF_MASK | V_GIF_ENABLE_MASK;
+
+       const u32 int_ctl_vmcb12_bits = V_TPR_MASK | V_IRQ_INJECTION_BITS_MASK;
+
        struct kvm_vcpu *vcpu = &svm->vcpu;
 
        /*
@@ -535,8 +542,8 @@ static void nested_vmcb02_prepare_control(struct vcpu_svm *svm)
                vcpu->arch.l1_tsc_offset + svm->nested.ctl.tsc_offset;
 
        svm->vmcb->control.int_ctl             =
-               (svm->nested.ctl.int_ctl & ~mask) |
-               (svm->vmcb01.ptr->control.int_ctl & mask);
+               (svm->nested.ctl.int_ctl & int_ctl_vmcb12_bits) |
+               (svm->vmcb01.ptr->control.int_ctl & int_ctl_vmcb01_bits);
 
        svm->vmcb->control.virt_ext            = svm->nested.ctl.virt_ext;
        svm->vmcb->control.int_vector          = svm->nested.ctl.int_vector;
index e8ccab5..69639f9 100644 (file)
@@ -1589,17 +1589,18 @@ static void svm_set_vintr(struct vcpu_svm *svm)
 
 static void svm_clear_vintr(struct vcpu_svm *svm)
 {
-       const u32 mask = V_TPR_MASK | V_GIF_ENABLE_MASK | V_GIF_MASK | V_INTR_MASKING_MASK;
        svm_clr_intercept(svm, INTERCEPT_VINTR);
 
        /* Drop int_ctl fields related to VINTR injection.  */
-       svm->vmcb->control.int_ctl &= mask;
+       svm->vmcb->control.int_ctl &= ~V_IRQ_INJECTION_BITS_MASK;
        if (is_guest_mode(&svm->vcpu)) {
-               svm->vmcb01.ptr->control.int_ctl &= mask;
+               svm->vmcb01.ptr->control.int_ctl &= ~V_IRQ_INJECTION_BITS_MASK;
 
                WARN_ON((svm->vmcb->control.int_ctl & V_TPR_MASK) !=
                        (svm->nested.ctl.int_ctl & V_TPR_MASK));
-               svm->vmcb->control.int_ctl |= svm->nested.ctl.int_ctl & ~mask;
+
+               svm->vmcb->control.int_ctl |= svm->nested.ctl.int_ctl &
+                       V_IRQ_INJECTION_BITS_MASK;
        }
 
        vmcb_mark_dirty(svm->vmcb, VMCB_INTR);
index 1a52134..b3f77d1 100644 (file)
@@ -330,6 +330,31 @@ void nested_vmx_free_vcpu(struct kvm_vcpu *vcpu)
        vcpu_put(vcpu);
 }
 
+#define EPTP_PA_MASK   GENMASK_ULL(51, 12)
+
+static bool nested_ept_root_matches(hpa_t root_hpa, u64 root_eptp, u64 eptp)
+{
+       return VALID_PAGE(root_hpa) &&
+              ((root_eptp & EPTP_PA_MASK) == (eptp & EPTP_PA_MASK));
+}
+
+static void nested_ept_invalidate_addr(struct kvm_vcpu *vcpu, gpa_t eptp,
+                                      gpa_t addr)
+{
+       uint i;
+       struct kvm_mmu_root_info *cached_root;
+
+       WARN_ON_ONCE(!mmu_is_nested(vcpu));
+
+       for (i = 0; i < KVM_MMU_NUM_PREV_ROOTS; i++) {
+               cached_root = &vcpu->arch.mmu->prev_roots[i];
+
+               if (nested_ept_root_matches(cached_root->hpa, cached_root->pgd,
+                                           eptp))
+                       vcpu->arch.mmu->invlpg(vcpu, addr, cached_root->hpa);
+       }
+}
+
 static void nested_ept_inject_page_fault(struct kvm_vcpu *vcpu,
                struct x86_exception *fault)
 {
@@ -342,10 +367,22 @@ static void nested_ept_inject_page_fault(struct kvm_vcpu *vcpu,
                vm_exit_reason = EXIT_REASON_PML_FULL;
                vmx->nested.pml_full = false;
                exit_qualification &= INTR_INFO_UNBLOCK_NMI;
-       } else if (fault->error_code & PFERR_RSVD_MASK)
-               vm_exit_reason = EXIT_REASON_EPT_MISCONFIG;
-       else
-               vm_exit_reason = EXIT_REASON_EPT_VIOLATION;
+       } else {
+               if (fault->error_code & PFERR_RSVD_MASK)
+                       vm_exit_reason = EXIT_REASON_EPT_MISCONFIG;
+               else
+                       vm_exit_reason = EXIT_REASON_EPT_VIOLATION;
+
+               /*
+                * Although the caller (kvm_inject_emulated_page_fault) would
+                * have already synced the faulting address in the shadow EPT
+                * tables for the current EPTP12, we also need to sync it for
+                * any other cached EPTP02s based on the same EP4TA, since the
+                * TLB associates mappings to the EP4TA rather than the full EPTP.
+                */
+               nested_ept_invalidate_addr(vcpu, vmcs12->ept_pointer,
+                                          fault->address);
+       }
 
        nested_vmx_vmexit(vcpu, vm_exit_reason, 0, exit_qualification);
        vmcs12->guest_physical_address = fault->address;
@@ -5325,14 +5362,6 @@ static int handle_vmptrst(struct kvm_vcpu *vcpu)
        return nested_vmx_succeed(vcpu);
 }
 
-#define EPTP_PA_MASK   GENMASK_ULL(51, 12)
-
-static bool nested_ept_root_matches(hpa_t root_hpa, u64 root_eptp, u64 eptp)
-{
-       return VALID_PAGE(root_hpa) &&
-               ((root_eptp & EPTP_PA_MASK) == (eptp & EPTP_PA_MASK));
-}
-
 /* Emulate the INVEPT instruction */
 static int handle_invept(struct kvm_vcpu *vcpu)
 {
@@ -5826,7 +5855,8 @@ static bool nested_vmx_l0_wants_exit(struct kvm_vcpu *vcpu,
                if (is_nmi(intr_info))
                        return true;
                else if (is_page_fault(intr_info))
-                       return vcpu->arch.apf.host_apf_flags || !enable_ept;
+                       return vcpu->arch.apf.host_apf_flags ||
+                              vmx_need_pf_intercept(vcpu);
                else if (is_debug(intr_info) &&
                         vcpu->guest_debug &
                         (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))
index db88ed4..17a1cb4 100644 (file)
@@ -522,7 +522,7 @@ static inline struct vmcs *alloc_vmcs(bool shadow)
 
 static inline bool vmx_has_waitpkg(struct vcpu_vmx *vmx)
 {
-       return vmx->secondary_exec_control &
+       return secondary_exec_controls_get(vmx) &
                SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE;
 }
 
index fd1ab80..a4cf678 100644 (file)
@@ -10,6 +10,7 @@ BEGIN {
 
 /^GNU objdump/ {
        verstr = ""
+       gsub(/\(.*\)/, "");
        for (i = 3; i <= NF; i++)
                if (match($(i), "^[0-9]")) {
                        verstr = $(i);
index 64053d6..2f2158e 100644 (file)
@@ -9,12 +9,6 @@ config MQ_IOSCHED_DEADLINE
        help
          MQ version of the deadline IO scheduler.
 
-config MQ_IOSCHED_DEADLINE_CGROUP
-       tristate
-       default y
-       depends on MQ_IOSCHED_DEADLINE
-       depends on BLK_CGROUP
-
 config MQ_IOSCHED_KYBER
        tristate "Kyber I/O scheduler"
        default y
index bfbe4e1..1e1afa1 100644 (file)
@@ -22,8 +22,6 @@ obj-$(CONFIG_BLK_CGROUP_IOPRIO)       += blk-ioprio.o
 obj-$(CONFIG_BLK_CGROUP_IOLATENCY)     += blk-iolatency.o
 obj-$(CONFIG_BLK_CGROUP_IOCOST)        += blk-iocost.o
 obj-$(CONFIG_MQ_IOSCHED_DEADLINE)      += mq-deadline.o
-mq-deadline-y += mq-deadline-main.o
-mq-deadline-$(CONFIG_MQ_IOSCHED_DEADLINE_CGROUP)+= mq-deadline-cgroup.o
 obj-$(CONFIG_MQ_IOSCHED_KYBER) += kyber-iosched.o
 bfq-y                          := bfq-iosched.o bfq-wf2q.o bfq-cgroup.o
 obj-$(CONFIG_IOSCHED_BFQ)      += bfq.o
index 575d7a2..31fe9be 100644 (file)
@@ -790,6 +790,7 @@ static void blkcg_rstat_flush(struct cgroup_subsys_state *css, int cpu)
                struct blkcg_gq *parent = blkg->parent;
                struct blkg_iostat_set *bisc = per_cpu_ptr(blkg->iostat_cpu, cpu);
                struct blkg_iostat cur, delta;
+               unsigned long flags;
                unsigned int seq;
 
                /* fetch the current per-cpu values */
@@ -799,21 +800,21 @@ static void blkcg_rstat_flush(struct cgroup_subsys_state *css, int cpu)
                } while (u64_stats_fetch_retry(&bisc->sync, seq));
 
                /* propagate percpu delta to global */
-               u64_stats_update_begin(&blkg->iostat.sync);
+               flags = u64_stats_update_begin_irqsave(&blkg->iostat.sync);
                blkg_iostat_set(&delta, &cur);
                blkg_iostat_sub(&delta, &bisc->last);
                blkg_iostat_add(&blkg->iostat.cur, &delta);
                blkg_iostat_add(&bisc->last, &delta);
-               u64_stats_update_end(&blkg->iostat.sync);
+               u64_stats_update_end_irqrestore(&blkg->iostat.sync, flags);
 
                /* propagate global delta to parent (unless that's root) */
                if (parent && parent->parent) {
-                       u64_stats_update_begin(&parent->iostat.sync);
+                       flags = u64_stats_update_begin_irqsave(&parent->iostat.sync);
                        blkg_iostat_set(&delta, &blkg->iostat.cur);
                        blkg_iostat_sub(&delta, &blkg->iostat.last);
                        blkg_iostat_add(&parent->iostat.cur, &delta);
                        blkg_iostat_add(&blkg->iostat.last, &delta);
-                       u64_stats_update_end(&parent->iostat.sync);
+                       u64_stats_update_end_irqrestore(&parent->iostat.sync, flags);
                }
        }
 
@@ -848,6 +849,7 @@ static void blkcg_fill_root_iostats(void)
                memset(&tmp, 0, sizeof(tmp));
                for_each_possible_cpu(cpu) {
                        struct disk_stats *cpu_dkstats;
+                       unsigned long flags;
 
                        cpu_dkstats = per_cpu_ptr(bdev->bd_stats, cpu);
                        tmp.ios[BLKG_IOSTAT_READ] +=
@@ -864,9 +866,9 @@ static void blkcg_fill_root_iostats(void)
                        tmp.bytes[BLKG_IOSTAT_DISCARD] +=
                                cpu_dkstats->sectors[STAT_DISCARD] << 9;
 
-                       u64_stats_update_begin(&blkg->iostat.sync);
+                       flags = u64_stats_update_begin_irqsave(&blkg->iostat.sync);
                        blkg_iostat_set(&blkg->iostat.cur, &tmp);
-                       u64_stats_update_end(&blkg->iostat.sync);
+                       u64_stats_update_end_irqrestore(&blkg->iostat.sync, flags);
                }
        }
 }
index 0447769..4f8449b 100644 (file)
@@ -122,7 +122,6 @@ void blk_rq_init(struct request_queue *q, struct request *rq)
        rq->internal_tag = BLK_MQ_NO_TAG;
        rq->start_time_ns = ktime_get_ns();
        rq->part = NULL;
-       refcount_set(&rq->ref, 1);
        blk_crypto_rq_set_defaults(rq);
 }
 EXPORT_SYMBOL(blk_rq_init);
index 1002f6c..4201728 100644 (file)
@@ -262,6 +262,11 @@ static void flush_end_io(struct request *flush_rq, blk_status_t error)
        spin_unlock_irqrestore(&fq->mq_flush_lock, flags);
 }
 
+bool is_flush_rq(struct request *rq)
+{
+       return rq->end_io == flush_end_io;
+}
+
 /**
  * blk_kick_flush - consider issuing flush request
  * @q: request_queue being kicked
@@ -329,6 +334,14 @@ static void blk_kick_flush(struct request_queue *q, struct blk_flush_queue *fq,
        flush_rq->rq_flags |= RQF_FLUSH_SEQ;
        flush_rq->rq_disk = first_rq->rq_disk;
        flush_rq->end_io = flush_end_io;
+       /*
+        * Order WRITE ->end_io and WRITE rq->ref, and its pair is the one
+        * implied in refcount_inc_not_zero() called from
+        * blk_mq_find_and_get_req(), which orders WRITE/READ flush_rq->ref
+        * and READ flush_rq->end_io
+        */
+       smp_wmb();
+       refcount_set(&flush_rq->ref, 1);
 
        blk_flush_queue_rq(flush_rq, false);
 }
index 5fac375..0e56557 100644 (file)
@@ -3061,19 +3061,19 @@ static ssize_t ioc_weight_write(struct kernfs_open_file *of, char *buf,
                if (v < CGROUP_WEIGHT_MIN || v > CGROUP_WEIGHT_MAX)
                        return -EINVAL;
 
-               spin_lock(&blkcg->lock);
+               spin_lock_irq(&blkcg->lock);
                iocc->dfl_weight = v * WEIGHT_ONE;
                hlist_for_each_entry(blkg, &blkcg->blkg_list, blkcg_node) {
                        struct ioc_gq *iocg = blkg_to_iocg(blkg);
 
                        if (iocg) {
-                               spin_lock_irq(&iocg->ioc->lock);
+                               spin_lock(&iocg->ioc->lock);
                                ioc_now(iocg->ioc, &now);
                                weight_updated(iocg, &now);
-                               spin_unlock_irq(&iocg->ioc->lock);
+                               spin_unlock(&iocg->ioc->lock);
                        }
                }
-               spin_unlock(&blkcg->lock);
+               spin_unlock_irq(&blkcg->lock);
 
                return nbytes;
        }
index 2c4ac51..9d4fdc2 100644 (file)
@@ -911,7 +911,7 @@ static bool blk_mq_req_expired(struct request *rq, unsigned long *next)
 
 void blk_mq_put_rq_ref(struct request *rq)
 {
-       if (is_flush_rq(rq, rq->mq_hctx))
+       if (is_flush_rq(rq))
                rq->end_io(rq, 0);
        else if (refcount_dec_and_test(&rq->ref))
                __blk_mq_free_request(rq);
@@ -923,34 +923,14 @@ static bool blk_mq_check_expired(struct blk_mq_hw_ctx *hctx,
        unsigned long *next = priv;
 
        /*
-        * Just do a quick check if it is expired before locking the request in
-        * so we're not unnecessarilly synchronizing across CPUs.
-        */
-       if (!blk_mq_req_expired(rq, next))
-               return true;
-
-       /*
-        * We have reason to believe the request may be expired. Take a
-        * reference on the request to lock this request lifetime into its
-        * currently allocated context to prevent it from being reallocated in
-        * the event the completion by-passes this timeout handler.
-        *
-        * If the reference was already released, then the driver beat the
-        * timeout handler to posting a natural completion.
-        */
-       if (!refcount_inc_not_zero(&rq->ref))
-               return true;
-
-       /*
-        * The request is now locked and cannot be reallocated underneath the
-        * timeout handler's processing. Re-verify this exact request is truly
-        * expired; if it is not expired, then the request was completed and
-        * reallocated as a new request.
+        * blk_mq_queue_tag_busy_iter() has locked the request, so it cannot
+        * be reallocated underneath the timeout handler's processing, then
+        * the expire check is reliable. If the request is not expired, then
+        * it was completed and reallocated as a new request after returning
+        * from blk_mq_check_expired().
         */
        if (blk_mq_req_expired(rq, next))
                blk_mq_rq_timed_out(rq, reserved);
-
-       blk_mq_put_rq_ref(rq);
        return true;
 }
 
@@ -2994,10 +2974,12 @@ static void queue_set_hctx_shared(struct request_queue *q, bool shared)
        int i;
 
        queue_for_each_hw_ctx(q, hctx, i) {
-               if (shared)
+               if (shared) {
                        hctx->flags |= BLK_MQ_F_TAG_QUEUE_SHARED;
-               else
+               } else {
+                       blk_mq_tag_idle(hctx);
                        hctx->flags &= ~BLK_MQ_F_TAG_QUEUE_SHARED;
+               }
        }
 }
 
index 4b885c0..cb01429 100644 (file)
@@ -44,11 +44,7 @@ static inline void __blk_get_queue(struct request_queue *q)
        kobject_get(&q->kobj);
 }
 
-static inline bool
-is_flush_rq(struct request *req, struct blk_mq_hw_ctx *hctx)
-{
-       return hctx->fq->flush_rq == req;
-}
+bool is_flush_rq(struct request *req);
 
 struct blk_flush_queue *blk_alloc_flush_queue(int node, int cmd_size,
                                              gfp_t flags);
diff --git a/block/mq-deadline-cgroup.c b/block/mq-deadline-cgroup.c
deleted file mode 100644 (file)
index 3b4bfdd..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-
-#include <linux/blk-cgroup.h>
-#include <linux/ioprio.h>
-
-#include "mq-deadline-cgroup.h"
-
-static struct blkcg_policy dd_blkcg_policy;
-
-static struct blkcg_policy_data *dd_cpd_alloc(gfp_t gfp)
-{
-       struct dd_blkcg *pd;
-
-       pd = kzalloc(sizeof(*pd), gfp);
-       if (!pd)
-               return NULL;
-       pd->stats = alloc_percpu_gfp(typeof(*pd->stats),
-                                    GFP_KERNEL | __GFP_ZERO);
-       if (!pd->stats) {
-               kfree(pd);
-               return NULL;
-       }
-       return &pd->cpd;
-}
-
-static void dd_cpd_free(struct blkcg_policy_data *cpd)
-{
-       struct dd_blkcg *dd_blkcg = container_of(cpd, typeof(*dd_blkcg), cpd);
-
-       free_percpu(dd_blkcg->stats);
-       kfree(dd_blkcg);
-}
-
-static struct dd_blkcg *dd_blkcg_from_pd(struct blkg_policy_data *pd)
-{
-       return container_of(blkcg_to_cpd(pd->blkg->blkcg, &dd_blkcg_policy),
-                           struct dd_blkcg, cpd);
-}
-
-/*
- * Convert an association between a block cgroup and a request queue into a
- * pointer to the mq-deadline information associated with a (blkcg, queue) pair.
- */
-struct dd_blkcg *dd_blkcg_from_bio(struct bio *bio)
-{
-       struct blkg_policy_data *pd;
-
-       pd = blkg_to_pd(bio->bi_blkg, &dd_blkcg_policy);
-       if (!pd)
-               return NULL;
-
-       return dd_blkcg_from_pd(pd);
-}
-
-static size_t dd_pd_stat(struct blkg_policy_data *pd, char *buf, size_t size)
-{
-       static const char *const prio_class_name[] = {
-               [IOPRIO_CLASS_NONE]     = "NONE",
-               [IOPRIO_CLASS_RT]       = "RT",
-               [IOPRIO_CLASS_BE]       = "BE",
-               [IOPRIO_CLASS_IDLE]     = "IDLE",
-       };
-       struct dd_blkcg *blkcg = dd_blkcg_from_pd(pd);
-       int res = 0;
-       u8 prio;
-
-       for (prio = 0; prio < ARRAY_SIZE(blkcg->stats->stats); prio++)
-               res += scnprintf(buf + res, size - res,
-                       " [%s] dispatched=%u inserted=%u merged=%u",
-                       prio_class_name[prio],
-                       ddcg_sum(blkcg, dispatched, prio) +
-                       ddcg_sum(blkcg, merged, prio) -
-                       ddcg_sum(blkcg, completed, prio),
-                       ddcg_sum(blkcg, inserted, prio) -
-                       ddcg_sum(blkcg, completed, prio),
-                       ddcg_sum(blkcg, merged, prio));
-
-       return res;
-}
-
-static struct blkg_policy_data *dd_pd_alloc(gfp_t gfp, struct request_queue *q,
-                                           struct blkcg *blkcg)
-{
-       struct dd_blkg *pd;
-
-       pd = kzalloc(sizeof(*pd), gfp);
-       if (!pd)
-               return NULL;
-       return &pd->pd;
-}
-
-static void dd_pd_free(struct blkg_policy_data *pd)
-{
-       struct dd_blkg *dd_blkg = container_of(pd, typeof(*dd_blkg), pd);
-
-       kfree(dd_blkg);
-}
-
-static struct blkcg_policy dd_blkcg_policy = {
-       .cpd_alloc_fn           = dd_cpd_alloc,
-       .cpd_free_fn            = dd_cpd_free,
-
-       .pd_alloc_fn            = dd_pd_alloc,
-       .pd_free_fn             = dd_pd_free,
-       .pd_stat_fn             = dd_pd_stat,
-};
-
-int dd_activate_policy(struct request_queue *q)
-{
-       return blkcg_activate_policy(q, &dd_blkcg_policy);
-}
-
-void dd_deactivate_policy(struct request_queue *q)
-{
-       blkcg_deactivate_policy(q, &dd_blkcg_policy);
-}
-
-int __init dd_blkcg_init(void)
-{
-       return blkcg_policy_register(&dd_blkcg_policy);
-}
-
-void __exit dd_blkcg_exit(void)
-{
-       blkcg_policy_unregister(&dd_blkcg_policy);
-}
diff --git a/block/mq-deadline-cgroup.h b/block/mq-deadline-cgroup.h
deleted file mode 100644 (file)
index 0143fd7..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-
-#if !defined(_MQ_DEADLINE_CGROUP_H_)
-#define _MQ_DEADLINE_CGROUP_H_
-
-#include <linux/blk-cgroup.h>
-
-struct request_queue;
-
-/**
- * struct io_stats_per_prio - I/O statistics per I/O priority class.
- * @inserted: Number of inserted requests.
- * @merged: Number of merged requests.
- * @dispatched: Number of dispatched requests.
- * @completed: Number of I/O completions.
- */
-struct io_stats_per_prio {
-       local_t inserted;
-       local_t merged;
-       local_t dispatched;
-       local_t completed;
-};
-
-/* I/O statistics per I/O cgroup per I/O priority class (IOPRIO_CLASS_*). */
-struct blkcg_io_stats {
-       struct io_stats_per_prio stats[4];
-};
-
-/**
- * struct dd_blkcg - Per cgroup data.
- * @cpd: blkcg_policy_data structure.
- * @stats: I/O statistics.
- */
-struct dd_blkcg {
-       struct blkcg_policy_data cpd;   /* must be the first member */
-       struct blkcg_io_stats __percpu *stats;
-};
-
-/*
- * Count one event of type 'event_type' and with I/O priority class
- * 'prio_class'.
- */
-#define ddcg_count(ddcg, event_type, prio_class) do {                  \
-if (ddcg) {                                                            \
-       struct blkcg_io_stats *io_stats = get_cpu_ptr((ddcg)->stats);   \
-                                                                       \
-       BUILD_BUG_ON(!__same_type((ddcg), struct dd_blkcg *));          \
-       BUILD_BUG_ON(!__same_type((prio_class), u8));                   \
-       local_inc(&io_stats->stats[(prio_class)].event_type);           \
-       put_cpu_ptr(io_stats);                                          \
-}                                                                      \
-} while (0)
-
-/*
- * Returns the total number of ddcg_count(ddcg, event_type, prio_class) calls
- * across all CPUs. No locking or barriers since it is fine if the returned
- * sum is slightly outdated.
- */
-#define ddcg_sum(ddcg, event_type, prio) ({                            \
-       unsigned int cpu;                                               \
-       u32 sum = 0;                                                    \
-                                                                       \
-       BUILD_BUG_ON(!__same_type((ddcg), struct dd_blkcg *));          \
-       BUILD_BUG_ON(!__same_type((prio), u8));                         \
-       for_each_present_cpu(cpu)                                       \
-               sum += local_read(&per_cpu_ptr((ddcg)->stats, cpu)->    \
-                                 stats[(prio)].event_type);            \
-       sum;                                                            \
-})
-
-#ifdef CONFIG_BLK_CGROUP
-
-/**
- * struct dd_blkg - Per (cgroup, request queue) data.
- * @pd: blkg_policy_data structure.
- */
-struct dd_blkg {
-       struct blkg_policy_data pd;     /* must be the first member */
-};
-
-struct dd_blkcg *dd_blkcg_from_bio(struct bio *bio);
-int dd_activate_policy(struct request_queue *q);
-void dd_deactivate_policy(struct request_queue *q);
-int __init dd_blkcg_init(void);
-void __exit dd_blkcg_exit(void);
-
-#else /* CONFIG_BLK_CGROUP */
-
-static inline struct dd_blkcg *dd_blkcg_from_bio(struct bio *bio)
-{
-       return NULL;
-}
-
-static inline int dd_activate_policy(struct request_queue *q)
-{
-       return 0;
-}
-
-static inline void dd_deactivate_policy(struct request_queue *q)
-{
-}
-
-static inline int dd_blkcg_init(void)
-{
-       return 0;
-}
-
-static inline void dd_blkcg_exit(void)
-{
-}
-
-#endif /* CONFIG_BLK_CGROUP */
-
-#endif /* _MQ_DEADLINE_CGROUP_H_ */
diff --git a/block/mq-deadline-main.c b/block/mq-deadline-main.c
deleted file mode 100644 (file)
index 6f612e6..0000000
+++ /dev/null
@@ -1,1175 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- *  MQ Deadline i/o scheduler - adaptation of the legacy deadline scheduler,
- *  for the blk-mq scheduling framework
- *
- *  Copyright (C) 2016 Jens Axboe <axboe@kernel.dk>
- */
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/blkdev.h>
-#include <linux/blk-mq.h>
-#include <linux/elevator.h>
-#include <linux/bio.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/compiler.h>
-#include <linux/rbtree.h>
-#include <linux/sbitmap.h>
-
-#include <trace/events/block.h>
-
-#include "blk.h"
-#include "blk-mq.h"
-#include "blk-mq-debugfs.h"
-#include "blk-mq-tag.h"
-#include "blk-mq-sched.h"
-#include "mq-deadline-cgroup.h"
-
-/*
- * See Documentation/block/deadline-iosched.rst
- */
-static const int read_expire = HZ / 2;  /* max time before a read is submitted. */
-static const int write_expire = 5 * HZ; /* ditto for writes, these limits are SOFT! */
-/*
- * Time after which to dispatch lower priority requests even if higher
- * priority requests are pending.
- */
-static const int aging_expire = 10 * HZ;
-static const int writes_starved = 2;    /* max times reads can starve a write */
-static const int fifo_batch = 16;       /* # of sequential requests treated as one
-                                    by the above parameters. For throughput. */
-
-enum dd_data_dir {
-       DD_READ         = READ,
-       DD_WRITE        = WRITE,
-};
-
-enum { DD_DIR_COUNT = 2 };
-
-enum dd_prio {
-       DD_RT_PRIO      = 0,
-       DD_BE_PRIO      = 1,
-       DD_IDLE_PRIO    = 2,
-       DD_PRIO_MAX     = 2,
-};
-
-enum { DD_PRIO_COUNT = 3 };
-
-/* I/O statistics for all I/O priorities (enum dd_prio). */
-struct io_stats {
-       struct io_stats_per_prio stats[DD_PRIO_COUNT];
-};
-
-/*
- * Deadline scheduler data per I/O priority (enum dd_prio). Requests are
- * present on both sort_list[] and fifo_list[].
- */
-struct dd_per_prio {
-       struct list_head dispatch;
-       struct rb_root sort_list[DD_DIR_COUNT];
-       struct list_head fifo_list[DD_DIR_COUNT];
-       /* Next request in FIFO order. Read, write or both are NULL. */
-       struct request *next_rq[DD_DIR_COUNT];
-};
-
-struct deadline_data {
-       /*
-        * run time data
-        */
-
-       /* Request queue that owns this data structure. */
-       struct request_queue *queue;
-
-       struct dd_per_prio per_prio[DD_PRIO_COUNT];
-
-       /* Data direction of latest dispatched request. */
-       enum dd_data_dir last_dir;
-       unsigned int batching;          /* number of sequential requests made */
-       unsigned int starved;           /* times reads have starved writes */
-
-       struct io_stats __percpu *stats;
-
-       /*
-        * settings that change how the i/o scheduler behaves
-        */
-       int fifo_expire[DD_DIR_COUNT];
-       int fifo_batch;
-       int writes_starved;
-       int front_merges;
-       u32 async_depth;
-       int aging_expire;
-
-       spinlock_t lock;
-       spinlock_t zone_lock;
-};
-
-/* Count one event of type 'event_type' and with I/O priority 'prio' */
-#define dd_count(dd, event_type, prio) do {                            \
-       struct io_stats *io_stats = get_cpu_ptr((dd)->stats);           \
-                                                                       \
-       BUILD_BUG_ON(!__same_type((dd), struct deadline_data *));       \
-       BUILD_BUG_ON(!__same_type((prio), enum dd_prio));               \
-       local_inc(&io_stats->stats[(prio)].event_type);                 \
-       put_cpu_ptr(io_stats);                                          \
-} while (0)
-
-/*
- * Returns the total number of dd_count(dd, event_type, prio) calls across all
- * CPUs. No locking or barriers since it is fine if the returned sum is slightly
- * outdated.
- */
-#define dd_sum(dd, event_type, prio) ({                                        \
-       unsigned int cpu;                                               \
-       u32 sum = 0;                                                    \
-                                                                       \
-       BUILD_BUG_ON(!__same_type((dd), struct deadline_data *));       \
-       BUILD_BUG_ON(!__same_type((prio), enum dd_prio));               \
-       for_each_present_cpu(cpu)                                       \
-               sum += local_read(&per_cpu_ptr((dd)->stats, cpu)->      \
-                                 stats[(prio)].event_type);            \
-       sum;                                                            \
-})
-
-/* Maps an I/O priority class to a deadline scheduler priority. */
-static const enum dd_prio ioprio_class_to_prio[] = {
-       [IOPRIO_CLASS_NONE]     = DD_BE_PRIO,
-       [IOPRIO_CLASS_RT]       = DD_RT_PRIO,
-       [IOPRIO_CLASS_BE]       = DD_BE_PRIO,
-       [IOPRIO_CLASS_IDLE]     = DD_IDLE_PRIO,
-};
-
-static inline struct rb_root *
-deadline_rb_root(struct dd_per_prio *per_prio, struct request *rq)
-{
-       return &per_prio->sort_list[rq_data_dir(rq)];
-}
-
-/*
- * Returns the I/O priority class (IOPRIO_CLASS_*) that has been assigned to a
- * request.
- */
-static u8 dd_rq_ioclass(struct request *rq)
-{
-       return IOPRIO_PRIO_CLASS(req_get_ioprio(rq));
-}
-
-/*
- * get the request after `rq' in sector-sorted order
- */
-static inline struct request *
-deadline_latter_request(struct request *rq)
-{
-       struct rb_node *node = rb_next(&rq->rb_node);
-
-       if (node)
-               return rb_entry_rq(node);
-
-       return NULL;
-}
-
-static void
-deadline_add_rq_rb(struct dd_per_prio *per_prio, struct request *rq)
-{
-       struct rb_root *root = deadline_rb_root(per_prio, rq);
-
-       elv_rb_add(root, rq);
-}
-
-static inline void
-deadline_del_rq_rb(struct dd_per_prio *per_prio, struct request *rq)
-{
-       const enum dd_data_dir data_dir = rq_data_dir(rq);
-
-       if (per_prio->next_rq[data_dir] == rq)
-               per_prio->next_rq[data_dir] = deadline_latter_request(rq);
-
-       elv_rb_del(deadline_rb_root(per_prio, rq), rq);
-}
-
-/*
- * remove rq from rbtree and fifo.
- */
-static void deadline_remove_request(struct request_queue *q,
-                                   struct dd_per_prio *per_prio,
-                                   struct request *rq)
-{
-       list_del_init(&rq->queuelist);
-
-       /*
-        * We might not be on the rbtree, if we are doing an insert merge
-        */
-       if (!RB_EMPTY_NODE(&rq->rb_node))
-               deadline_del_rq_rb(per_prio, rq);
-
-       elv_rqhash_del(q, rq);
-       if (q->last_merge == rq)
-               q->last_merge = NULL;
-}
-
-static void dd_request_merged(struct request_queue *q, struct request *req,
-                             enum elv_merge type)
-{
-       struct deadline_data *dd = q->elevator->elevator_data;
-       const u8 ioprio_class = dd_rq_ioclass(req);
-       const enum dd_prio prio = ioprio_class_to_prio[ioprio_class];
-       struct dd_per_prio *per_prio = &dd->per_prio[prio];
-
-       /*
-        * if the merge was a front merge, we need to reposition request
-        */
-       if (type == ELEVATOR_FRONT_MERGE) {
-               elv_rb_del(deadline_rb_root(per_prio, req), req);
-               deadline_add_rq_rb(per_prio, req);
-       }
-}
-
-/*
- * Callback function that is invoked after @next has been merged into @req.
- */
-static void dd_merged_requests(struct request_queue *q, struct request *req,
-                              struct request *next)
-{
-       struct deadline_data *dd = q->elevator->elevator_data;
-       const u8 ioprio_class = dd_rq_ioclass(next);
-       const enum dd_prio prio = ioprio_class_to_prio[ioprio_class];
-       struct dd_blkcg *blkcg = next->elv.priv[0];
-
-       dd_count(dd, merged, prio);
-       ddcg_count(blkcg, merged, ioprio_class);
-
-       /*
-        * if next expires before rq, assign its expire time to rq
-        * and move into next position (next will be deleted) in fifo
-        */
-       if (!list_empty(&req->queuelist) && !list_empty(&next->queuelist)) {
-               if (time_before((unsigned long)next->fifo_time,
-                               (unsigned long)req->fifo_time)) {
-                       list_move(&req->queuelist, &next->queuelist);
-                       req->fifo_time = next->fifo_time;
-               }
-       }
-
-       /*
-        * kill knowledge of next, this one is a goner
-        */
-       deadline_remove_request(q, &dd->per_prio[prio], next);
-}
-
-/*
- * move an entry to dispatch queue
- */
-static void
-deadline_move_request(struct deadline_data *dd, struct dd_per_prio *per_prio,
-                     struct request *rq)
-{
-       const enum dd_data_dir data_dir = rq_data_dir(rq);
-
-       per_prio->next_rq[data_dir] = deadline_latter_request(rq);
-
-       /*
-        * take it off the sort and fifo list
-        */
-       deadline_remove_request(rq->q, per_prio, rq);
-}
-
-/* Number of requests queued for a given priority level. */
-static u32 dd_queued(struct deadline_data *dd, enum dd_prio prio)
-{
-       return dd_sum(dd, inserted, prio) - dd_sum(dd, completed, prio);
-}
-
-/*
- * deadline_check_fifo returns 0 if there are no expired requests on the fifo,
- * 1 otherwise. Requires !list_empty(&dd->fifo_list[data_dir])
- */
-static inline int deadline_check_fifo(struct dd_per_prio *per_prio,
-                                     enum dd_data_dir data_dir)
-{
-       struct request *rq = rq_entry_fifo(per_prio->fifo_list[data_dir].next);
-
-       /*
-        * rq is expired!
-        */
-       if (time_after_eq(jiffies, (unsigned long)rq->fifo_time))
-               return 1;
-
-       return 0;
-}
-
-/*
- * For the specified data direction, return the next request to
- * dispatch using arrival ordered lists.
- */
-static struct request *
-deadline_fifo_request(struct deadline_data *dd, struct dd_per_prio *per_prio,
-                     enum dd_data_dir data_dir)
-{
-       struct request *rq;
-       unsigned long flags;
-
-       if (list_empty(&per_prio->fifo_list[data_dir]))
-               return NULL;
-
-       rq = rq_entry_fifo(per_prio->fifo_list[data_dir].next);
-       if (data_dir == DD_READ || !blk_queue_is_zoned(rq->q))
-               return rq;
-
-       /*
-        * Look for a write request that can be dispatched, that is one with
-        * an unlocked target zone.
-        */
-       spin_lock_irqsave(&dd->zone_lock, flags);
-       list_for_each_entry(rq, &per_prio->fifo_list[DD_WRITE], queuelist) {
-               if (blk_req_can_dispatch_to_zone(rq))
-                       goto out;
-       }
-       rq = NULL;
-out:
-       spin_unlock_irqrestore(&dd->zone_lock, flags);
-
-       return rq;
-}
-
-/*
- * For the specified data direction, return the next request to
- * dispatch using sector position sorted lists.
- */
-static struct request *
-deadline_next_request(struct deadline_data *dd, struct dd_per_prio *per_prio,
-                     enum dd_data_dir data_dir)
-{
-       struct request *rq;
-       unsigned long flags;
-
-       rq = per_prio->next_rq[data_dir];
-       if (!rq)
-               return NULL;
-
-       if (data_dir == DD_READ || !blk_queue_is_zoned(rq->q))
-               return rq;
-
-       /*
-        * Look for a write request that can be dispatched, that is one with
-        * an unlocked target zone.
-        */
-       spin_lock_irqsave(&dd->zone_lock, flags);
-       while (rq) {
-               if (blk_req_can_dispatch_to_zone(rq))
-                       break;
-               rq = deadline_latter_request(rq);
-       }
-       spin_unlock_irqrestore(&dd->zone_lock, flags);
-
-       return rq;
-}
-
-/*
- * deadline_dispatch_requests selects the best request according to
- * read/write expire, fifo_batch, etc and with a start time <= @latest.
- */
-static struct request *__dd_dispatch_request(struct deadline_data *dd,
-                                            struct dd_per_prio *per_prio,
-                                            u64 latest_start_ns)
-{
-       struct request *rq, *next_rq;
-       enum dd_data_dir data_dir;
-       struct dd_blkcg *blkcg;
-       enum dd_prio prio;
-       u8 ioprio_class;
-
-       lockdep_assert_held(&dd->lock);
-
-       if (!list_empty(&per_prio->dispatch)) {
-               rq = list_first_entry(&per_prio->dispatch, struct request,
-                                     queuelist);
-               if (rq->start_time_ns > latest_start_ns)
-                       return NULL;
-               list_del_init(&rq->queuelist);
-               goto done;
-       }
-
-       /*
-        * batches are currently reads XOR writes
-        */
-       rq = deadline_next_request(dd, per_prio, dd->last_dir);
-       if (rq && dd->batching < dd->fifo_batch)
-               /* we have a next request are still entitled to batch */
-               goto dispatch_request;
-
-       /*
-        * at this point we are not running a batch. select the appropriate
-        * data direction (read / write)
-        */
-
-       if (!list_empty(&per_prio->fifo_list[DD_READ])) {
-               BUG_ON(RB_EMPTY_ROOT(&per_prio->sort_list[DD_READ]));
-
-               if (deadline_fifo_request(dd, per_prio, DD_WRITE) &&
-                   (dd->starved++ >= dd->writes_starved))
-                       goto dispatch_writes;
-
-               data_dir = DD_READ;
-
-               goto dispatch_find_request;
-       }
-
-       /*
-        * there are either no reads or writes have been starved
-        */
-
-       if (!list_empty(&per_prio->fifo_list[DD_WRITE])) {
-dispatch_writes:
-               BUG_ON(RB_EMPTY_ROOT(&per_prio->sort_list[DD_WRITE]));
-
-               dd->starved = 0;
-
-               data_dir = DD_WRITE;
-
-               goto dispatch_find_request;
-       }
-
-       return NULL;
-
-dispatch_find_request:
-       /*
-        * we are not running a batch, find best request for selected data_dir
-        */
-       next_rq = deadline_next_request(dd, per_prio, data_dir);
-       if (deadline_check_fifo(per_prio, data_dir) || !next_rq) {
-               /*
-                * A deadline has expired, the last request was in the other
-                * direction, or we have run out of higher-sectored requests.
-                * Start again from the request with the earliest expiry time.
-                */
-               rq = deadline_fifo_request(dd, per_prio, data_dir);
-       } else {
-               /*
-                * The last req was the same dir and we have a next request in
-                * sort order. No expired requests so continue on from here.
-                */
-               rq = next_rq;
-       }
-
-       /*
-        * For a zoned block device, if we only have writes queued and none of
-        * them can be dispatched, rq will be NULL.
-        */
-       if (!rq)
-               return NULL;
-
-       dd->last_dir = data_dir;
-       dd->batching = 0;
-
-dispatch_request:
-       if (rq->start_time_ns > latest_start_ns)
-               return NULL;
-       /*
-        * rq is the selected appropriate request.
-        */
-       dd->batching++;
-       deadline_move_request(dd, per_prio, rq);
-done:
-       ioprio_class = dd_rq_ioclass(rq);
-       prio = ioprio_class_to_prio[ioprio_class];
-       dd_count(dd, dispatched, prio);
-       blkcg = rq->elv.priv[0];
-       ddcg_count(blkcg, dispatched, ioprio_class);
-       /*
-        * If the request needs its target zone locked, do it.
-        */
-       blk_req_zone_write_lock(rq);
-       rq->rq_flags |= RQF_STARTED;
-       return rq;
-}
-
-/*
- * Called from blk_mq_run_hw_queue() -> __blk_mq_sched_dispatch_requests().
- *
- * One confusing aspect here is that we get called for a specific
- * hardware queue, but we may return a request that is for a
- * different hardware queue. This is because mq-deadline has shared
- * state for all hardware queues, in terms of sorting, FIFOs, etc.
- */
-static struct request *dd_dispatch_request(struct blk_mq_hw_ctx *hctx)
-{
-       struct deadline_data *dd = hctx->queue->elevator->elevator_data;
-       const u64 now_ns = ktime_get_ns();
-       struct request *rq = NULL;
-       enum dd_prio prio;
-
-       spin_lock(&dd->lock);
-       /*
-        * Start with dispatching requests whose deadline expired more than
-        * aging_expire jiffies ago.
-        */
-       for (prio = DD_BE_PRIO; prio <= DD_PRIO_MAX; prio++) {
-               rq = __dd_dispatch_request(dd, &dd->per_prio[prio], now_ns -
-                                          jiffies_to_nsecs(dd->aging_expire));
-               if (rq)
-                       goto unlock;
-       }
-       /*
-        * Next, dispatch requests in priority order. Ignore lower priority
-        * requests if any higher priority requests are pending.
-        */
-       for (prio = 0; prio <= DD_PRIO_MAX; prio++) {
-               rq = __dd_dispatch_request(dd, &dd->per_prio[prio], now_ns);
-               if (rq || dd_queued(dd, prio))
-                       break;
-       }
-
-unlock:
-       spin_unlock(&dd->lock);
-
-       return rq;
-}
-
-/*
- * Called by __blk_mq_alloc_request(). The shallow_depth value set by this
- * function is used by __blk_mq_get_tag().
- */
-static void dd_limit_depth(unsigned int op, struct blk_mq_alloc_data *data)
-{
-       struct deadline_data *dd = data->q->elevator->elevator_data;
-
-       /* Do not throttle synchronous reads. */
-       if (op_is_sync(op) && !op_is_write(op))
-               return;
-
-       /*
-        * Throttle asynchronous requests and writes such that these requests
-        * do not block the allocation of synchronous requests.
-        */
-       data->shallow_depth = dd->async_depth;
-}
-
-/* Called by blk_mq_update_nr_requests(). */
-static void dd_depth_updated(struct blk_mq_hw_ctx *hctx)
-{
-       struct request_queue *q = hctx->queue;
-       struct deadline_data *dd = q->elevator->elevator_data;
-       struct blk_mq_tags *tags = hctx->sched_tags;
-
-       dd->async_depth = max(1UL, 3 * q->nr_requests / 4);
-
-       sbitmap_queue_min_shallow_depth(tags->bitmap_tags, dd->async_depth);
-}
-
-/* Called by blk_mq_init_hctx() and blk_mq_init_sched(). */
-static int dd_init_hctx(struct blk_mq_hw_ctx *hctx, unsigned int hctx_idx)
-{
-       dd_depth_updated(hctx);
-       return 0;
-}
-
-static void dd_exit_sched(struct elevator_queue *e)
-{
-       struct deadline_data *dd = e->elevator_data;
-       enum dd_prio prio;
-
-       dd_deactivate_policy(dd->queue);
-
-       for (prio = 0; prio <= DD_PRIO_MAX; prio++) {
-               struct dd_per_prio *per_prio = &dd->per_prio[prio];
-
-               WARN_ON_ONCE(!list_empty(&per_prio->fifo_list[DD_READ]));
-               WARN_ON_ONCE(!list_empty(&per_prio->fifo_list[DD_WRITE]));
-       }
-
-       free_percpu(dd->stats);
-
-       kfree(dd);
-}
-
-/*
- * Initialize elevator private data (deadline_data) and associate with blkcg.
- */
-static int dd_init_sched(struct request_queue *q, struct elevator_type *e)
-{
-       struct deadline_data *dd;
-       struct elevator_queue *eq;
-       enum dd_prio prio;
-       int ret = -ENOMEM;
-
-       /*
-        * Initialization would be very tricky if the queue is not frozen,
-        * hence the warning statement below.
-        */
-       WARN_ON_ONCE(!percpu_ref_is_zero(&q->q_usage_counter));
-
-       eq = elevator_alloc(q, e);
-       if (!eq)
-               return ret;
-
-       dd = kzalloc_node(sizeof(*dd), GFP_KERNEL, q->node);
-       if (!dd)
-               goto put_eq;
-
-       eq->elevator_data = dd;
-
-       dd->stats = alloc_percpu_gfp(typeof(*dd->stats),
-                                    GFP_KERNEL | __GFP_ZERO);
-       if (!dd->stats)
-               goto free_dd;
-
-       dd->queue = q;
-
-       for (prio = 0; prio <= DD_PRIO_MAX; prio++) {
-               struct dd_per_prio *per_prio = &dd->per_prio[prio];
-
-               INIT_LIST_HEAD(&per_prio->dispatch);
-               INIT_LIST_HEAD(&per_prio->fifo_list[DD_READ]);
-               INIT_LIST_HEAD(&per_prio->fifo_list[DD_WRITE]);
-               per_prio->sort_list[DD_READ] = RB_ROOT;
-               per_prio->sort_list[DD_WRITE] = RB_ROOT;
-       }
-       dd->fifo_expire[DD_READ] = read_expire;
-       dd->fifo_expire[DD_WRITE] = write_expire;
-       dd->writes_starved = writes_starved;
-       dd->front_merges = 1;
-       dd->last_dir = DD_WRITE;
-       dd->fifo_batch = fifo_batch;
-       dd->aging_expire = aging_expire;
-       spin_lock_init(&dd->lock);
-       spin_lock_init(&dd->zone_lock);
-
-       ret = dd_activate_policy(q);
-       if (ret)
-               goto free_stats;
-
-       ret = 0;
-       q->elevator = eq;
-       return 0;
-
-free_stats:
-       free_percpu(dd->stats);
-
-free_dd:
-       kfree(dd);
-
-put_eq:
-       kobject_put(&eq->kobj);
-       return ret;
-}
-
-/*
- * Try to merge @bio into an existing request. If @bio has been merged into
- * an existing request, store the pointer to that request into *@rq.
- */
-static int dd_request_merge(struct request_queue *q, struct request **rq,
-                           struct bio *bio)
-{
-       struct deadline_data *dd = q->elevator->elevator_data;
-       const u8 ioprio_class = IOPRIO_PRIO_CLASS(bio->bi_ioprio);
-       const enum dd_prio prio = ioprio_class_to_prio[ioprio_class];
-       struct dd_per_prio *per_prio = &dd->per_prio[prio];
-       sector_t sector = bio_end_sector(bio);
-       struct request *__rq;
-
-       if (!dd->front_merges)
-               return ELEVATOR_NO_MERGE;
-
-       __rq = elv_rb_find(&per_prio->sort_list[bio_data_dir(bio)], sector);
-       if (__rq) {
-               BUG_ON(sector != blk_rq_pos(__rq));
-
-               if (elv_bio_merge_ok(__rq, bio)) {
-                       *rq = __rq;
-                       return ELEVATOR_FRONT_MERGE;
-               }
-       }
-
-       return ELEVATOR_NO_MERGE;
-}
-
-/*
- * Attempt to merge a bio into an existing request. This function is called
- * before @bio is associated with a request.
- */
-static bool dd_bio_merge(struct request_queue *q, struct bio *bio,
-               unsigned int nr_segs)
-{
-       struct deadline_data *dd = q->elevator->elevator_data;
-       struct request *free = NULL;
-       bool ret;
-
-       spin_lock(&dd->lock);
-       ret = blk_mq_sched_try_merge(q, bio, nr_segs, &free);
-       spin_unlock(&dd->lock);
-
-       if (free)
-               blk_mq_free_request(free);
-
-       return ret;
-}
-
-/*
- * add rq to rbtree and fifo
- */
-static void dd_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
-                             bool at_head)
-{
-       struct request_queue *q = hctx->queue;
-       struct deadline_data *dd = q->elevator->elevator_data;
-       const enum dd_data_dir data_dir = rq_data_dir(rq);
-       u16 ioprio = req_get_ioprio(rq);
-       u8 ioprio_class = IOPRIO_PRIO_CLASS(ioprio);
-       struct dd_per_prio *per_prio;
-       enum dd_prio prio;
-       struct dd_blkcg *blkcg;
-       LIST_HEAD(free);
-
-       lockdep_assert_held(&dd->lock);
-
-       /*
-        * This may be a requeue of a write request that has locked its
-        * target zone. If it is the case, this releases the zone lock.
-        */
-       blk_req_zone_write_unlock(rq);
-
-       /*
-        * If a block cgroup has been associated with the submitter and if an
-        * I/O priority has been set in the associated block cgroup, use the
-        * lowest of the cgroup priority and the request priority for the
-        * request. If no priority has been set in the request, use the cgroup
-        * priority.
-        */
-       prio = ioprio_class_to_prio[ioprio_class];
-       dd_count(dd, inserted, prio);
-       blkcg = dd_blkcg_from_bio(rq->bio);
-       ddcg_count(blkcg, inserted, ioprio_class);
-       rq->elv.priv[0] = blkcg;
-
-       if (blk_mq_sched_try_insert_merge(q, rq, &free)) {
-               blk_mq_free_requests(&free);
-               return;
-       }
-
-       trace_block_rq_insert(rq);
-
-       per_prio = &dd->per_prio[prio];
-       if (at_head) {
-               list_add(&rq->queuelist, &per_prio->dispatch);
-       } else {
-               deadline_add_rq_rb(per_prio, rq);
-
-               if (rq_mergeable(rq)) {
-                       elv_rqhash_add(q, rq);
-                       if (!q->last_merge)
-                               q->last_merge = rq;
-               }
-
-               /*
-                * set expire time and add to fifo list
-                */
-               rq->fifo_time = jiffies + dd->fifo_expire[data_dir];
-               list_add_tail(&rq->queuelist, &per_prio->fifo_list[data_dir]);
-       }
-}
-
-/*
- * Called from blk_mq_sched_insert_request() or blk_mq_sched_insert_requests().
- */
-static void dd_insert_requests(struct blk_mq_hw_ctx *hctx,
-                              struct list_head *list, bool at_head)
-{
-       struct request_queue *q = hctx->queue;
-       struct deadline_data *dd = q->elevator->elevator_data;
-
-       spin_lock(&dd->lock);
-       while (!list_empty(list)) {
-               struct request *rq;
-
-               rq = list_first_entry(list, struct request, queuelist);
-               list_del_init(&rq->queuelist);
-               dd_insert_request(hctx, rq, at_head);
-       }
-       spin_unlock(&dd->lock);
-}
-
-/* Callback from inside blk_mq_rq_ctx_init(). */
-static void dd_prepare_request(struct request *rq)
-{
-       rq->elv.priv[0] = NULL;
-}
-
-/*
- * Callback from inside blk_mq_free_request().
- *
- * For zoned block devices, write unlock the target zone of
- * completed write requests. Do this while holding the zone lock
- * spinlock so that the zone is never unlocked while deadline_fifo_request()
- * or deadline_next_request() are executing. This function is called for
- * all requests, whether or not these requests complete successfully.
- *
- * For a zoned block device, __dd_dispatch_request() may have stopped
- * dispatching requests if all the queued requests are write requests directed
- * at zones that are already locked due to on-going write requests. To ensure
- * write request dispatch progress in this case, mark the queue as needing a
- * restart to ensure that the queue is run again after completion of the
- * request and zones being unlocked.
- */
-static void dd_finish_request(struct request *rq)
-{
-       struct request_queue *q = rq->q;
-       struct deadline_data *dd = q->elevator->elevator_data;
-       struct dd_blkcg *blkcg = rq->elv.priv[0];
-       const u8 ioprio_class = dd_rq_ioclass(rq);
-       const enum dd_prio prio = ioprio_class_to_prio[ioprio_class];
-       struct dd_per_prio *per_prio = &dd->per_prio[prio];
-
-       dd_count(dd, completed, prio);
-       ddcg_count(blkcg, completed, ioprio_class);
-
-       if (blk_queue_is_zoned(q)) {
-               unsigned long flags;
-
-               spin_lock_irqsave(&dd->zone_lock, flags);
-               blk_req_zone_write_unlock(rq);
-               if (!list_empty(&per_prio->fifo_list[DD_WRITE]))
-                       blk_mq_sched_mark_restart_hctx(rq->mq_hctx);
-               spin_unlock_irqrestore(&dd->zone_lock, flags);
-       }
-}
-
-static bool dd_has_work_for_prio(struct dd_per_prio *per_prio)
-{
-       return !list_empty_careful(&per_prio->dispatch) ||
-               !list_empty_careful(&per_prio->fifo_list[DD_READ]) ||
-               !list_empty_careful(&per_prio->fifo_list[DD_WRITE]);
-}
-
-static bool dd_has_work(struct blk_mq_hw_ctx *hctx)
-{
-       struct deadline_data *dd = hctx->queue->elevator->elevator_data;
-       enum dd_prio prio;
-
-       for (prio = 0; prio <= DD_PRIO_MAX; prio++)
-               if (dd_has_work_for_prio(&dd->per_prio[prio]))
-                       return true;
-
-       return false;
-}
-
-/*
- * sysfs parts below
- */
-#define SHOW_INT(__FUNC, __VAR)                                                \
-static ssize_t __FUNC(struct elevator_queue *e, char *page)            \
-{                                                                      \
-       struct deadline_data *dd = e->elevator_data;                    \
-                                                                       \
-       return sysfs_emit(page, "%d\n", __VAR);                         \
-}
-#define SHOW_JIFFIES(__FUNC, __VAR) SHOW_INT(__FUNC, jiffies_to_msecs(__VAR))
-SHOW_JIFFIES(deadline_read_expire_show, dd->fifo_expire[DD_READ]);
-SHOW_JIFFIES(deadline_write_expire_show, dd->fifo_expire[DD_WRITE]);
-SHOW_JIFFIES(deadline_aging_expire_show, dd->aging_expire);
-SHOW_INT(deadline_writes_starved_show, dd->writes_starved);
-SHOW_INT(deadline_front_merges_show, dd->front_merges);
-SHOW_INT(deadline_async_depth_show, dd->front_merges);
-SHOW_INT(deadline_fifo_batch_show, dd->fifo_batch);
-#undef SHOW_INT
-#undef SHOW_JIFFIES
-
-#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV)                        \
-static ssize_t __FUNC(struct elevator_queue *e, const char *page, size_t count)        \
-{                                                                      \
-       struct deadline_data *dd = e->elevator_data;                    \
-       int __data, __ret;                                              \
-                                                                       \
-       __ret = kstrtoint(page, 0, &__data);                            \
-       if (__ret < 0)                                                  \
-               return __ret;                                           \
-       if (__data < (MIN))                                             \
-               __data = (MIN);                                         \
-       else if (__data > (MAX))                                        \
-               __data = (MAX);                                         \
-       *(__PTR) = __CONV(__data);                                      \
-       return count;                                                   \
-}
-#define STORE_INT(__FUNC, __PTR, MIN, MAX)                             \
-       STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, )
-#define STORE_JIFFIES(__FUNC, __PTR, MIN, MAX)                         \
-       STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, msecs_to_jiffies)
-STORE_JIFFIES(deadline_read_expire_store, &dd->fifo_expire[DD_READ], 0, INT_MAX);
-STORE_JIFFIES(deadline_write_expire_store, &dd->fifo_expire[DD_WRITE], 0, INT_MAX);
-STORE_JIFFIES(deadline_aging_expire_store, &dd->aging_expire, 0, INT_MAX);
-STORE_INT(deadline_writes_starved_store, &dd->writes_starved, INT_MIN, INT_MAX);
-STORE_INT(deadline_front_merges_store, &dd->front_merges, 0, 1);
-STORE_INT(deadline_async_depth_store, &dd->front_merges, 1, INT_MAX);
-STORE_INT(deadline_fifo_batch_store, &dd->fifo_batch, 0, INT_MAX);
-#undef STORE_FUNCTION
-#undef STORE_INT
-#undef STORE_JIFFIES
-
-#define DD_ATTR(name) \
-       __ATTR(name, 0644, deadline_##name##_show, deadline_##name##_store)
-
-static struct elv_fs_entry deadline_attrs[] = {
-       DD_ATTR(read_expire),
-       DD_ATTR(write_expire),
-       DD_ATTR(writes_starved),
-       DD_ATTR(front_merges),
-       DD_ATTR(async_depth),
-       DD_ATTR(fifo_batch),
-       DD_ATTR(aging_expire),
-       __ATTR_NULL
-};
-
-#ifdef CONFIG_BLK_DEBUG_FS
-#define DEADLINE_DEBUGFS_DDIR_ATTRS(prio, data_dir, name)              \
-static void *deadline_##name##_fifo_start(struct seq_file *m,          \
-                                         loff_t *pos)                  \
-       __acquires(&dd->lock)                                           \
-{                                                                      \
-       struct request_queue *q = m->private;                           \
-       struct deadline_data *dd = q->elevator->elevator_data;          \
-       struct dd_per_prio *per_prio = &dd->per_prio[prio];             \
-                                                                       \
-       spin_lock(&dd->lock);                                           \
-       return seq_list_start(&per_prio->fifo_list[data_dir], *pos);    \
-}                                                                      \
-                                                                       \
-static void *deadline_##name##_fifo_next(struct seq_file *m, void *v,  \
-                                        loff_t *pos)                   \
-{                                                                      \
-       struct request_queue *q = m->private;                           \
-       struct deadline_data *dd = q->elevator->elevator_data;          \
-       struct dd_per_prio *per_prio = &dd->per_prio[prio];             \
-                                                                       \
-       return seq_list_next(v, &per_prio->fifo_list[data_dir], pos);   \
-}                                                                      \
-                                                                       \
-static void deadline_##name##_fifo_stop(struct seq_file *m, void *v)   \
-       __releases(&dd->lock)                                           \
-{                                                                      \
-       struct request_queue *q = m->private;                           \
-       struct deadline_data *dd = q->elevator->elevator_data;          \
-                                                                       \
-       spin_unlock(&dd->lock);                                         \
-}                                                                      \
-                                                                       \
-static const struct seq_operations deadline_##name##_fifo_seq_ops = {  \
-       .start  = deadline_##name##_fifo_start,                         \
-       .next   = deadline_##name##_fifo_next,                          \
-       .stop   = deadline_##name##_fifo_stop,                          \
-       .show   = blk_mq_debugfs_rq_show,                               \
-};                                                                     \
-                                                                       \
-static int deadline_##name##_next_rq_show(void *data,                  \
-                                         struct seq_file *m)           \
-{                                                                      \
-       struct request_queue *q = data;                                 \
-       struct deadline_data *dd = q->elevator->elevator_data;          \
-       struct dd_per_prio *per_prio = &dd->per_prio[prio];             \
-       struct request *rq = per_prio->next_rq[data_dir];               \
-                                                                       \
-       if (rq)                                                         \
-               __blk_mq_debugfs_rq_show(m, rq);                        \
-       return 0;                                                       \
-}
-
-DEADLINE_DEBUGFS_DDIR_ATTRS(DD_RT_PRIO, DD_READ, read0);
-DEADLINE_DEBUGFS_DDIR_ATTRS(DD_RT_PRIO, DD_WRITE, write0);
-DEADLINE_DEBUGFS_DDIR_ATTRS(DD_BE_PRIO, DD_READ, read1);
-DEADLINE_DEBUGFS_DDIR_ATTRS(DD_BE_PRIO, DD_WRITE, write1);
-DEADLINE_DEBUGFS_DDIR_ATTRS(DD_IDLE_PRIO, DD_READ, read2);
-DEADLINE_DEBUGFS_DDIR_ATTRS(DD_IDLE_PRIO, DD_WRITE, write2);
-#undef DEADLINE_DEBUGFS_DDIR_ATTRS
-
-static int deadline_batching_show(void *data, struct seq_file *m)
-{
-       struct request_queue *q = data;
-       struct deadline_data *dd = q->elevator->elevator_data;
-
-       seq_printf(m, "%u\n", dd->batching);
-       return 0;
-}
-
-static int deadline_starved_show(void *data, struct seq_file *m)
-{
-       struct request_queue *q = data;
-       struct deadline_data *dd = q->elevator->elevator_data;
-
-       seq_printf(m, "%u\n", dd->starved);
-       return 0;
-}
-
-static int dd_async_depth_show(void *data, struct seq_file *m)
-{
-       struct request_queue *q = data;
-       struct deadline_data *dd = q->elevator->elevator_data;
-
-       seq_printf(m, "%u\n", dd->async_depth);
-       return 0;
-}
-
-static int dd_queued_show(void *data, struct seq_file *m)
-{
-       struct request_queue *q = data;
-       struct deadline_data *dd = q->elevator->elevator_data;
-
-       seq_printf(m, "%u %u %u\n", dd_queued(dd, DD_RT_PRIO),
-                  dd_queued(dd, DD_BE_PRIO),
-                  dd_queued(dd, DD_IDLE_PRIO));
-       return 0;
-}
-
-/* Number of requests owned by the block driver for a given priority. */
-static u32 dd_owned_by_driver(struct deadline_data *dd, enum dd_prio prio)
-{
-       return dd_sum(dd, dispatched, prio) + dd_sum(dd, merged, prio)
-               - dd_sum(dd, completed, prio);
-}
-
-static int dd_owned_by_driver_show(void *data, struct seq_file *m)
-{
-       struct request_queue *q = data;
-       struct deadline_data *dd = q->elevator->elevator_data;
-
-       seq_printf(m, "%u %u %u\n", dd_owned_by_driver(dd, DD_RT_PRIO),
-                  dd_owned_by_driver(dd, DD_BE_PRIO),
-                  dd_owned_by_driver(dd, DD_IDLE_PRIO));
-       return 0;
-}
-
-#define DEADLINE_DISPATCH_ATTR(prio)                                   \
-static void *deadline_dispatch##prio##_start(struct seq_file *m,       \
-                                            loff_t *pos)               \
-       __acquires(&dd->lock)                                           \
-{                                                                      \
-       struct request_queue *q = m->private;                           \
-       struct deadline_data *dd = q->elevator->elevator_data;          \
-       struct dd_per_prio *per_prio = &dd->per_prio[prio];             \
-                                                                       \
-       spin_lock(&dd->lock);                                           \
-       return seq_list_start(&per_prio->dispatch, *pos);               \
-}                                                                      \
-                                                                       \
-static void *deadline_dispatch##prio##_next(struct seq_file *m,                \
-                                           void *v, loff_t *pos)       \
-{                                                                      \
-       struct request_queue *q = m->private;                           \
-       struct deadline_data *dd = q->elevator->elevator_data;          \
-       struct dd_per_prio *per_prio = &dd->per_prio[prio];             \
-                                                                       \
-       return seq_list_next(v, &per_prio->dispatch, pos);              \
-}                                                                      \
-                                                                       \
-static void deadline_dispatch##prio##_stop(struct seq_file *m, void *v)        \
-       __releases(&dd->lock)                                           \
-{                                                                      \
-       struct request_queue *q = m->private;                           \
-       struct deadline_data *dd = q->elevator->elevator_data;          \
-                                                                       \
-       spin_unlock(&dd->lock);                                         \
-}                                                                      \
-                                                                       \
-static const struct seq_operations deadline_dispatch##prio##_seq_ops = { \
-       .start  = deadline_dispatch##prio##_start,                      \
-       .next   = deadline_dispatch##prio##_next,                       \
-       .stop   = deadline_dispatch##prio##_stop,                       \
-       .show   = blk_mq_debugfs_rq_show,                               \
-}
-
-DEADLINE_DISPATCH_ATTR(0);
-DEADLINE_DISPATCH_ATTR(1);
-DEADLINE_DISPATCH_ATTR(2);
-#undef DEADLINE_DISPATCH_ATTR
-
-#define DEADLINE_QUEUE_DDIR_ATTRS(name)                                        \
-       {#name "_fifo_list", 0400,                                      \
-                       .seq_ops = &deadline_##name##_fifo_seq_ops}
-#define DEADLINE_NEXT_RQ_ATTR(name)                                    \
-       {#name "_next_rq", 0400, deadline_##name##_next_rq_show}
-static const struct blk_mq_debugfs_attr deadline_queue_debugfs_attrs[] = {
-       DEADLINE_QUEUE_DDIR_ATTRS(read0),
-       DEADLINE_QUEUE_DDIR_ATTRS(write0),
-       DEADLINE_QUEUE_DDIR_ATTRS(read1),
-       DEADLINE_QUEUE_DDIR_ATTRS(write1),
-       DEADLINE_QUEUE_DDIR_ATTRS(read2),
-       DEADLINE_QUEUE_DDIR_ATTRS(write2),
-       DEADLINE_NEXT_RQ_ATTR(read0),
-       DEADLINE_NEXT_RQ_ATTR(write0),
-       DEADLINE_NEXT_RQ_ATTR(read1),
-       DEADLINE_NEXT_RQ_ATTR(write1),
-       DEADLINE_NEXT_RQ_ATTR(read2),
-       DEADLINE_NEXT_RQ_ATTR(write2),
-       {"batching", 0400, deadline_batching_show},
-       {"starved", 0400, deadline_starved_show},
-       {"async_depth", 0400, dd_async_depth_show},
-       {"dispatch0", 0400, .seq_ops = &deadline_dispatch0_seq_ops},
-       {"dispatch1", 0400, .seq_ops = &deadline_dispatch1_seq_ops},
-       {"dispatch2", 0400, .seq_ops = &deadline_dispatch2_seq_ops},
-       {"owned_by_driver", 0400, dd_owned_by_driver_show},
-       {"queued", 0400, dd_queued_show},
-       {},
-};
-#undef DEADLINE_QUEUE_DDIR_ATTRS
-#endif
-
-static struct elevator_type mq_deadline = {
-       .ops = {
-               .depth_updated          = dd_depth_updated,
-               .limit_depth            = dd_limit_depth,
-               .insert_requests        = dd_insert_requests,
-               .dispatch_request       = dd_dispatch_request,
-               .prepare_request        = dd_prepare_request,
-               .finish_request         = dd_finish_request,
-               .next_request           = elv_rb_latter_request,
-               .former_request         = elv_rb_former_request,
-               .bio_merge              = dd_bio_merge,
-               .request_merge          = dd_request_merge,
-               .requests_merged        = dd_merged_requests,
-               .request_merged         = dd_request_merged,
-               .has_work               = dd_has_work,
-               .init_sched             = dd_init_sched,
-               .exit_sched             = dd_exit_sched,
-               .init_hctx              = dd_init_hctx,
-       },
-
-#ifdef CONFIG_BLK_DEBUG_FS
-       .queue_debugfs_attrs = deadline_queue_debugfs_attrs,
-#endif
-       .elevator_attrs = deadline_attrs,
-       .elevator_name = "mq-deadline",
-       .elevator_alias = "deadline",
-       .elevator_features = ELEVATOR_F_ZBD_SEQ_WRITE,
-       .elevator_owner = THIS_MODULE,
-};
-MODULE_ALIAS("mq-deadline-iosched");
-
-static int __init deadline_init(void)
-{
-       int ret;
-
-       ret = elv_register(&mq_deadline);
-       if (ret)
-               goto out;
-       ret = dd_blkcg_init();
-       if (ret)
-               goto unreg;
-
-out:
-       return ret;
-
-unreg:
-       elv_unregister(&mq_deadline);
-       goto out;
-}
-
-static void __exit deadline_exit(void)
-{
-       dd_blkcg_exit();
-       elv_unregister(&mq_deadline);
-}
-
-module_init(deadline_init);
-module_exit(deadline_exit);
-
-MODULE_AUTHOR("Jens Axboe, Damien Le Moal and Bart Van Assche");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("MQ deadline IO scheduler");
diff --git a/block/mq-deadline.c b/block/mq-deadline.c
new file mode 100644 (file)
index 0000000..a09761c
--- /dev/null
@@ -0,0 +1,1130 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  MQ Deadline i/o scheduler - adaptation of the legacy deadline scheduler,
+ *  for the blk-mq scheduling framework
+ *
+ *  Copyright (C) 2016 Jens Axboe <axboe@kernel.dk>
+ */
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
+#include <linux/elevator.h>
+#include <linux/bio.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/compiler.h>
+#include <linux/rbtree.h>
+#include <linux/sbitmap.h>
+
+#include <trace/events/block.h>
+
+#include "blk.h"
+#include "blk-mq.h"
+#include "blk-mq-debugfs.h"
+#include "blk-mq-tag.h"
+#include "blk-mq-sched.h"
+
+/*
+ * See Documentation/block/deadline-iosched.rst
+ */
+static const int read_expire = HZ / 2;  /* max time before a read is submitted. */
+static const int write_expire = 5 * HZ; /* ditto for writes, these limits are SOFT! */
+/*
+ * Time after which to dispatch lower priority requests even if higher
+ * priority requests are pending.
+ */
+static const int aging_expire = 10 * HZ;
+static const int writes_starved = 2;    /* max times reads can starve a write */
+static const int fifo_batch = 16;       /* # of sequential requests treated as one
+                                    by the above parameters. For throughput. */
+
+enum dd_data_dir {
+       DD_READ         = READ,
+       DD_WRITE        = WRITE,
+};
+
+enum { DD_DIR_COUNT = 2 };
+
+enum dd_prio {
+       DD_RT_PRIO      = 0,
+       DD_BE_PRIO      = 1,
+       DD_IDLE_PRIO    = 2,
+       DD_PRIO_MAX     = 2,
+};
+
+enum { DD_PRIO_COUNT = 3 };
+
+/* I/O statistics per I/O priority. */
+struct io_stats_per_prio {
+       local_t inserted;
+       local_t merged;
+       local_t dispatched;
+       local_t completed;
+};
+
+/* I/O statistics for all I/O priorities (enum dd_prio). */
+struct io_stats {
+       struct io_stats_per_prio stats[DD_PRIO_COUNT];
+};
+
+/*
+ * Deadline scheduler data per I/O priority (enum dd_prio). Requests are
+ * present on both sort_list[] and fifo_list[].
+ */
+struct dd_per_prio {
+       struct list_head dispatch;
+       struct rb_root sort_list[DD_DIR_COUNT];
+       struct list_head fifo_list[DD_DIR_COUNT];
+       /* Next request in FIFO order. Read, write or both are NULL. */
+       struct request *next_rq[DD_DIR_COUNT];
+};
+
+struct deadline_data {
+       /*
+        * run time data
+        */
+
+       struct dd_per_prio per_prio[DD_PRIO_COUNT];
+
+       /* Data direction of latest dispatched request. */
+       enum dd_data_dir last_dir;
+       unsigned int batching;          /* number of sequential requests made */
+       unsigned int starved;           /* times reads have starved writes */
+
+       struct io_stats __percpu *stats;
+
+       /*
+        * settings that change how the i/o scheduler behaves
+        */
+       int fifo_expire[DD_DIR_COUNT];
+       int fifo_batch;
+       int writes_starved;
+       int front_merges;
+       u32 async_depth;
+       int aging_expire;
+
+       spinlock_t lock;
+       spinlock_t zone_lock;
+};
+
+/* Count one event of type 'event_type' and with I/O priority 'prio' */
+#define dd_count(dd, event_type, prio) do {                            \
+       struct io_stats *io_stats = get_cpu_ptr((dd)->stats);           \
+                                                                       \
+       BUILD_BUG_ON(!__same_type((dd), struct deadline_data *));       \
+       BUILD_BUG_ON(!__same_type((prio), enum dd_prio));               \
+       local_inc(&io_stats->stats[(prio)].event_type);                 \
+       put_cpu_ptr(io_stats);                                          \
+} while (0)
+
+/*
+ * Returns the total number of dd_count(dd, event_type, prio) calls across all
+ * CPUs. No locking or barriers since it is fine if the returned sum is slightly
+ * outdated.
+ */
+#define dd_sum(dd, event_type, prio) ({                                        \
+       unsigned int cpu;                                               \
+       u32 sum = 0;                                                    \
+                                                                       \
+       BUILD_BUG_ON(!__same_type((dd), struct deadline_data *));       \
+       BUILD_BUG_ON(!__same_type((prio), enum dd_prio));               \
+       for_each_present_cpu(cpu)                                       \
+               sum += local_read(&per_cpu_ptr((dd)->stats, cpu)->      \
+                                 stats[(prio)].event_type);            \
+       sum;                                                            \
+})
+
+/* Maps an I/O priority class to a deadline scheduler priority. */
+static const enum dd_prio ioprio_class_to_prio[] = {
+       [IOPRIO_CLASS_NONE]     = DD_BE_PRIO,
+       [IOPRIO_CLASS_RT]       = DD_RT_PRIO,
+       [IOPRIO_CLASS_BE]       = DD_BE_PRIO,
+       [IOPRIO_CLASS_IDLE]     = DD_IDLE_PRIO,
+};
+
+static inline struct rb_root *
+deadline_rb_root(struct dd_per_prio *per_prio, struct request *rq)
+{
+       return &per_prio->sort_list[rq_data_dir(rq)];
+}
+
+/*
+ * Returns the I/O priority class (IOPRIO_CLASS_*) that has been assigned to a
+ * request.
+ */
+static u8 dd_rq_ioclass(struct request *rq)
+{
+       return IOPRIO_PRIO_CLASS(req_get_ioprio(rq));
+}
+
+/*
+ * get the request after `rq' in sector-sorted order
+ */
+static inline struct request *
+deadline_latter_request(struct request *rq)
+{
+       struct rb_node *node = rb_next(&rq->rb_node);
+
+       if (node)
+               return rb_entry_rq(node);
+
+       return NULL;
+}
+
+static void
+deadline_add_rq_rb(struct dd_per_prio *per_prio, struct request *rq)
+{
+       struct rb_root *root = deadline_rb_root(per_prio, rq);
+
+       elv_rb_add(root, rq);
+}
+
+static inline void
+deadline_del_rq_rb(struct dd_per_prio *per_prio, struct request *rq)
+{
+       const enum dd_data_dir data_dir = rq_data_dir(rq);
+
+       if (per_prio->next_rq[data_dir] == rq)
+               per_prio->next_rq[data_dir] = deadline_latter_request(rq);
+
+       elv_rb_del(deadline_rb_root(per_prio, rq), rq);
+}
+
+/*
+ * remove rq from rbtree and fifo.
+ */
+static void deadline_remove_request(struct request_queue *q,
+                                   struct dd_per_prio *per_prio,
+                                   struct request *rq)
+{
+       list_del_init(&rq->queuelist);
+
+       /*
+        * We might not be on the rbtree, if we are doing an insert merge
+        */
+       if (!RB_EMPTY_NODE(&rq->rb_node))
+               deadline_del_rq_rb(per_prio, rq);
+
+       elv_rqhash_del(q, rq);
+       if (q->last_merge == rq)
+               q->last_merge = NULL;
+}
+
+static void dd_request_merged(struct request_queue *q, struct request *req,
+                             enum elv_merge type)
+{
+       struct deadline_data *dd = q->elevator->elevator_data;
+       const u8 ioprio_class = dd_rq_ioclass(req);
+       const enum dd_prio prio = ioprio_class_to_prio[ioprio_class];
+       struct dd_per_prio *per_prio = &dd->per_prio[prio];
+
+       /*
+        * if the merge was a front merge, we need to reposition request
+        */
+       if (type == ELEVATOR_FRONT_MERGE) {
+               elv_rb_del(deadline_rb_root(per_prio, req), req);
+               deadline_add_rq_rb(per_prio, req);
+       }
+}
+
+/*
+ * Callback function that is invoked after @next has been merged into @req.
+ */
+static void dd_merged_requests(struct request_queue *q, struct request *req,
+                              struct request *next)
+{
+       struct deadline_data *dd = q->elevator->elevator_data;
+       const u8 ioprio_class = dd_rq_ioclass(next);
+       const enum dd_prio prio = ioprio_class_to_prio[ioprio_class];
+
+       dd_count(dd, merged, prio);
+
+       /*
+        * if next expires before rq, assign its expire time to rq
+        * and move into next position (next will be deleted) in fifo
+        */
+       if (!list_empty(&req->queuelist) && !list_empty(&next->queuelist)) {
+               if (time_before((unsigned long)next->fifo_time,
+                               (unsigned long)req->fifo_time)) {
+                       list_move(&req->queuelist, &next->queuelist);
+                       req->fifo_time = next->fifo_time;
+               }
+       }
+
+       /*
+        * kill knowledge of next, this one is a goner
+        */
+       deadline_remove_request(q, &dd->per_prio[prio], next);
+}
+
+/*
+ * move an entry to dispatch queue
+ */
+static void
+deadline_move_request(struct deadline_data *dd, struct dd_per_prio *per_prio,
+                     struct request *rq)
+{
+       const enum dd_data_dir data_dir = rq_data_dir(rq);
+
+       per_prio->next_rq[data_dir] = deadline_latter_request(rq);
+
+       /*
+        * take it off the sort and fifo list
+        */
+       deadline_remove_request(rq->q, per_prio, rq);
+}
+
+/* Number of requests queued for a given priority level. */
+static u32 dd_queued(struct deadline_data *dd, enum dd_prio prio)
+{
+       return dd_sum(dd, inserted, prio) - dd_sum(dd, completed, prio);
+}
+
+/*
+ * deadline_check_fifo returns 0 if there are no expired requests on the fifo,
+ * 1 otherwise. Requires !list_empty(&dd->fifo_list[data_dir])
+ */
+static inline int deadline_check_fifo(struct dd_per_prio *per_prio,
+                                     enum dd_data_dir data_dir)
+{
+       struct request *rq = rq_entry_fifo(per_prio->fifo_list[data_dir].next);
+
+       /*
+        * rq is expired!
+        */
+       if (time_after_eq(jiffies, (unsigned long)rq->fifo_time))
+               return 1;
+
+       return 0;
+}
+
+/*
+ * For the specified data direction, return the next request to
+ * dispatch using arrival ordered lists.
+ */
+static struct request *
+deadline_fifo_request(struct deadline_data *dd, struct dd_per_prio *per_prio,
+                     enum dd_data_dir data_dir)
+{
+       struct request *rq;
+       unsigned long flags;
+
+       if (list_empty(&per_prio->fifo_list[data_dir]))
+               return NULL;
+
+       rq = rq_entry_fifo(per_prio->fifo_list[data_dir].next);
+       if (data_dir == DD_READ || !blk_queue_is_zoned(rq->q))
+               return rq;
+
+       /*
+        * Look for a write request that can be dispatched, that is one with
+        * an unlocked target zone.
+        */
+       spin_lock_irqsave(&dd->zone_lock, flags);
+       list_for_each_entry(rq, &per_prio->fifo_list[DD_WRITE], queuelist) {
+               if (blk_req_can_dispatch_to_zone(rq))
+                       goto out;
+       }
+       rq = NULL;
+out:
+       spin_unlock_irqrestore(&dd->zone_lock, flags);
+
+       return rq;
+}
+
+/*
+ * For the specified data direction, return the next request to
+ * dispatch using sector position sorted lists.
+ */
+static struct request *
+deadline_next_request(struct deadline_data *dd, struct dd_per_prio *per_prio,
+                     enum dd_data_dir data_dir)
+{
+       struct request *rq;
+       unsigned long flags;
+
+       rq = per_prio->next_rq[data_dir];
+       if (!rq)
+               return NULL;
+
+       if (data_dir == DD_READ || !blk_queue_is_zoned(rq->q))
+               return rq;
+
+       /*
+        * Look for a write request that can be dispatched, that is one with
+        * an unlocked target zone.
+        */
+       spin_lock_irqsave(&dd->zone_lock, flags);
+       while (rq) {
+               if (blk_req_can_dispatch_to_zone(rq))
+                       break;
+               rq = deadline_latter_request(rq);
+       }
+       spin_unlock_irqrestore(&dd->zone_lock, flags);
+
+       return rq;
+}
+
+/*
+ * deadline_dispatch_requests selects the best request according to
+ * read/write expire, fifo_batch, etc and with a start time <= @latest.
+ */
+static struct request *__dd_dispatch_request(struct deadline_data *dd,
+                                            struct dd_per_prio *per_prio,
+                                            u64 latest_start_ns)
+{
+       struct request *rq, *next_rq;
+       enum dd_data_dir data_dir;
+       enum dd_prio prio;
+       u8 ioprio_class;
+
+       lockdep_assert_held(&dd->lock);
+
+       if (!list_empty(&per_prio->dispatch)) {
+               rq = list_first_entry(&per_prio->dispatch, struct request,
+                                     queuelist);
+               if (rq->start_time_ns > latest_start_ns)
+                       return NULL;
+               list_del_init(&rq->queuelist);
+               goto done;
+       }
+
+       /*
+        * batches are currently reads XOR writes
+        */
+       rq = deadline_next_request(dd, per_prio, dd->last_dir);
+       if (rq && dd->batching < dd->fifo_batch)
+               /* we have a next request are still entitled to batch */
+               goto dispatch_request;
+
+       /*
+        * at this point we are not running a batch. select the appropriate
+        * data direction (read / write)
+        */
+
+       if (!list_empty(&per_prio->fifo_list[DD_READ])) {
+               BUG_ON(RB_EMPTY_ROOT(&per_prio->sort_list[DD_READ]));
+
+               if (deadline_fifo_request(dd, per_prio, DD_WRITE) &&
+                   (dd->starved++ >= dd->writes_starved))
+                       goto dispatch_writes;
+
+               data_dir = DD_READ;
+
+               goto dispatch_find_request;
+       }
+
+       /*
+        * there are either no reads or writes have been starved
+        */
+
+       if (!list_empty(&per_prio->fifo_list[DD_WRITE])) {
+dispatch_writes:
+               BUG_ON(RB_EMPTY_ROOT(&per_prio->sort_list[DD_WRITE]));
+
+               dd->starved = 0;
+
+               data_dir = DD_WRITE;
+
+               goto dispatch_find_request;
+       }
+
+       return NULL;
+
+dispatch_find_request:
+       /*
+        * we are not running a batch, find best request for selected data_dir
+        */
+       next_rq = deadline_next_request(dd, per_prio, data_dir);
+       if (deadline_check_fifo(per_prio, data_dir) || !next_rq) {
+               /*
+                * A deadline has expired, the last request was in the other
+                * direction, or we have run out of higher-sectored requests.
+                * Start again from the request with the earliest expiry time.
+                */
+               rq = deadline_fifo_request(dd, per_prio, data_dir);
+       } else {
+               /*
+                * The last req was the same dir and we have a next request in
+                * sort order. No expired requests so continue on from here.
+                */
+               rq = next_rq;
+       }
+
+       /*
+        * For a zoned block device, if we only have writes queued and none of
+        * them can be dispatched, rq will be NULL.
+        */
+       if (!rq)
+               return NULL;
+
+       dd->last_dir = data_dir;
+       dd->batching = 0;
+
+dispatch_request:
+       if (rq->start_time_ns > latest_start_ns)
+               return NULL;
+       /*
+        * rq is the selected appropriate request.
+        */
+       dd->batching++;
+       deadline_move_request(dd, per_prio, rq);
+done:
+       ioprio_class = dd_rq_ioclass(rq);
+       prio = ioprio_class_to_prio[ioprio_class];
+       dd_count(dd, dispatched, prio);
+       /*
+        * If the request needs its target zone locked, do it.
+        */
+       blk_req_zone_write_lock(rq);
+       rq->rq_flags |= RQF_STARTED;
+       return rq;
+}
+
+/*
+ * Called from blk_mq_run_hw_queue() -> __blk_mq_sched_dispatch_requests().
+ *
+ * One confusing aspect here is that we get called for a specific
+ * hardware queue, but we may return a request that is for a
+ * different hardware queue. This is because mq-deadline has shared
+ * state for all hardware queues, in terms of sorting, FIFOs, etc.
+ */
+static struct request *dd_dispatch_request(struct blk_mq_hw_ctx *hctx)
+{
+       struct deadline_data *dd = hctx->queue->elevator->elevator_data;
+       const u64 now_ns = ktime_get_ns();
+       struct request *rq = NULL;
+       enum dd_prio prio;
+
+       spin_lock(&dd->lock);
+       /*
+        * Start with dispatching requests whose deadline expired more than
+        * aging_expire jiffies ago.
+        */
+       for (prio = DD_BE_PRIO; prio <= DD_PRIO_MAX; prio++) {
+               rq = __dd_dispatch_request(dd, &dd->per_prio[prio], now_ns -
+                                          jiffies_to_nsecs(dd->aging_expire));
+               if (rq)
+                       goto unlock;
+       }
+       /*
+        * Next, dispatch requests in priority order. Ignore lower priority
+        * requests if any higher priority requests are pending.
+        */
+       for (prio = 0; prio <= DD_PRIO_MAX; prio++) {
+               rq = __dd_dispatch_request(dd, &dd->per_prio[prio], now_ns);
+               if (rq || dd_queued(dd, prio))
+                       break;
+       }
+
+unlock:
+       spin_unlock(&dd->lock);
+
+       return rq;
+}
+
+/*
+ * Called by __blk_mq_alloc_request(). The shallow_depth value set by this
+ * function is used by __blk_mq_get_tag().
+ */
+static void dd_limit_depth(unsigned int op, struct blk_mq_alloc_data *data)
+{
+       struct deadline_data *dd = data->q->elevator->elevator_data;
+
+       /* Do not throttle synchronous reads. */
+       if (op_is_sync(op) && !op_is_write(op))
+               return;
+
+       /*
+        * Throttle asynchronous requests and writes such that these requests
+        * do not block the allocation of synchronous requests.
+        */
+       data->shallow_depth = dd->async_depth;
+}
+
+/* Called by blk_mq_update_nr_requests(). */
+static void dd_depth_updated(struct blk_mq_hw_ctx *hctx)
+{
+       struct request_queue *q = hctx->queue;
+       struct deadline_data *dd = q->elevator->elevator_data;
+       struct blk_mq_tags *tags = hctx->sched_tags;
+
+       dd->async_depth = max(1UL, 3 * q->nr_requests / 4);
+
+       sbitmap_queue_min_shallow_depth(tags->bitmap_tags, dd->async_depth);
+}
+
+/* Called by blk_mq_init_hctx() and blk_mq_init_sched(). */
+static int dd_init_hctx(struct blk_mq_hw_ctx *hctx, unsigned int hctx_idx)
+{
+       dd_depth_updated(hctx);
+       return 0;
+}
+
+static void dd_exit_sched(struct elevator_queue *e)
+{
+       struct deadline_data *dd = e->elevator_data;
+       enum dd_prio prio;
+
+       for (prio = 0; prio <= DD_PRIO_MAX; prio++) {
+               struct dd_per_prio *per_prio = &dd->per_prio[prio];
+
+               WARN_ON_ONCE(!list_empty(&per_prio->fifo_list[DD_READ]));
+               WARN_ON_ONCE(!list_empty(&per_prio->fifo_list[DD_WRITE]));
+       }
+
+       free_percpu(dd->stats);
+
+       kfree(dd);
+}
+
+/*
+ * initialize elevator private data (deadline_data).
+ */
+static int dd_init_sched(struct request_queue *q, struct elevator_type *e)
+{
+       struct deadline_data *dd;
+       struct elevator_queue *eq;
+       enum dd_prio prio;
+       int ret = -ENOMEM;
+
+       eq = elevator_alloc(q, e);
+       if (!eq)
+               return ret;
+
+       dd = kzalloc_node(sizeof(*dd), GFP_KERNEL, q->node);
+       if (!dd)
+               goto put_eq;
+
+       eq->elevator_data = dd;
+
+       dd->stats = alloc_percpu_gfp(typeof(*dd->stats),
+                                    GFP_KERNEL | __GFP_ZERO);
+       if (!dd->stats)
+               goto free_dd;
+
+       for (prio = 0; prio <= DD_PRIO_MAX; prio++) {
+               struct dd_per_prio *per_prio = &dd->per_prio[prio];
+
+               INIT_LIST_HEAD(&per_prio->dispatch);
+               INIT_LIST_HEAD(&per_prio->fifo_list[DD_READ]);
+               INIT_LIST_HEAD(&per_prio->fifo_list[DD_WRITE]);
+               per_prio->sort_list[DD_READ] = RB_ROOT;
+               per_prio->sort_list[DD_WRITE] = RB_ROOT;
+       }
+       dd->fifo_expire[DD_READ] = read_expire;
+       dd->fifo_expire[DD_WRITE] = write_expire;
+       dd->writes_starved = writes_starved;
+       dd->front_merges = 1;
+       dd->last_dir = DD_WRITE;
+       dd->fifo_batch = fifo_batch;
+       dd->aging_expire = aging_expire;
+       spin_lock_init(&dd->lock);
+       spin_lock_init(&dd->zone_lock);
+
+       q->elevator = eq;
+       return 0;
+
+free_dd:
+       kfree(dd);
+
+put_eq:
+       kobject_put(&eq->kobj);
+       return ret;
+}
+
+/*
+ * Try to merge @bio into an existing request. If @bio has been merged into
+ * an existing request, store the pointer to that request into *@rq.
+ */
+static int dd_request_merge(struct request_queue *q, struct request **rq,
+                           struct bio *bio)
+{
+       struct deadline_data *dd = q->elevator->elevator_data;
+       const u8 ioprio_class = IOPRIO_PRIO_CLASS(bio->bi_ioprio);
+       const enum dd_prio prio = ioprio_class_to_prio[ioprio_class];
+       struct dd_per_prio *per_prio = &dd->per_prio[prio];
+       sector_t sector = bio_end_sector(bio);
+       struct request *__rq;
+
+       if (!dd->front_merges)
+               return ELEVATOR_NO_MERGE;
+
+       __rq = elv_rb_find(&per_prio->sort_list[bio_data_dir(bio)], sector);
+       if (__rq) {
+               BUG_ON(sector != blk_rq_pos(__rq));
+
+               if (elv_bio_merge_ok(__rq, bio)) {
+                       *rq = __rq;
+                       return ELEVATOR_FRONT_MERGE;
+               }
+       }
+
+       return ELEVATOR_NO_MERGE;
+}
+
+/*
+ * Attempt to merge a bio into an existing request. This function is called
+ * before @bio is associated with a request.
+ */
+static bool dd_bio_merge(struct request_queue *q, struct bio *bio,
+               unsigned int nr_segs)
+{
+       struct deadline_data *dd = q->elevator->elevator_data;
+       struct request *free = NULL;
+       bool ret;
+
+       spin_lock(&dd->lock);
+       ret = blk_mq_sched_try_merge(q, bio, nr_segs, &free);
+       spin_unlock(&dd->lock);
+
+       if (free)
+               blk_mq_free_request(free);
+
+       return ret;
+}
+
+/*
+ * add rq to rbtree and fifo
+ */
+static void dd_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
+                             bool at_head)
+{
+       struct request_queue *q = hctx->queue;
+       struct deadline_data *dd = q->elevator->elevator_data;
+       const enum dd_data_dir data_dir = rq_data_dir(rq);
+       u16 ioprio = req_get_ioprio(rq);
+       u8 ioprio_class = IOPRIO_PRIO_CLASS(ioprio);
+       struct dd_per_prio *per_prio;
+       enum dd_prio prio;
+       LIST_HEAD(free);
+
+       lockdep_assert_held(&dd->lock);
+
+       /*
+        * This may be a requeue of a write request that has locked its
+        * target zone. If it is the case, this releases the zone lock.
+        */
+       blk_req_zone_write_unlock(rq);
+
+       prio = ioprio_class_to_prio[ioprio_class];
+       dd_count(dd, inserted, prio);
+
+       if (blk_mq_sched_try_insert_merge(q, rq, &free)) {
+               blk_mq_free_requests(&free);
+               return;
+       }
+
+       trace_block_rq_insert(rq);
+
+       per_prio = &dd->per_prio[prio];
+       if (at_head) {
+               list_add(&rq->queuelist, &per_prio->dispatch);
+       } else {
+               deadline_add_rq_rb(per_prio, rq);
+
+               if (rq_mergeable(rq)) {
+                       elv_rqhash_add(q, rq);
+                       if (!q->last_merge)
+                               q->last_merge = rq;
+               }
+
+               /*
+                * set expire time and add to fifo list
+                */
+               rq->fifo_time = jiffies + dd->fifo_expire[data_dir];
+               list_add_tail(&rq->queuelist, &per_prio->fifo_list[data_dir]);
+       }
+}
+
+/*
+ * Called from blk_mq_sched_insert_request() or blk_mq_sched_insert_requests().
+ */
+static void dd_insert_requests(struct blk_mq_hw_ctx *hctx,
+                              struct list_head *list, bool at_head)
+{
+       struct request_queue *q = hctx->queue;
+       struct deadline_data *dd = q->elevator->elevator_data;
+
+       spin_lock(&dd->lock);
+       while (!list_empty(list)) {
+               struct request *rq;
+
+               rq = list_first_entry(list, struct request, queuelist);
+               list_del_init(&rq->queuelist);
+               dd_insert_request(hctx, rq, at_head);
+       }
+       spin_unlock(&dd->lock);
+}
+
+/*
+ * Nothing to do here. This is defined only to ensure that .finish_request
+ * method is called upon request completion.
+ */
+static void dd_prepare_request(struct request *rq)
+{
+}
+
+/*
+ * Callback from inside blk_mq_free_request().
+ *
+ * For zoned block devices, write unlock the target zone of
+ * completed write requests. Do this while holding the zone lock
+ * spinlock so that the zone is never unlocked while deadline_fifo_request()
+ * or deadline_next_request() are executing. This function is called for
+ * all requests, whether or not these requests complete successfully.
+ *
+ * For a zoned block device, __dd_dispatch_request() may have stopped
+ * dispatching requests if all the queued requests are write requests directed
+ * at zones that are already locked due to on-going write requests. To ensure
+ * write request dispatch progress in this case, mark the queue as needing a
+ * restart to ensure that the queue is run again after completion of the
+ * request and zones being unlocked.
+ */
+static void dd_finish_request(struct request *rq)
+{
+       struct request_queue *q = rq->q;
+       struct deadline_data *dd = q->elevator->elevator_data;
+       const u8 ioprio_class = dd_rq_ioclass(rq);
+       const enum dd_prio prio = ioprio_class_to_prio[ioprio_class];
+       struct dd_per_prio *per_prio = &dd->per_prio[prio];
+
+       dd_count(dd, completed, prio);
+
+       if (blk_queue_is_zoned(q)) {
+               unsigned long flags;
+
+               spin_lock_irqsave(&dd->zone_lock, flags);
+               blk_req_zone_write_unlock(rq);
+               if (!list_empty(&per_prio->fifo_list[DD_WRITE]))
+                       blk_mq_sched_mark_restart_hctx(rq->mq_hctx);
+               spin_unlock_irqrestore(&dd->zone_lock, flags);
+       }
+}
+
+static bool dd_has_work_for_prio(struct dd_per_prio *per_prio)
+{
+       return !list_empty_careful(&per_prio->dispatch) ||
+               !list_empty_careful(&per_prio->fifo_list[DD_READ]) ||
+               !list_empty_careful(&per_prio->fifo_list[DD_WRITE]);
+}
+
+static bool dd_has_work(struct blk_mq_hw_ctx *hctx)
+{
+       struct deadline_data *dd = hctx->queue->elevator->elevator_data;
+       enum dd_prio prio;
+
+       for (prio = 0; prio <= DD_PRIO_MAX; prio++)
+               if (dd_has_work_for_prio(&dd->per_prio[prio]))
+                       return true;
+
+       return false;
+}
+
+/*
+ * sysfs parts below
+ */
+#define SHOW_INT(__FUNC, __VAR)                                                \
+static ssize_t __FUNC(struct elevator_queue *e, char *page)            \
+{                                                                      \
+       struct deadline_data *dd = e->elevator_data;                    \
+                                                                       \
+       return sysfs_emit(page, "%d\n", __VAR);                         \
+}
+#define SHOW_JIFFIES(__FUNC, __VAR) SHOW_INT(__FUNC, jiffies_to_msecs(__VAR))
+SHOW_JIFFIES(deadline_read_expire_show, dd->fifo_expire[DD_READ]);
+SHOW_JIFFIES(deadline_write_expire_show, dd->fifo_expire[DD_WRITE]);
+SHOW_JIFFIES(deadline_aging_expire_show, dd->aging_expire);
+SHOW_INT(deadline_writes_starved_show, dd->writes_starved);
+SHOW_INT(deadline_front_merges_show, dd->front_merges);
+SHOW_INT(deadline_async_depth_show, dd->front_merges);
+SHOW_INT(deadline_fifo_batch_show, dd->fifo_batch);
+#undef SHOW_INT
+#undef SHOW_JIFFIES
+
+#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV)                        \
+static ssize_t __FUNC(struct elevator_queue *e, const char *page, size_t count)        \
+{                                                                      \
+       struct deadline_data *dd = e->elevator_data;                    \
+       int __data, __ret;                                              \
+                                                                       \
+       __ret = kstrtoint(page, 0, &__data);                            \
+       if (__ret < 0)                                                  \
+               return __ret;                                           \
+       if (__data < (MIN))                                             \
+               __data = (MIN);                                         \
+       else if (__data > (MAX))                                        \
+               __data = (MAX);                                         \
+       *(__PTR) = __CONV(__data);                                      \
+       return count;                                                   \
+}
+#define STORE_INT(__FUNC, __PTR, MIN, MAX)                             \
+       STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, )
+#define STORE_JIFFIES(__FUNC, __PTR, MIN, MAX)                         \
+       STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, msecs_to_jiffies)
+STORE_JIFFIES(deadline_read_expire_store, &dd->fifo_expire[DD_READ], 0, INT_MAX);
+STORE_JIFFIES(deadline_write_expire_store, &dd->fifo_expire[DD_WRITE], 0, INT_MAX);
+STORE_JIFFIES(deadline_aging_expire_store, &dd->aging_expire, 0, INT_MAX);
+STORE_INT(deadline_writes_starved_store, &dd->writes_starved, INT_MIN, INT_MAX);
+STORE_INT(deadline_front_merges_store, &dd->front_merges, 0, 1);
+STORE_INT(deadline_async_depth_store, &dd->front_merges, 1, INT_MAX);
+STORE_INT(deadline_fifo_batch_store, &dd->fifo_batch, 0, INT_MAX);
+#undef STORE_FUNCTION
+#undef STORE_INT
+#undef STORE_JIFFIES
+
+#define DD_ATTR(name) \
+       __ATTR(name, 0644, deadline_##name##_show, deadline_##name##_store)
+
+static struct elv_fs_entry deadline_attrs[] = {
+       DD_ATTR(read_expire),
+       DD_ATTR(write_expire),
+       DD_ATTR(writes_starved),
+       DD_ATTR(front_merges),
+       DD_ATTR(async_depth),
+       DD_ATTR(fifo_batch),
+       DD_ATTR(aging_expire),
+       __ATTR_NULL
+};
+
+#ifdef CONFIG_BLK_DEBUG_FS
+#define DEADLINE_DEBUGFS_DDIR_ATTRS(prio, data_dir, name)              \
+static void *deadline_##name##_fifo_start(struct seq_file *m,          \
+                                         loff_t *pos)                  \
+       __acquires(&dd->lock)                                           \
+{                                                                      \
+       struct request_queue *q = m->private;                           \
+       struct deadline_data *dd = q->elevator->elevator_data;          \
+       struct dd_per_prio *per_prio = &dd->per_prio[prio];             \
+                                                                       \
+       spin_lock(&dd->lock);                                           \
+       return seq_list_start(&per_prio->fifo_list[data_dir], *pos);    \
+}                                                                      \
+                                                                       \
+static void *deadline_##name##_fifo_next(struct seq_file *m, void *v,  \
+                                        loff_t *pos)                   \
+{                                                                      \
+       struct request_queue *q = m->private;                           \
+       struct deadline_data *dd = q->elevator->elevator_data;          \
+       struct dd_per_prio *per_prio = &dd->per_prio[prio];             \
+                                                                       \
+       return seq_list_next(v, &per_prio->fifo_list[data_dir], pos);   \
+}                                                                      \
+                                                                       \
+static void deadline_##name##_fifo_stop(struct seq_file *m, void *v)   \
+       __releases(&dd->lock)                                           \
+{                                                                      \
+       struct request_queue *q = m->private;                           \
+       struct deadline_data *dd = q->elevator->elevator_data;          \
+                                                                       \
+       spin_unlock(&dd->lock);                                         \
+}                                                                      \
+                                                                       \
+static const struct seq_operations deadline_##name##_fifo_seq_ops = {  \
+       .start  = deadline_##name##_fifo_start,                         \
+       .next   = deadline_##name##_fifo_next,                          \
+       .stop   = deadline_##name##_fifo_stop,                          \
+       .show   = blk_mq_debugfs_rq_show,                               \
+};                                                                     \
+                                                                       \
+static int deadline_##name##_next_rq_show(void *data,                  \
+                                         struct seq_file *m)           \
+{                                                                      \
+       struct request_queue *q = data;                                 \
+       struct deadline_data *dd = q->elevator->elevator_data;          \
+       struct dd_per_prio *per_prio = &dd->per_prio[prio];             \
+       struct request *rq = per_prio->next_rq[data_dir];               \
+                                                                       \
+       if (rq)                                                         \
+               __blk_mq_debugfs_rq_show(m, rq);                        \
+       return 0;                                                       \
+}
+
+DEADLINE_DEBUGFS_DDIR_ATTRS(DD_RT_PRIO, DD_READ, read0);
+DEADLINE_DEBUGFS_DDIR_ATTRS(DD_RT_PRIO, DD_WRITE, write0);
+DEADLINE_DEBUGFS_DDIR_ATTRS(DD_BE_PRIO, DD_READ, read1);
+DEADLINE_DEBUGFS_DDIR_ATTRS(DD_BE_PRIO, DD_WRITE, write1);
+DEADLINE_DEBUGFS_DDIR_ATTRS(DD_IDLE_PRIO, DD_READ, read2);
+DEADLINE_DEBUGFS_DDIR_ATTRS(DD_IDLE_PRIO, DD_WRITE, write2);
+#undef DEADLINE_DEBUGFS_DDIR_ATTRS
+
+static int deadline_batching_show(void *data, struct seq_file *m)
+{
+       struct request_queue *q = data;
+       struct deadline_data *dd = q->elevator->elevator_data;
+
+       seq_printf(m, "%u\n", dd->batching);
+       return 0;
+}
+
+static int deadline_starved_show(void *data, struct seq_file *m)
+{
+       struct request_queue *q = data;
+       struct deadline_data *dd = q->elevator->elevator_data;
+
+       seq_printf(m, "%u\n", dd->starved);
+       return 0;
+}
+
+static int dd_async_depth_show(void *data, struct seq_file *m)
+{
+       struct request_queue *q = data;
+       struct deadline_data *dd = q->elevator->elevator_data;
+
+       seq_printf(m, "%u\n", dd->async_depth);
+       return 0;
+}
+
+static int dd_queued_show(void *data, struct seq_file *m)
+{
+       struct request_queue *q = data;
+       struct deadline_data *dd = q->elevator->elevator_data;
+
+       seq_printf(m, "%u %u %u\n", dd_queued(dd, DD_RT_PRIO),
+                  dd_queued(dd, DD_BE_PRIO),
+                  dd_queued(dd, DD_IDLE_PRIO));
+       return 0;
+}
+
+/* Number of requests owned by the block driver for a given priority. */
+static u32 dd_owned_by_driver(struct deadline_data *dd, enum dd_prio prio)
+{
+       return dd_sum(dd, dispatched, prio) + dd_sum(dd, merged, prio)
+               - dd_sum(dd, completed, prio);
+}
+
+static int dd_owned_by_driver_show(void *data, struct seq_file *m)
+{
+       struct request_queue *q = data;
+       struct deadline_data *dd = q->elevator->elevator_data;
+
+       seq_printf(m, "%u %u %u\n", dd_owned_by_driver(dd, DD_RT_PRIO),
+                  dd_owned_by_driver(dd, DD_BE_PRIO),
+                  dd_owned_by_driver(dd, DD_IDLE_PRIO));
+       return 0;
+}
+
+#define DEADLINE_DISPATCH_ATTR(prio)                                   \
+static void *deadline_dispatch##prio##_start(struct seq_file *m,       \
+                                            loff_t *pos)               \
+       __acquires(&dd->lock)                                           \
+{                                                                      \
+       struct request_queue *q = m->private;                           \
+       struct deadline_data *dd = q->elevator->elevator_data;          \
+       struct dd_per_prio *per_prio = &dd->per_prio[prio];             \
+                                                                       \
+       spin_lock(&dd->lock);                                           \
+       return seq_list_start(&per_prio->dispatch, *pos);               \
+}                                                                      \
+                                                                       \
+static void *deadline_dispatch##prio##_next(struct seq_file *m,                \
+                                           void *v, loff_t *pos)       \
+{                                                                      \
+       struct request_queue *q = m->private;                           \
+       struct deadline_data *dd = q->elevator->elevator_data;          \
+       struct dd_per_prio *per_prio = &dd->per_prio[prio];             \
+                                                                       \
+       return seq_list_next(v, &per_prio->dispatch, pos);              \
+}                                                                      \
+                                                                       \
+static void deadline_dispatch##prio##_stop(struct seq_file *m, void *v)        \
+       __releases(&dd->lock)                                           \
+{                                                                      \
+       struct request_queue *q = m->private;                           \
+       struct deadline_data *dd = q->elevator->elevator_data;          \
+                                                                       \
+       spin_unlock(&dd->lock);                                         \
+}                                                                      \
+                                                                       \
+static const struct seq_operations deadline_dispatch##prio##_seq_ops = { \
+       .start  = deadline_dispatch##prio##_start,                      \
+       .next   = deadline_dispatch##prio##_next,                       \
+       .stop   = deadline_dispatch##prio##_stop,                       \
+       .show   = blk_mq_debugfs_rq_show,                               \
+}
+
+DEADLINE_DISPATCH_ATTR(0);
+DEADLINE_DISPATCH_ATTR(1);
+DEADLINE_DISPATCH_ATTR(2);
+#undef DEADLINE_DISPATCH_ATTR
+
+#define DEADLINE_QUEUE_DDIR_ATTRS(name)                                        \
+       {#name "_fifo_list", 0400,                                      \
+                       .seq_ops = &deadline_##name##_fifo_seq_ops}
+#define DEADLINE_NEXT_RQ_ATTR(name)                                    \
+       {#name "_next_rq", 0400, deadline_##name##_next_rq_show}
+static const struct blk_mq_debugfs_attr deadline_queue_debugfs_attrs[] = {
+       DEADLINE_QUEUE_DDIR_ATTRS(read0),
+       DEADLINE_QUEUE_DDIR_ATTRS(write0),
+       DEADLINE_QUEUE_DDIR_ATTRS(read1),
+       DEADLINE_QUEUE_DDIR_ATTRS(write1),
+       DEADLINE_QUEUE_DDIR_ATTRS(read2),
+       DEADLINE_QUEUE_DDIR_ATTRS(write2),
+       DEADLINE_NEXT_RQ_ATTR(read0),
+       DEADLINE_NEXT_RQ_ATTR(write0),
+       DEADLINE_NEXT_RQ_ATTR(read1),
+       DEADLINE_NEXT_RQ_ATTR(write1),
+       DEADLINE_NEXT_RQ_ATTR(read2),
+       DEADLINE_NEXT_RQ_ATTR(write2),
+       {"batching", 0400, deadline_batching_show},
+       {"starved", 0400, deadline_starved_show},
+       {"async_depth", 0400, dd_async_depth_show},
+       {"dispatch0", 0400, .seq_ops = &deadline_dispatch0_seq_ops},
+       {"dispatch1", 0400, .seq_ops = &deadline_dispatch1_seq_ops},
+       {"dispatch2", 0400, .seq_ops = &deadline_dispatch2_seq_ops},
+       {"owned_by_driver", 0400, dd_owned_by_driver_show},
+       {"queued", 0400, dd_queued_show},
+       {},
+};
+#undef DEADLINE_QUEUE_DDIR_ATTRS
+#endif
+
+static struct elevator_type mq_deadline = {
+       .ops = {
+               .depth_updated          = dd_depth_updated,
+               .limit_depth            = dd_limit_depth,
+               .insert_requests        = dd_insert_requests,
+               .dispatch_request       = dd_dispatch_request,
+               .prepare_request        = dd_prepare_request,
+               .finish_request         = dd_finish_request,
+               .next_request           = elv_rb_latter_request,
+               .former_request         = elv_rb_former_request,
+               .bio_merge              = dd_bio_merge,
+               .request_merge          = dd_request_merge,
+               .requests_merged        = dd_merged_requests,
+               .request_merged         = dd_request_merged,
+               .has_work               = dd_has_work,
+               .init_sched             = dd_init_sched,
+               .exit_sched             = dd_exit_sched,
+               .init_hctx              = dd_init_hctx,
+       },
+
+#ifdef CONFIG_BLK_DEBUG_FS
+       .queue_debugfs_attrs = deadline_queue_debugfs_attrs,
+#endif
+       .elevator_attrs = deadline_attrs,
+       .elevator_name = "mq-deadline",
+       .elevator_alias = "deadline",
+       .elevator_features = ELEVATOR_F_ZBD_SEQ_WRITE,
+       .elevator_owner = THIS_MODULE,
+};
+MODULE_ALIAS("mq-deadline-iosched");
+
+static int __init deadline_init(void)
+{
+       return elv_register(&mq_deadline);
+}
+
+static void __exit deadline_exit(void)
+{
+       elv_unregister(&mq_deadline);
+}
+
+module_init(deadline_init);
+module_exit(deadline_exit);
+
+MODULE_AUTHOR("Jens Axboe, Damien Le Moal and Bart Van Assche");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MQ deadline IO scheduler");
index ca3b02d..64b772c 100644 (file)
@@ -1768,7 +1768,7 @@ config CRYPTO_DRBG_HMAC
        bool
        default y
        select CRYPTO_HMAC
-       select CRYPTO_SHA256
+       select CRYPTO_SHA512
 
 config CRYPTO_DRBG_HASH
        bool "Enable Hash DRBG"
index 23d9a09..a3ef6cc 100644 (file)
@@ -3021,6 +3021,9 @@ static int acpi_nfit_register_region(struct acpi_nfit_desc *acpi_desc,
                struct acpi_nfit_memory_map *memdev = nfit_memdev->memdev;
                struct nd_mapping_desc *mapping;
 
+               /* range index 0 == unmapped in SPA or invalid-SPA */
+               if (memdev->range_index == 0 || spa->range_index == 0)
+                       continue;
                if (memdev->range_index != spa->range_index)
                        continue;
                if (count >= ND_MAX_MAPPINGS) {
index 31cf9ae..1f6007a 100644 (file)
@@ -292,6 +292,12 @@ void __init init_prmt(void)
        int mc = acpi_table_parse_entries(ACPI_SIG_PRMT, sizeof(struct acpi_table_prmt) +
                                          sizeof (struct acpi_table_prmt_header),
                                          0, acpi_parse_prmt, 0);
+       /*
+        * Return immediately if PRMT table is not present or no PRM module found.
+        */
+       if (mc <= 0)
+               return;
+
        pr_info("PRM: found %u modules\n", mc);
 
        status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
index fbdbef0..3a30846 100644 (file)
@@ -452,7 +452,7 @@ int acpi_s2idle_prepare_late(void)
        if (lps0_dsm_func_mask_microsoft > 0) {
                acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF,
                                lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-               acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT,
+               acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_ENTRY,
                                lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
                acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
                                lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
@@ -479,7 +479,7 @@ void acpi_s2idle_restore_early(void)
        if (lps0_dsm_func_mask_microsoft > 0) {
                acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
                                lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-               acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_ENTRY,
+               acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT,
                                lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
                acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON,
                                lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
index f636049..6c0ef9d 100644 (file)
@@ -2837,6 +2837,7 @@ void device_initialize(struct device *dev)
        device_pm_init(dev);
        set_dev_node(dev, -1);
 #ifdef CONFIG_GENERIC_MSI_IRQ
+       raw_spin_lock_init(&dev->msi_lock);
        INIT_LIST_HEAD(&dev->msi_list);
 #endif
        INIT_LIST_HEAD(&dev->links.consumers);
index c383179..19f5d5a 100644 (file)
@@ -818,6 +818,10 @@ static bool nbd_clear_req(struct request *req, void *data, bool reserved)
 {
        struct nbd_cmd *cmd = blk_mq_rq_to_pdu(req);
 
+       /* don't abort one completed request */
+       if (blk_mq_request_completed(req))
+               return true;
+
        mutex_lock(&cmd->lock);
        cmd->status = BLK_STS_IOERR;
        mutex_unlock(&cmd->lock);
@@ -2004,15 +2008,19 @@ static void nbd_disconnect_and_put(struct nbd_device *nbd)
 {
        mutex_lock(&nbd->config_lock);
        nbd_disconnect(nbd);
-       nbd_clear_sock(nbd);
-       mutex_unlock(&nbd->config_lock);
+       sock_shutdown(nbd);
        /*
         * Make sure recv thread has finished, so it does not drop the last
         * config ref and try to destroy the workqueue from inside the work
-        * queue.
+        * queue. And this also ensure that we can safely call nbd_clear_que()
+        * to cancel the inflight I/Os.
         */
        if (nbd->recv_workq)
                flush_workqueue(nbd->recv_workq);
+       nbd_clear_que(nbd);
+       nbd->task_setup = NULL;
+       mutex_unlock(&nbd->config_lock);
+
        if (test_and_clear_bit(NBD_RT_HAS_CONFIG_REF,
                               &nbd->config->runtime_flags))
                nbd_config_put(nbd);
index 4b49df2..afb37aa 100644 (file)
@@ -692,6 +692,28 @@ static const struct blk_mq_ops virtio_mq_ops = {
 static unsigned int virtblk_queue_depth;
 module_param_named(queue_depth, virtblk_queue_depth, uint, 0444);
 
+static int virtblk_validate(struct virtio_device *vdev)
+{
+       u32 blk_size;
+
+       if (!vdev->config->get) {
+               dev_err(&vdev->dev, "%s failure: config access disabled\n",
+                       __func__);
+               return -EINVAL;
+       }
+
+       if (!virtio_has_feature(vdev, VIRTIO_BLK_F_BLK_SIZE))
+               return 0;
+
+       blk_size = virtio_cread32(vdev,
+                       offsetof(struct virtio_blk_config, blk_size));
+
+       if (blk_size < SECTOR_SIZE || blk_size > PAGE_SIZE)
+               __virtio_clear_bit(vdev, VIRTIO_BLK_F_BLK_SIZE);
+
+       return 0;
+}
+
 static int virtblk_probe(struct virtio_device *vdev)
 {
        struct virtio_blk *vblk;
@@ -703,12 +725,6 @@ static int virtblk_probe(struct virtio_device *vdev)
        u8 physical_block_exp, alignment_offset;
        unsigned int queue_depth;
 
-       if (!vdev->config->get) {
-               dev_err(&vdev->dev, "%s failure: config access disabled\n",
-                       __func__);
-               return -EINVAL;
-       }
-
        err = ida_simple_get(&vd_index_ida, 0, minor_to_index(1 << MINORBITS),
                             GFP_KERNEL);
        if (err < 0)
@@ -823,6 +839,14 @@ static int virtblk_probe(struct virtio_device *vdev)
        else
                blk_size = queue_logical_block_size(q);
 
+       if (unlikely(blk_size < SECTOR_SIZE || blk_size > PAGE_SIZE)) {
+               dev_err(&vdev->dev,
+                       "block size is changed unexpectedly, now is %u\n",
+                       blk_size);
+               err = -EINVAL;
+               goto err_cleanup_disk;
+       }
+
        /* Use topology information if available */
        err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
                                   struct virtio_blk_config, physical_block_exp,
@@ -881,6 +905,8 @@ static int virtblk_probe(struct virtio_device *vdev)
        device_add_disk(&vdev->dev, vblk->disk, virtblk_attr_groups);
        return 0;
 
+err_cleanup_disk:
+       blk_cleanup_disk(vblk->disk);
 out_free_tags:
        blk_mq_free_tag_set(&vblk->tag_set);
 out_free_vq:
@@ -983,6 +1009,7 @@ static struct virtio_driver virtio_blk = {
        .driver.name                    = KBUILD_MODNAME,
        .driver.owner                   = THIS_MODULE,
        .id_table                       = id_table,
+       .validate                       = virtblk_validate,
        .probe                          = virtblk_probe,
        .remove                         = virtblk_remove,
        .config_changed                 = virtblk_config_changed,
index 0ef98e3..148a4dd 100644 (file)
@@ -3097,8 +3097,10 @@ static int sysc_probe(struct platform_device *pdev)
                return error;
 
        error = sysc_check_active_timer(ddata);
-       if (error == -EBUSY)
+       if (error == -ENXIO)
                ddata->reserved = true;
+       else if (error)
+               return error;
 
        error = sysc_get_clocks(ddata);
        if (error)
index 496900d..de36f58 100644 (file)
@@ -974,6 +974,6 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
                               hws[IMX6QDL_CLK_PLL3_USB_OTG]->clk);
        }
 
-       imx_register_uart_clocks(1);
+       imx_register_uart_clocks(2);
 }
 CLK_OF_DECLARE(imx6q, "fsl,imx6q-ccm", imx6q_clocks_init);
index 51ed640..4ece326 100644 (file)
@@ -357,27 +357,43 @@ static int gdsc_init(struct gdsc *sc)
        if (on < 0)
                return on;
 
-       /*
-        * Votable GDSCs can be ON due to Vote from other masters.
-        * If a Votable GDSC is ON, make sure we have a Vote.
-        */
-       if ((sc->flags & VOTABLE) && on)
-               gdsc_enable(&sc->pd);
+       if (on) {
+               /* The regulator must be on, sync the kernel state */
+               if (sc->rsupply) {
+                       ret = regulator_enable(sc->rsupply);
+                       if (ret < 0)
+                               return ret;
+               }
 
-       /*
-        * Make sure the retain bit is set if the GDSC is already on, otherwise
-        * we end up turning off the GDSC and destroying all the register
-        * contents that we thought we were saving.
-        */
-       if ((sc->flags & RETAIN_FF_ENABLE) && on)
-               gdsc_retain_ff_on(sc);
+               /*
+                * Votable GDSCs can be ON due to Vote from other masters.
+                * If a Votable GDSC is ON, make sure we have a Vote.
+                */
+               if (sc->flags & VOTABLE) {
+                       ret = regmap_update_bits(sc->regmap, sc->gdscr,
+                                                SW_COLLAPSE_MASK, val);
+                       if (ret)
+                               return ret;
+               }
+
+               /* Turn on HW trigger mode if supported */
+               if (sc->flags & HW_CTRL) {
+                       ret = gdsc_hwctrl(sc, true);
+                       if (ret < 0)
+                               return ret;
+               }
 
-       /* If ALWAYS_ON GDSCs are not ON, turn them ON */
-       if (sc->flags & ALWAYS_ON) {
-               if (!on)
-                       gdsc_enable(&sc->pd);
+               /*
+                * Make sure the retain bit is set if the GDSC is already on,
+                * otherwise we end up turning off the GDSC and destroying all
+                * the register contents that we thought we were saving.
+                */
+               if (sc->flags & RETAIN_FF_ENABLE)
+                       gdsc_retain_ff_on(sc);
+       } else if (sc->flags & ALWAYS_ON) {
+               /* If ALWAYS_ON GDSCs are not ON, turn them ON */
+               gdsc_enable(&sc->pd);
                on = true;
-               sc->pd.flags |= GENPD_FLAG_ALWAYS_ON;
        }
 
        if (on || (sc->pwrsts & PWRSTS_RET))
@@ -385,6 +401,8 @@ static int gdsc_init(struct gdsc *sc)
        else
                gdsc_clear_mem_on(sc);
 
+       if (sc->flags & ALWAYS_ON)
+               sc->pd.flags |= GENPD_FLAG_ALWAYS_ON;
        if (!sc->pd.power_off)
                sc->pd.power_off = gdsc_disable;
        if (!sc->pd.power_on)
index 3fc98a3..c10fc33 100644 (file)
@@ -104,7 +104,11 @@ struct armada_37xx_dvfs {
 };
 
 static struct armada_37xx_dvfs armada_37xx_dvfs[] = {
-       {.cpu_freq_max = 1200*1000*1000, .divider = {1, 2, 4, 6} },
+       /*
+        * The cpufreq scaling for 1.2 GHz variant of the SOC is currently
+        * unstable because we do not know how to configure it properly.
+        */
+       /* {.cpu_freq_max = 1200*1000*1000, .divider = {1, 2, 4, 6} }, */
        {.cpu_freq_max = 1000*1000*1000, .divider = {1, 2, 4, 5} },
        {.cpu_freq_max = 800*1000*1000,  .divider = {1, 2, 3, 4} },
        {.cpu_freq_max = 600*1000*1000,  .divider = {2, 4, 5, 6} },
index bef7528..231e585 100644 (file)
@@ -139,7 +139,9 @@ static const struct of_device_id blocklist[] __initconst = {
        { .compatible = "qcom,qcs404", },
        { .compatible = "qcom,sc7180", },
        { .compatible = "qcom,sc7280", },
+       { .compatible = "qcom,sc8180x", },
        { .compatible = "qcom,sdm845", },
+       { .compatible = "qcom,sm8150", },
 
        { .compatible = "st,stih407", },
        { .compatible = "st,stih410", },
index ec9a87c..75f818d 100644 (file)
@@ -134,7 +134,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
        }
 
        if (!zalloc_cpumask_var(&opp_shared_cpus, GFP_KERNEL))
-               ret = -ENOMEM;
+               return -ENOMEM;
 
        /* Obtain CPUs that share SCMI performance controls */
        ret = scmi_get_sharing_cpus(cpu_dev, policy->cpus);
index 5fa6ae9..44736cb 100644 (file)
@@ -313,7 +313,7 @@ long dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages,
                return -ENXIO;
 
        if (nr_pages < 0)
-               return nr_pages;
+               return -EINVAL;
 
        avail = dax_dev->ops->direct_access(dax_dev, pgoff, nr_pages,
                        kaddr, pfn);
index 7bf0a7a..2363fee 100644 (file)
@@ -35,15 +35,48 @@ efi_status_t check_platform_features(void)
 }
 
 /*
- * Although relocatable kernels can fix up the misalignment with respect to
- * MIN_KIMG_ALIGN, the resulting virtual text addresses are subtly out of
- * sync with those recorded in the vmlinux when kaslr is disabled but the
- * image required relocation anyway. Therefore retain 2M alignment unless
- * KASLR is in use.
+ * Distro versions of GRUB may ignore the BSS allocation entirely (i.e., fail
+ * to provide space, and fail to zero it). Check for this condition by double
+ * checking that the first and the last byte of the image are covered by the
+ * same EFI memory map entry.
  */
-static u64 min_kimg_align(void)
+static bool check_image_region(u64 base, u64 size)
 {
-       return efi_nokaslr ? MIN_KIMG_ALIGN : EFI_KIMG_ALIGN;
+       unsigned long map_size, desc_size, buff_size;
+       efi_memory_desc_t *memory_map;
+       struct efi_boot_memmap map;
+       efi_status_t status;
+       bool ret = false;
+       int map_offset;
+
+       map.map =       &memory_map;
+       map.map_size =  &map_size;
+       map.desc_size = &desc_size;
+       map.desc_ver =  NULL;
+       map.key_ptr =   NULL;
+       map.buff_size = &buff_size;
+
+       status = efi_get_memory_map(&map);
+       if (status != EFI_SUCCESS)
+               return false;
+
+       for (map_offset = 0; map_offset < map_size; map_offset += desc_size) {
+               efi_memory_desc_t *md = (void *)memory_map + map_offset;
+               u64 end = md->phys_addr + md->num_pages * EFI_PAGE_SIZE;
+
+               /*
+                * Find the region that covers base, and return whether
+                * it covers base+size bytes.
+                */
+               if (base >= md->phys_addr && base < end) {
+                       ret = (base + size) <= end;
+                       break;
+               }
+       }
+
+       efi_bs_call(free_pool, memory_map);
+
+       return ret;
 }
 
 efi_status_t handle_kernel_image(unsigned long *image_addr,
@@ -56,6 +89,16 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
        unsigned long kernel_size, kernel_memsize = 0;
        u32 phys_seed = 0;
 
+       /*
+        * Although relocatable kernels can fix up the misalignment with
+        * respect to MIN_KIMG_ALIGN, the resulting virtual text addresses are
+        * subtly out of sync with those recorded in the vmlinux when kaslr is
+        * disabled but the image required relocation anyway. Therefore retain
+        * 2M alignment if KASLR was explicitly disabled, even if it was not
+        * going to be activated to begin with.
+        */
+       u64 min_kimg_align = efi_nokaslr ? MIN_KIMG_ALIGN : EFI_KIMG_ALIGN;
+
        if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
                if (!efi_nokaslr) {
                        status = efi_get_random_bytes(sizeof(phys_seed),
@@ -76,6 +119,10 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
        if (image->image_base != _text)
                efi_err("FIRMWARE BUG: efi_loaded_image_t::image_base has bogus value\n");
 
+       if (!IS_ALIGNED((u64)_text, EFI_KIMG_ALIGN))
+               efi_err("FIRMWARE BUG: kernel image not aligned on %ldk boundary\n",
+                       EFI_KIMG_ALIGN >> 10);
+
        kernel_size = _edata - _text;
        kernel_memsize = kernel_size + (_end - _edata);
        *reserve_size = kernel_memsize;
@@ -85,14 +132,18 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
                 * If KASLR is enabled, and we have some randomness available,
                 * locate the kernel at a randomized offset in physical memory.
                 */
-               status = efi_random_alloc(*reserve_size, min_kimg_align(),
+               status = efi_random_alloc(*reserve_size, min_kimg_align,
                                          reserve_addr, phys_seed);
+               if (status != EFI_SUCCESS)
+                       efi_warn("efi_random_alloc() failed: 0x%lx\n", status);
        } else {
                status = EFI_OUT_OF_RESOURCES;
        }
 
        if (status != EFI_SUCCESS) {
-               if (IS_ALIGNED((u64)_text, min_kimg_align())) {
+               if (!check_image_region((u64)_text, kernel_memsize)) {
+                       efi_err("FIRMWARE BUG: Image BSS overlaps adjacent EFI memory region\n");
+               } else if (IS_ALIGNED((u64)_text, min_kimg_align)) {
                        /*
                         * Just execute from wherever we were loaded by the
                         * UEFI PE/COFF loader if the alignment is suitable.
@@ -103,7 +154,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
                }
 
                status = efi_allocate_pages_aligned(*reserve_size, reserve_addr,
-                                                   ULONG_MAX, min_kimg_align());
+                                                   ULONG_MAX, min_kimg_align);
 
                if (status != EFI_SUCCESS) {
                        efi_err("Failed to relocate kernel\n");
index a408df4..724155b 100644 (file)
@@ -30,6 +30,8 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
 
        region_end = min(md->phys_addr + md->num_pages * EFI_PAGE_SIZE - 1,
                         (u64)ULONG_MAX);
+       if (region_end < size)
+               return 0;
 
        first_slot = round_up(md->phys_addr, align);
        last_slot = round_down(region_end - size + 1, align);
index 3b5d131..8f53837 100644 (file)
@@ -468,6 +468,46 @@ bool amdgpu_atomfirmware_dynamic_boot_config_supported(struct amdgpu_device *ade
        return (fw_cap & ATOM_FIRMWARE_CAP_DYNAMIC_BOOT_CFG_ENABLE) ? true : false;
 }
 
+/*
+ * Helper function to query RAS EEPROM address
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Return true if vbios supports ras rom address reporting
+ */
+bool amdgpu_atomfirmware_ras_rom_addr(struct amdgpu_device *adev, uint8_t* i2c_address)
+{
+       struct amdgpu_mode_info *mode_info = &adev->mode_info;
+       int index;
+       u16 data_offset, size;
+       union firmware_info *firmware_info;
+       u8 frev, crev;
+
+       if (i2c_address == NULL)
+               return false;
+
+       *i2c_address = 0;
+
+       index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
+                       firmwareinfo);
+
+       if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context,
+                               index, &size, &frev, &crev, &data_offset)) {
+               /* support firmware_info 3.4 + */
+               if ((frev == 3 && crev >=4) || (frev > 3)) {
+                       firmware_info = (union firmware_info *)
+                               (mode_info->atom_context->bios + data_offset);
+                       *i2c_address = firmware_info->v34.ras_rom_i2c_slave_addr;
+               }
+       }
+
+       if (*i2c_address != 0)
+               return true;
+
+       return false;
+}
+
+
 union smu_info {
        struct atom_smu_info_v3_1 v31;
 };
index 1bbbb19..751248b 100644 (file)
@@ -36,6 +36,7 @@ int amdgpu_atomfirmware_get_clock_info(struct amdgpu_device *adev);
 int amdgpu_atomfirmware_get_gfx_info(struct amdgpu_device *adev);
 bool amdgpu_atomfirmware_mem_ecc_supported(struct amdgpu_device *adev);
 bool amdgpu_atomfirmware_sram_ecc_supported(struct amdgpu_device *adev);
+bool amdgpu_atomfirmware_ras_rom_addr(struct amdgpu_device *adev, uint8_t* i2c_address);
 bool amdgpu_atomfirmware_mem_training_supported(struct amdgpu_device *adev);
 bool amdgpu_atomfirmware_dynamic_boot_config_supported(struct amdgpu_device *adev);
 int amdgpu_atomfirmware_get_fw_reserved_fb_size(struct amdgpu_device *adev);
index 43e7b61..ada7bc1 100644 (file)
@@ -299,6 +299,9 @@ int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
                                  ip->major, ip->minor,
                                  ip->revision);
 
+                       if (le16_to_cpu(ip->hw_id) == VCN_HWID)
+                               adev->vcn.num_vcn_inst++;
+
                        for (k = 0; k < num_base_address; k++) {
                                /*
                                 * convert the endianness of base addresses in place,
@@ -385,7 +388,7 @@ void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev)
 {
        struct binary_header *bhdr;
        struct harvest_table *harvest_info;
-       int i;
+       int i, vcn_harvest_count = 0;
 
        bhdr = (struct binary_header *)adev->mman.discovery_bin;
        harvest_info = (struct harvest_table *)(adev->mman.discovery_bin +
@@ -397,8 +400,7 @@ void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev)
 
                switch (le32_to_cpu(harvest_info->list[i].hw_id)) {
                case VCN_HWID:
-                       adev->harvest_ip_mask |= AMD_HARVEST_IP_VCN_MASK;
-                       adev->harvest_ip_mask |= AMD_HARVEST_IP_JPEG_MASK;
+                       vcn_harvest_count++;
                        break;
                case DMU_HWID:
                        adev->harvest_ip_mask |= AMD_HARVEST_IP_DMU_MASK;
@@ -407,6 +409,10 @@ void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev)
                        break;
                }
        }
+       if (vcn_harvest_count == adev->vcn.num_vcn_inst) {
+               adev->harvest_ip_mask |= AMD_HARVEST_IP_VCN_MASK;
+               adev->harvest_ip_mask |= AMD_HARVEST_IP_JPEG_MASK;
+       }
 }
 
 int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev)
index 5ed8381..971c5b8 100644 (file)
@@ -1571,6 +1571,8 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev)
                pci_ignore_hotplug(pdev);
                pci_set_power_state(pdev, PCI_D3cold);
                drm_dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF;
+       } else if (amdgpu_device_supports_boco(drm_dev)) {
+               /* nothing to do */
        } else if (amdgpu_device_supports_baco(drm_dev)) {
                amdgpu_device_baco_enter(drm_dev);
        }
index f40c871..38222de 100644 (file)
@@ -26,6 +26,7 @@
 #include "amdgpu_ras.h"
 #include <linux/bits.h>
 #include "atom.h"
+#include "amdgpu_atomfirmware.h"
 
 #define EEPROM_I2C_TARGET_ADDR_VEGA20          0xA0
 #define EEPROM_I2C_TARGET_ADDR_ARCTURUS                0xA8
@@ -96,6 +97,9 @@ static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev,
        if (!i2c_addr)
                return false;
 
+       if (amdgpu_atomfirmware_ras_rom_addr(adev, (uint8_t*)i2c_addr))
+               return true;
+
        switch (adev->asic_type) {
        case CHIP_VEGA20:
                *i2c_addr = EEPROM_I2C_TARGET_ADDR_VEGA20;
index c7b364e..e883731 100644 (file)
@@ -3026,6 +3026,14 @@ svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size,
        pr_debug("svms 0x%p [0x%llx 0x%llx] nattr 0x%x\n", &p->svms, start,
                 start + size - 1, nattr);
 
+       /* Flush pending deferred work to avoid racing with deferred actions from
+        * previous memory map changes (e.g. munmap). Concurrent memory map changes
+        * can still race with get_attr because we don't hold the mmap lock. But that
+        * would be a race condition in the application anyway, and undefined
+        * behaviour is acceptable in that case.
+        */
+       flush_work(&p->svms.deferred_list_work);
+
        mmap_read_lock(mm);
        if (!svm_range_is_valid(mm, start, size)) {
                pr_debug("invalid range\n");
index c0ae73b..afa96c8 100644 (file)
@@ -9605,7 +9605,12 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
                } else if (amdgpu_freesync_vid_mode && aconnector &&
                           is_freesync_video_mode(&new_crtc_state->mode,
                                                  aconnector)) {
-                       set_freesync_fixed_config(dm_new_crtc_state);
+                       struct drm_display_mode *high_mode;
+
+                       high_mode = get_highest_refresh_rate_mode(aconnector, false);
+                       if (!drm_mode_equal(&new_crtc_state->mode, high_mode)) {
+                               set_freesync_fixed_config(dm_new_crtc_state);
+                       }
                }
 
                ret = dm_atomic_get_state(state, &dm_state);
index 40f617b..4aba0e8 100644 (file)
@@ -584,7 +584,7 @@ static void amdgpu_dm_irq_schedule_work(struct amdgpu_device *adev,
                handler_data = container_of(handler_list->next, struct amdgpu_dm_irq_handler_data, list);
 
                /*allocate a new amdgpu_dm_irq_handler_data*/
-               handler_data_add = kzalloc(sizeof(*handler_data), GFP_KERNEL);
+               handler_data_add = kzalloc(sizeof(*handler_data), GFP_ATOMIC);
                if (!handler_data_add) {
                        DRM_ERROR("DM_IRQ: failed to allocate irq handler!\n");
                        return;
index 605e297..a30283f 100644 (file)
@@ -1530,6 +1530,12 @@ void dc_z10_restore(struct dc *dc)
        if (dc->hwss.z10_restore)
                dc->hwss.z10_restore(dc);
 }
+
+void dc_z10_save_init(struct dc *dc)
+{
+       if (dc->hwss.z10_save_init)
+               dc->hwss.z10_save_init(dc);
+}
 #endif
 /*
  * Applies given context to HW and copy it into current context.
index f2b39ec..cde8ed2 100644 (file)
@@ -47,6 +47,9 @@ int dc_setup_system_context(struct dc *dc, struct dc_phy_addr_space_config *pa_c
                 */
                memcpy(&dc->vm_pa_config, pa_config, sizeof(struct dc_phy_addr_space_config));
                dc->vm_pa_config.valid = true;
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+               dc_z10_save_init(dc);
+#endif
        }
 
        return num_vmids;
index af7b601..21d7828 100644 (file)
@@ -1338,6 +1338,7 @@ void dc_hardware_release(struct dc *dc);
 bool dc_set_psr_allow_active(struct dc *dc, bool enable);
 #if defined(CONFIG_DRM_AMD_DC_DCN)
 void dc_z10_restore(struct dc *dc);
+void dc_z10_save_init(struct dc *dc);
 #endif
 
 bool dc_enable_dmub_notifications(struct dc *dc);
index 253654d..28e15eb 100644 (file)
@@ -1788,7 +1788,6 @@ static bool dcn30_split_stream_for_mpc_or_odm(
                }
                pri_pipe->next_odm_pipe = sec_pipe;
                sec_pipe->prev_odm_pipe = pri_pipe;
-               ASSERT(sec_pipe->top_pipe == NULL);
 
                if (!sec_pipe->top_pipe)
                        sec_pipe->stream_res.opp = pool->opps[pipe_idx];
index 9776d17..912285f 100644 (file)
@@ -1622,106 +1622,12 @@ static void dcn301_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *b
        dml_init_instance(&dc->dml, &dcn3_01_soc, &dcn3_01_ip, DML_PROJECT_DCN30);
 }
 
-static void calculate_wm_set_for_vlevel(
-               int vlevel,
-               struct wm_range_table_entry *table_entry,
-               struct dcn_watermarks *wm_set,
-               struct display_mode_lib *dml,
-               display_e2e_pipe_params_st *pipes,
-               int pipe_cnt)
-{
-       double dram_clock_change_latency_cached = dml->soc.dram_clock_change_latency_us;
-
-       ASSERT(vlevel < dml->soc.num_states);
-       /* only pipe 0 is read for voltage and dcf/soc clocks */
-       pipes[0].clks_cfg.voltage = vlevel;
-       pipes[0].clks_cfg.dcfclk_mhz = dml->soc.clock_limits[vlevel].dcfclk_mhz;
-       pipes[0].clks_cfg.socclk_mhz = dml->soc.clock_limits[vlevel].socclk_mhz;
-
-       dml->soc.dram_clock_change_latency_us = table_entry->pstate_latency_us;
-       dml->soc.sr_exit_time_us = table_entry->sr_exit_time_us;
-       dml->soc.sr_enter_plus_exit_time_us = table_entry->sr_enter_plus_exit_time_us;
-
-       wm_set->urgent_ns = get_wm_urgent(dml, pipes, pipe_cnt) * 1000;
-       wm_set->cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(dml, pipes, pipe_cnt) * 1000;
-       wm_set->cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(dml, pipes, pipe_cnt) * 1000;
-       wm_set->cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(dml, pipes, pipe_cnt) * 1000;
-       wm_set->pte_meta_urgent_ns = get_wm_memory_trip(dml, pipes, pipe_cnt) * 1000;
-       wm_set->frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(dml, pipes, pipe_cnt) * 1000;
-       wm_set->frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(dml, pipes, pipe_cnt) * 1000;
-       wm_set->urgent_latency_ns = get_urgent_latency(dml, pipes, pipe_cnt) * 1000;
-       dml->soc.dram_clock_change_latency_us = dram_clock_change_latency_cached;
-
-}
-
-static void dcn301_calculate_wm_and_dlg(
-               struct dc *dc, struct dc_state *context,
-               display_e2e_pipe_params_st *pipes,
-               int pipe_cnt,
-               int vlevel_req)
-{
-       int i, pipe_idx;
-       int vlevel, vlevel_max;
-       struct wm_range_table_entry *table_entry;
-       struct clk_bw_params *bw_params = dc->clk_mgr->bw_params;
-
-       ASSERT(bw_params);
-
-       vlevel_max = bw_params->clk_table.num_entries - 1;
-
-       /* WM Set D */
-       table_entry = &bw_params->wm_table.entries[WM_D];
-       if (table_entry->wm_type == WM_TYPE_RETRAINING)
-               vlevel = 0;
-       else
-               vlevel = vlevel_max;
-       calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.d,
-                                               &context->bw_ctx.dml, pipes, pipe_cnt);
-       /* WM Set C */
-       table_entry = &bw_params->wm_table.entries[WM_C];
-       vlevel = min(max(vlevel_req, 2), vlevel_max);
-       calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.c,
-                                               &context->bw_ctx.dml, pipes, pipe_cnt);
-       /* WM Set B */
-       table_entry = &bw_params->wm_table.entries[WM_B];
-       vlevel = min(max(vlevel_req, 1), vlevel_max);
-       calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.b,
-                                               &context->bw_ctx.dml, pipes, pipe_cnt);
-
-       /* WM Set A */
-       table_entry = &bw_params->wm_table.entries[WM_A];
-       vlevel = min(vlevel_req, vlevel_max);
-       calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.a,
-                                               &context->bw_ctx.dml, pipes, pipe_cnt);
-
-       for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
-               if (!context->res_ctx.pipe_ctx[i].stream)
-                       continue;
-
-               pipes[pipe_idx].clks_cfg.dispclk_mhz = get_dispclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt);
-               pipes[pipe_idx].clks_cfg.dppclk_mhz = get_dppclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
-
-               if (dc->config.forced_clocks) {
-                       pipes[pipe_idx].clks_cfg.dispclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dispclk_mhz;
-                       pipes[pipe_idx].clks_cfg.dppclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dppclk_mhz;
-               }
-               if (dc->debug.min_disp_clk_khz > pipes[pipe_idx].clks_cfg.dispclk_mhz * 1000)
-                       pipes[pipe_idx].clks_cfg.dispclk_mhz = dc->debug.min_disp_clk_khz / 1000.0;
-               if (dc->debug.min_dpp_clk_khz > pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000)
-                       pipes[pipe_idx].clks_cfg.dppclk_mhz = dc->debug.min_dpp_clk_khz / 1000.0;
-
-               pipe_idx++;
-       }
-
-       dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel);
-}
-
 static struct resource_funcs dcn301_res_pool_funcs = {
        .destroy = dcn301_destroy_resource_pool,
        .link_enc_create = dcn301_link_encoder_create,
        .panel_cntl_create = dcn301_panel_cntl_create,
        .validate_bandwidth = dcn30_validate_bandwidth,
-       .calculate_wm_and_dlg = dcn301_calculate_wm_and_dlg,
+       .calculate_wm_and_dlg = dcn30_calculate_wm_and_dlg,
        .update_soc_for_wm_a = dcn30_update_soc_for_wm_a,
        .populate_dml_pipes = dcn30_populate_dml_pipes_from_context,
        .acquire_idle_pipe_for_layer = dcn20_acquire_idle_pipe_for_layer,
index 6ac6faf..8a2119d 100644 (file)
@@ -404,6 +404,18 @@ void dcn31_update_info_frame(struct pipe_ctx *pipe_ctx)
                        &pipe_ctx->stream_res.encoder_info_frame);
        }
 }
+void dcn31_z10_save_init(struct dc *dc)
+{
+       union dmub_rb_cmd cmd;
+
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.dcn_restore.header.type = DMUB_CMD__IDLE_OPT;
+       cmd.dcn_restore.header.sub_type = DMUB_CMD__IDLE_OPT_DCN_SAVE_INIT;
+
+       dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
+       dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
+       dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
+}
 
 void dcn31_z10_restore(struct dc *dc)
 {
index 40dfebe..140435e 100644 (file)
@@ -44,6 +44,7 @@ void dcn31_enable_power_gating_plane(
 void dcn31_update_info_frame(struct pipe_ctx *pipe_ctx);
 
 void dcn31_z10_restore(struct dc *dc);
+void dcn31_z10_save_init(struct dc *dc);
 
 void dcn31_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on);
 int dcn31_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config);
index aaf2dbd..b30d923 100644 (file)
@@ -97,6 +97,7 @@ static const struct hw_sequencer_funcs dcn31_funcs = {
        .set_abm_immediate_disable = dcn21_set_abm_immediate_disable,
        .set_pipe = dcn21_set_pipe,
        .z10_restore = dcn31_z10_restore,
+       .z10_save_init = dcn31_z10_save_init,
        .is_abm_supported = dcn31_is_abm_supported,
        .set_disp_pattern_generator = dcn30_set_disp_pattern_generator,
        .update_visual_confirm_color = dcn20_update_visual_confirm_color,
index 5ab008e..ad5f2ad 100644 (file)
@@ -237,6 +237,7 @@ struct hw_sequencer_funcs {
                        int width, int height, int offset);
 
        void (*z10_restore)(struct dc *dc);
+       void (*z10_save_init)(struct dc *dc);
 
        void (*update_visual_confirm_color)(struct dc *dc,
                        struct pipe_ctx *pipe_ctx,
index 7c4734f..7fafb8d 100644 (file)
@@ -856,6 +856,11 @@ enum dmub_cmd_idle_opt_type {
         * DCN hardware restore.
         */
        DMUB_CMD__IDLE_OPT_DCN_RESTORE = 0,
+
+       /**
+        * DCN hardware save.
+        */
+       DMUB_CMD__IDLE_OPT_DCN_SAVE_INIT = 1
 };
 
 /**
index 3811e58..4495545 100644 (file)
@@ -590,7 +590,7 @@ struct atom_firmware_info_v3_4 {
        uint8_t  board_i2c_feature_id;            // enum of atom_board_i2c_feature_id_def
        uint8_t  board_i2c_feature_gpio_id;       // i2c id find in gpio_lut data table gpio_id
        uint8_t  board_i2c_feature_slave_addr;
-       uint8_t  reserved3;
+       uint8_t  ras_rom_i2c_slave_addr;
        uint16_t bootup_mvddq_mv;
        uint16_t bootup_mvpp_mv;
        uint32_t zfbstartaddrin16mb;
index 5627de7..c5e26d6 100644 (file)
@@ -111,7 +111,9 @@ typedef struct {
   uint32_t InWhisperMode        : 1;
   uint32_t spare0               : 1;
   uint32_t ZstateStatus         : 4;
-  uint32_t spare1               :12;
+  uint32_t spare1               : 4;
+  uint32_t DstateFun            : 4;
+  uint32_t DstateDev            : 4;
   // MP1_EXT_SCRATCH2
   uint32_t P2JobHandler         :24;
   uint32_t RsmuPmiP2FinishedCnt : 8;
index 2597910..02e8c6e 100644 (file)
@@ -5127,6 +5127,13 @@ static int vega10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
        return size;
 }
 
+static bool vega10_get_power_profile_mode_quirks(struct pp_hwmgr *hwmgr)
+{
+       struct amdgpu_device *adev = hwmgr->adev;
+
+       return (adev->pdev->device == 0x6860);
+}
+
 static int vega10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size)
 {
        struct vega10_hwmgr *data = hwmgr->backend;
@@ -5163,9 +5170,15 @@ static int vega10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, ui
        }
 
 out:
-       smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask,
+       if (vega10_get_power_profile_mode_quirks(hwmgr))
+               smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask,
+                                               1 << power_profile_mode,
+                                               NULL);
+       else
+               smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask,
                                                (!power_profile_mode) ? 0 : 1 << (power_profile_mode - 1),
                                                NULL);
+
        hwmgr->power_profile_mode = power_profile_mode;
 
        return 0;
index c751f71..d92dd2c 100644 (file)
@@ -353,8 +353,7 @@ static void sienna_cichlid_check_bxco_support(struct smu_context *smu)
        struct amdgpu_device *adev = smu->adev;
        uint32_t val;
 
-       if (powerplay_table->platform_caps & SMU_11_0_7_PP_PLATFORM_CAP_BACO ||
-           powerplay_table->platform_caps & SMU_11_0_7_PP_PLATFORM_CAP_MACO) {
+       if (powerplay_table->platform_caps & SMU_11_0_7_PP_PLATFORM_CAP_BACO) {
                val = RREG32_SOC15(NBIO, 0, mmRCC_BIF_STRAP0);
                smu_baco->platform_support =
                        (val & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) ? true :
index 18681dc..bcaaa08 100644 (file)
@@ -256,7 +256,7 @@ static int vangogh_tables_init(struct smu_context *smu)
        return 0;
 
 err3_out:
-       kfree(smu_table->clocks_table);
+       kfree(smu_table->watermarks_table);
 err2_out:
        kfree(smu_table->gpu_metrics_table);
 err1_out:
index d299079..5d82891 100644 (file)
@@ -855,8 +855,6 @@ static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
        req.request.sequence = req32.request.sequence;
        req.request.signal = req32.request.signal;
        err = drm_ioctl_kernel(file, drm_wait_vblank_ioctl, &req, DRM_UNLOCKED);
-       if (err)
-               return err;
 
        req32.reply.type = req.reply.type;
        req32.reply.sequence = req.reply.sequence;
@@ -865,7 +863,7 @@ static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
        if (copy_to_user(argp, &req32, sizeof(req32)))
                return -EFAULT;
 
-       return 0;
+       return err;
 }
 
 #if defined(CONFIG_X86)
index be716b5..00dade4 100644 (file)
@@ -2463,6 +2463,15 @@ static void intel_ddi_power_up_lanes(struct intel_encoder *encoder,
        }
 }
 
+/* Splitter enable for eDP MSO is limited to certain pipes. */
+static u8 intel_ddi_splitter_pipe_mask(struct drm_i915_private *i915)
+{
+       if (IS_ALDERLAKE_P(i915))
+               return BIT(PIPE_A) | BIT(PIPE_B);
+       else
+               return BIT(PIPE_A);
+}
+
 static void intel_ddi_mso_get_config(struct intel_encoder *encoder,
                                     struct intel_crtc_state *pipe_config)
 {
@@ -2480,8 +2489,7 @@ static void intel_ddi_mso_get_config(struct intel_encoder *encoder,
        if (!pipe_config->splitter.enable)
                return;
 
-       /* Splitter enable is supported for pipe A only. */
-       if (drm_WARN_ON(&i915->drm, pipe != PIPE_A)) {
+       if (drm_WARN_ON(&i915->drm, !(intel_ddi_splitter_pipe_mask(i915) & BIT(pipe)))) {
                pipe_config->splitter.enable = false;
                return;
        }
@@ -2513,10 +2521,6 @@ static void intel_ddi_mso_configure(const struct intel_crtc_state *crtc_state)
                return;
 
        if (crtc_state->splitter.enable) {
-               /* Splitter enable is supported for pipe A only. */
-               if (drm_WARN_ON(&i915->drm, pipe != PIPE_A))
-                       return;
-
                dss1 |= SPLITTER_ENABLE;
                dss1 |= OVERLAP_PIXELS(crtc_state->splitter.pixel_overlap);
                if (crtc_state->splitter.link_count == 2)
@@ -4743,12 +4747,8 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
 
                dig_port->hpd_pulse = intel_dp_hpd_pulse;
 
-               /* Splitter enable for eDP MSO is limited to certain pipes. */
-               if (dig_port->dp.mso_link_count) {
-                       encoder->pipe_mask = BIT(PIPE_A);
-                       if (IS_ALDERLAKE_P(dev_priv))
-                               encoder->pipe_mask |= BIT(PIPE_B);
-               }
+               if (dig_port->dp.mso_link_count)
+                       encoder->pipe_mask = intel_ddi_splitter_pipe_mask(dev_priv);
        }
 
        /* In theory we don't need the encoder->type check, but leave it just in
index 2d5d217..0a8a239 100644 (file)
@@ -5746,16 +5746,18 @@ static void bdw_set_pipemisc(const struct intel_crtc_state *crtc_state)
 
        switch (crtc_state->pipe_bpp) {
        case 18:
-               val |= PIPEMISC_DITHER_6_BPC;
+               val |= PIPEMISC_6_BPC;
                break;
        case 24:
-               val |= PIPEMISC_DITHER_8_BPC;
+               val |= PIPEMISC_8_BPC;
                break;
        case 30:
-               val |= PIPEMISC_DITHER_10_BPC;
+               val |= PIPEMISC_10_BPC;
                break;
        case 36:
-               val |= PIPEMISC_DITHER_12_BPC;
+               /* Port output 12BPC defined for ADLP+ */
+               if (DISPLAY_VER(dev_priv) > 12)
+                       val |= PIPEMISC_12_BPC_ADLP;
                break;
        default:
                MISSING_CASE(crtc_state->pipe_bpp);
@@ -5808,15 +5810,27 @@ int bdw_get_pipemisc_bpp(struct intel_crtc *crtc)
 
        tmp = intel_de_read(dev_priv, PIPEMISC(crtc->pipe));
 
-       switch (tmp & PIPEMISC_DITHER_BPC_MASK) {
-       case PIPEMISC_DITHER_6_BPC:
+       switch (tmp & PIPEMISC_BPC_MASK) {
+       case PIPEMISC_6_BPC:
                return 18;
-       case PIPEMISC_DITHER_8_BPC:
+       case PIPEMISC_8_BPC:
                return 24;
-       case PIPEMISC_DITHER_10_BPC:
+       case PIPEMISC_10_BPC:
                return 30;
-       case PIPEMISC_DITHER_12_BPC:
-               return 36;
+       /*
+        * PORT OUTPUT 12 BPC defined for ADLP+.
+        *
+        * TODO:
+        * For previous platforms with DSI interface, bits 5:7
+        * are used for storing pipe_bpp irrespective of dithering.
+        * Since the value of 12 BPC is not defined for these bits
+        * on older platforms, need to find a workaround for 12 BPC
+        * MIPI DSI HW readout.
+        */
+       case PIPEMISC_12_BPC_ADLP:
+               if (DISPLAY_VER(dev_priv) > 12)
+                       return 36;
+               fallthrough;
        default:
                MISSING_CASE(tmp);
                return 0;
index 4298ae6..86b7ac7 100644 (file)
@@ -6387,13 +6387,13 @@ void intel_display_power_suspend_late(struct drm_i915_private *i915)
        if (DISPLAY_VER(i915) >= 11 || IS_GEMINILAKE(i915) ||
            IS_BROXTON(i915)) {
                bxt_enable_dc9(i915);
-               /* Tweaked Wa_14010685332:icp,jsp,mcc */
-               if (INTEL_PCH_TYPE(i915) >= PCH_ICP && INTEL_PCH_TYPE(i915) <= PCH_MCC)
-                       intel_de_rmw(i915, SOUTH_CHICKEN1,
-                                    SBCLK_RUN_REFCLK_DIS, SBCLK_RUN_REFCLK_DIS);
        } else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) {
                hsw_enable_pc8(i915);
        }
+
+       /* Tweaked Wa_14010685332:cnp,icp,jsp,mcc,tgp,adp */
+       if (INTEL_PCH_TYPE(i915) >= PCH_CNP && INTEL_PCH_TYPE(i915) < PCH_DG1)
+               intel_de_rmw(i915, SOUTH_CHICKEN1, SBCLK_RUN_REFCLK_DIS, SBCLK_RUN_REFCLK_DIS);
 }
 
 void intel_display_power_resume_early(struct drm_i915_private *i915)
@@ -6402,13 +6402,13 @@ void intel_display_power_resume_early(struct drm_i915_private *i915)
            IS_BROXTON(i915)) {
                gen9_sanitize_dc_state(i915);
                bxt_disable_dc9(i915);
-               /* Tweaked Wa_14010685332:icp,jsp,mcc */
-               if (INTEL_PCH_TYPE(i915) >= PCH_ICP && INTEL_PCH_TYPE(i915) <= PCH_MCC)
-                       intel_de_rmw(i915, SOUTH_CHICKEN1, SBCLK_RUN_REFCLK_DIS, 0);
-
        } else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) {
                hsw_disable_pc8(i915);
        }
+
+       /* Tweaked Wa_14010685332:cnp,icp,jsp,mcc,tgp,adp */
+       if (INTEL_PCH_TYPE(i915) >= PCH_CNP && INTEL_PCH_TYPE(i915) < PCH_DG1)
+               intel_de_rmw(i915, SOUTH_CHICKEN1, SBCLK_RUN_REFCLK_DIS, 0);
 }
 
 void intel_display_power_suspend(struct drm_i915_private *i915)
index 08bceae..053a3c2 100644 (file)
@@ -206,7 +206,6 @@ int intel_dp_init_lttpr_and_dprx_caps(struct intel_dp *intel_dp)
 
        return lttpr_count;
 }
-EXPORT_SYMBOL(intel_dp_init_lttpr_and_dprx_caps);
 
 static u8 dp_voltage_max(u8 preemph)
 {
index 06024d3..cde0a47 100644 (file)
@@ -3149,6 +3149,7 @@ static int init_bdw_mmio_info(struct intel_gvt *gvt)
        MMIO_DFH(_MMIO(0xb100), D_BDW, F_CMD_ACCESS, NULL, NULL);
        MMIO_DFH(_MMIO(0xb10c), D_BDW, F_CMD_ACCESS, NULL, NULL);
        MMIO_D(_MMIO(0xb110), D_BDW);
+       MMIO_D(GEN9_SCRATCH_LNCF1, D_BDW_PLUS);
 
        MMIO_F(_MMIO(0x24d0), 48, F_CMD_ACCESS | F_CMD_WRITE_PATCH, 0, 0,
                D_BDW_PLUS, NULL, force_nonpriv_write);
index b8ac807..f776c47 100644 (file)
@@ -105,6 +105,8 @@ static struct engine_mmio gen9_engine_mmio_list[] __cacheline_aligned = {
        {RCS0, COMMON_SLICE_CHICKEN2, 0xffff, true}, /* 0x7014 */
        {RCS0, GEN9_CS_DEBUG_MODE1, 0xffff, false}, /* 0x20ec */
        {RCS0, GEN8_L3SQCREG4, 0, false}, /* 0xb118 */
+       {RCS0, GEN9_SCRATCH1, 0, false}, /* 0xb11c */
+       {RCS0, GEN9_SCRATCH_LNCF1, 0, false}, /* 0xb008 */
        {RCS0, GEN7_HALF_SLICE_CHICKEN1, 0xffff, true}, /* 0xe100 */
        {RCS0, HALF_SLICE_CHICKEN2, 0xffff, true}, /* 0xe180 */
        {RCS0, HALF_SLICE_CHICKEN3, 0xffff, true}, /* 0xe184 */
index 35c97c3..9666646 100644 (file)
@@ -727,9 +727,18 @@ static void err_print_gt(struct drm_i915_error_state_buf *m,
        if (GRAPHICS_VER(m->i915) >= 12) {
                int i;
 
-               for (i = 0; i < GEN12_SFC_DONE_MAX; i++)
+               for (i = 0; i < GEN12_SFC_DONE_MAX; i++) {
+                       /*
+                        * SFC_DONE resides in the VD forcewake domain, so it
+                        * only exists if the corresponding VCS engine is
+                        * present.
+                        */
+                       if (!HAS_ENGINE(gt->_gt, _VCS(i * 2)))
+                               continue;
+
                        err_printf(m, "  SFC_DONE[%d]: 0x%08x\n", i,
                                   gt->sfc_done[i]);
+               }
 
                err_printf(m, "  GAM_DONE: 0x%08x\n", gt->gam_done);
        }
@@ -1581,6 +1590,14 @@ static void gt_record_regs(struct intel_gt_coredump *gt)
 
        if (GRAPHICS_VER(i915) >= 12) {
                for (i = 0; i < GEN12_SFC_DONE_MAX; i++) {
+                       /*
+                        * SFC_DONE resides in the VD forcewake domain, so it
+                        * only exists if the corresponding VCS engine is
+                        * present.
+                        */
+                       if (!HAS_ENGINE(gt->_gt, _VCS(i * 2)))
+                               continue;
+
                        gt->sfc_done[i] =
                                intel_uncore_read(uncore, GEN12_SFC_DONE(i));
                }
index c039431..c3816f5 100644 (file)
@@ -3064,24 +3064,6 @@ static void valleyview_irq_reset(struct drm_i915_private *dev_priv)
        spin_unlock_irq(&dev_priv->irq_lock);
 }
 
-static void cnp_display_clock_wa(struct drm_i915_private *dev_priv)
-{
-       struct intel_uncore *uncore = &dev_priv->uncore;
-
-       /*
-        * Wa_14010685332:cnp/cmp,tgp,adp
-        * TODO: Clarify which platforms this applies to
-        * TODO: Figure out if this workaround can be applied in the s0ix suspend/resume handlers as
-        * on earlier platforms and whether the workaround is also needed for runtime suspend/resume
-        */
-       if (INTEL_PCH_TYPE(dev_priv) == PCH_CNP ||
-           (INTEL_PCH_TYPE(dev_priv) >= PCH_TGP && INTEL_PCH_TYPE(dev_priv) < PCH_DG1)) {
-               intel_uncore_rmw(uncore, SOUTH_CHICKEN1, SBCLK_RUN_REFCLK_DIS,
-                                SBCLK_RUN_REFCLK_DIS);
-               intel_uncore_rmw(uncore, SOUTH_CHICKEN1, SBCLK_RUN_REFCLK_DIS, 0);
-       }
-}
-
 static void gen8_display_irq_reset(struct drm_i915_private *dev_priv)
 {
        struct intel_uncore *uncore = &dev_priv->uncore;
@@ -3115,7 +3097,6 @@ static void gen8_irq_reset(struct drm_i915_private *dev_priv)
        if (HAS_PCH_SPLIT(dev_priv))
                ibx_irq_reset(dev_priv);
 
-       cnp_display_clock_wa(dev_priv);
 }
 
 static void gen11_display_irq_reset(struct drm_i915_private *dev_priv)
@@ -3159,8 +3140,6 @@ static void gen11_display_irq_reset(struct drm_i915_private *dev_priv)
 
        if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
                GEN3_IRQ_RESET(uncore, SDE);
-
-       cnp_display_clock_wa(dev_priv);
 }
 
 static void gen11_irq_reset(struct drm_i915_private *dev_priv)
index 41186c1..476bb3b 100644 (file)
@@ -6163,11 +6163,17 @@ enum {
 #define   PIPEMISC_HDR_MODE_PRECISION  (1 << 23) /* icl+ */
 #define   PIPEMISC_OUTPUT_COLORSPACE_YUV  (1 << 11)
 #define   PIPEMISC_PIXEL_ROUNDING_TRUNC        REG_BIT(8) /* tgl+ */
-#define   PIPEMISC_DITHER_BPC_MASK     (7 << 5)
-#define   PIPEMISC_DITHER_8_BPC                (0 << 5)
-#define   PIPEMISC_DITHER_10_BPC       (1 << 5)
-#define   PIPEMISC_DITHER_6_BPC                (2 << 5)
-#define   PIPEMISC_DITHER_12_BPC       (3 << 5)
+/*
+ * For Display < 13, Bits 5-7 of PIPE MISC represent DITHER BPC with
+ * valid values of: 6, 8, 10 BPC.
+ * ADLP+, the bits 5-7 represent PORT OUTPUT BPC with valid values of:
+ * 6, 8, 10, 12 BPC.
+ */
+#define   PIPEMISC_BPC_MASK            (7 << 5)
+#define   PIPEMISC_8_BPC               (0 << 5)
+#define   PIPEMISC_10_BPC              (1 << 5)
+#define   PIPEMISC_6_BPC               (2 << 5)
+#define   PIPEMISC_12_BPC_ADLP         (4 << 5) /* adlp+ */
 #define   PIPEMISC_DITHER_ENABLE       (1 << 4)
 #define   PIPEMISC_DITHER_TYPE_MASK    (3 << 2)
 #define   PIPEMISC_DITHER_TYPE_SP      (0 << 2)
index 6f4c80b..473f5bb 100644 (file)
@@ -133,6 +133,8 @@ static int mtk_disp_color_probe(struct platform_device *pdev)
 
 static int mtk_disp_color_remove(struct platform_device *pdev)
 {
+       component_del(&pdev->dev, &mtk_disp_color_component_ops);
+
        return 0;
 }
 
index fa9d799..5326989 100644 (file)
@@ -423,6 +423,8 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
 
 static int mtk_disp_ovl_remove(struct platform_device *pdev)
 {
+       component_del(&pdev->dev, &mtk_disp_ovl_component_ops);
+
        return 0;
 }
 
index bced555..e94738f 100644 (file)
@@ -605,11 +605,15 @@ static int mtk_dpi_bridge_atomic_check(struct drm_bridge *bridge,
                                       struct drm_crtc_state *crtc_state,
                                       struct drm_connector_state *conn_state)
 {
-       struct mtk_dpi *dpi = bridge->driver_private;
+       struct mtk_dpi *dpi = bridge_to_dpi(bridge);
        unsigned int out_bus_format;
 
        out_bus_format = bridge_state->output_bus_cfg.format;
 
+       if (out_bus_format == MEDIA_BUS_FMT_FIXED)
+               if (dpi->conf->num_output_fmts)
+                       out_bus_format = dpi->conf->output_fmts[0];
+
        dev_dbg(dpi->dev, "input format 0x%04x, output format 0x%04x\n",
                bridge_state->input_bus_cfg.format,
                bridge_state->output_bus_cfg.format);
index 474efb8..735efe7 100644 (file)
@@ -532,13 +532,10 @@ void mtk_drm_crtc_async_update(struct drm_crtc *crtc, struct drm_plane *plane,
                               struct drm_atomic_state *state)
 {
        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
-       const struct drm_plane_helper_funcs *plane_helper_funcs =
-                       plane->helper_private;
 
        if (!mtk_crtc->enabled)
                return;
 
-       plane_helper_funcs->atomic_update(plane, state);
        mtk_drm_crtc_update_config(mtk_crtc, false);
 }
 
index 75bc00e..50d2056 100644 (file)
@@ -34,6 +34,7 @@
 
 #define DISP_AAL_EN                            0x0000
 #define DISP_AAL_SIZE                          0x0030
+#define DISP_AAL_OUTPUT_SIZE                   0x04d8
 
 #define DISP_DITHER_EN                         0x0000
 #define DITHER_EN                              BIT(0)
@@ -197,6 +198,7 @@ static void mtk_aal_config(struct device *dev, unsigned int w,
        struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
 
        mtk_ddp_write(cmdq_pkt, w << 16 | h, &priv->cmdq_reg, priv->regs, DISP_AAL_SIZE);
+       mtk_ddp_write(cmdq_pkt, w << 16 | h, &priv->cmdq_reg, priv->regs, DISP_AAL_OUTPUT_SIZE);
 }
 
 static void mtk_aal_gamma_set(struct device *dev, struct drm_crtc_state *state)
index b5582dc..e6dcb34 100644 (file)
@@ -110,6 +110,35 @@ static int mtk_plane_atomic_async_check(struct drm_plane *plane,
                                                   true, true);
 }
 
+static void mtk_plane_update_new_state(struct drm_plane_state *new_state,
+                                      struct mtk_plane_state *mtk_plane_state)
+{
+       struct drm_framebuffer *fb = new_state->fb;
+       struct drm_gem_object *gem;
+       struct mtk_drm_gem_obj *mtk_gem;
+       unsigned int pitch, format;
+       dma_addr_t addr;
+
+       gem = fb->obj[0];
+       mtk_gem = to_mtk_gem_obj(gem);
+       addr = mtk_gem->dma_addr;
+       pitch = fb->pitches[0];
+       format = fb->format->format;
+
+       addr += (new_state->src.x1 >> 16) * fb->format->cpp[0];
+       addr += (new_state->src.y1 >> 16) * pitch;
+
+       mtk_plane_state->pending.enable = true;
+       mtk_plane_state->pending.pitch = pitch;
+       mtk_plane_state->pending.format = format;
+       mtk_plane_state->pending.addr = addr;
+       mtk_plane_state->pending.x = new_state->dst.x1;
+       mtk_plane_state->pending.y = new_state->dst.y1;
+       mtk_plane_state->pending.width = drm_rect_width(&new_state->dst);
+       mtk_plane_state->pending.height = drm_rect_height(&new_state->dst);
+       mtk_plane_state->pending.rotation = new_state->rotation;
+}
+
 static void mtk_plane_atomic_async_update(struct drm_plane *plane,
                                          struct drm_atomic_state *state)
 {
@@ -126,8 +155,10 @@ static void mtk_plane_atomic_async_update(struct drm_plane *plane,
        plane->state->src_h = new_state->src_h;
        plane->state->src_w = new_state->src_w;
        swap(plane->state->fb, new_state->fb);
-       new_plane_state->pending.async_dirty = true;
 
+       mtk_plane_update_new_state(new_state, new_plane_state);
+       wmb(); /* Make sure the above parameters are set before update */
+       new_plane_state->pending.async_dirty = true;
        mtk_drm_crtc_async_update(new_state->crtc, plane, state);
 }
 
@@ -189,14 +220,8 @@ static void mtk_plane_atomic_update(struct drm_plane *plane,
        struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
                                                                           plane);
        struct mtk_plane_state *mtk_plane_state = to_mtk_plane_state(new_state);
-       struct drm_crtc *crtc = new_state->crtc;
-       struct drm_framebuffer *fb = new_state->fb;
-       struct drm_gem_object *gem;
-       struct mtk_drm_gem_obj *mtk_gem;
-       unsigned int pitch, format;
-       dma_addr_t addr;
 
-       if (!crtc || WARN_ON(!fb))
+       if (!new_state->crtc || WARN_ON(!new_state->fb))
                return;
 
        if (!new_state->visible) {
@@ -204,24 +229,7 @@ static void mtk_plane_atomic_update(struct drm_plane *plane,
                return;
        }
 
-       gem = fb->obj[0];
-       mtk_gem = to_mtk_gem_obj(gem);
-       addr = mtk_gem->dma_addr;
-       pitch = fb->pitches[0];
-       format = fb->format->format;
-
-       addr += (new_state->src.x1 >> 16) * fb->format->cpp[0];
-       addr += (new_state->src.y1 >> 16) * pitch;
-
-       mtk_plane_state->pending.enable = true;
-       mtk_plane_state->pending.pitch = pitch;
-       mtk_plane_state->pending.format = format;
-       mtk_plane_state->pending.addr = addr;
-       mtk_plane_state->pending.x = new_state->dst.x1;
-       mtk_plane_state->pending.y = new_state->dst.y1;
-       mtk_plane_state->pending.width = drm_rect_width(&new_state->dst);
-       mtk_plane_state->pending.height = drm_rect_height(&new_state->dst);
-       mtk_plane_state->pending.rotation = new_state->rotation;
+       mtk_plane_update_new_state(new_state, mtk_plane_state);
        wmb(); /* Make sure the above parameters are set before update */
        mtk_plane_state->pending.dirty = true;
 }
index 446e796..0f3cafa 100644 (file)
 #define VPP_WRAP_OSD3_MATRIX_PRE_OFFSET2 0x3dbc
 #define VPP_WRAP_OSD3_MATRIX_EN_CTRL 0x3dbd
 
+/* osd1 HDR */
+#define OSD1_HDR2_CTRL 0x38a0
+#define OSD1_HDR2_CTRL_VDIN0_HDR2_TOP_EN       BIT(13)
+#define OSD1_HDR2_CTRL_REG_ONLY_MAT            BIT(16)
+
 /* osd2 scaler */
 #define OSD2_VSC_PHASE_STEP 0x3d00
 #define OSD2_VSC_INI_PHASE 0x3d01
index aede0c6..259f3e6 100644 (file)
@@ -425,9 +425,14 @@ void meson_viu_init(struct meson_drm *priv)
        if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
            meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
                meson_viu_load_matrix(priv);
-       else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+       else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
                meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff,
                                               true);
+               /* fix green/pink color distortion from vendor u-boot */
+               writel_bits_relaxed(OSD1_HDR2_CTRL_REG_ONLY_MAT |
+                               OSD1_HDR2_CTRL_VDIN0_HDR2_TOP_EN, 0,
+                               priv->io_base + _REG(OSD1_HDR2_CTRL));
+       }
 
        /* Initialize OSD1 fifo control register */
        reg = VIU_OSD_DDR_PRIORITY_URGENT |
index f949767..bcb0310 100644 (file)
@@ -2237,6 +2237,33 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
                interlock[NV50_DISP_INTERLOCK_CORE] = 0;
        }
 
+       /* Finish updating head(s)...
+        *
+        * NVD is rather picky about both where window assignments can change,
+        * *and* about certain core and window channel states matching.
+        *
+        * The EFI GOP driver on newer GPUs configures window channels with a
+        * different output format to what we do, and the core channel update
+        * in the assign_windows case above would result in a state mismatch.
+        *
+        * Delay some of the head update until after that point to workaround
+        * the issue.  This only affects the initial modeset.
+        *
+        * TODO: handle this better when adding flexible window mapping
+        */
+       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+               struct nv50_head_atom *asyh = nv50_head_atom(new_crtc_state);
+               struct nv50_head *head = nv50_head(crtc);
+
+               NV_ATOMIC(drm, "%s: set %04x (clr %04x)\n", crtc->name,
+                         asyh->set.mask, asyh->clr.mask);
+
+               if (asyh->set.mask) {
+                       nv50_head_flush_set_wndw(head, asyh);
+                       interlock[NV50_DISP_INTERLOCK_CORE] = 1;
+               }
+       }
+
        /* Update plane(s). */
        for_each_new_plane_in_state(state, plane, new_plane_state, i) {
                struct nv50_wndw_atom *asyw = nv50_wndw_atom(new_plane_state);
index ec361d1..d66f972 100644 (file)
@@ -50,11 +50,8 @@ nv50_head_flush_clr(struct nv50_head *head,
 }
 
 void
-nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh)
+nv50_head_flush_set_wndw(struct nv50_head *head, struct nv50_head_atom *asyh)
 {
-       if (asyh->set.view   ) head->func->view    (head, asyh);
-       if (asyh->set.mode   ) head->func->mode    (head, asyh);
-       if (asyh->set.core   ) head->func->core_set(head, asyh);
        if (asyh->set.olut   ) {
                asyh->olut.offset = nv50_lut_load(&head->olut,
                                                  asyh->olut.buffer,
@@ -62,6 +59,14 @@ nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh)
                                                  asyh->olut.load);
                head->func->olut_set(head, asyh);
        }
+}
+
+void
+nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh)
+{
+       if (asyh->set.view   ) head->func->view    (head, asyh);
+       if (asyh->set.mode   ) head->func->mode    (head, asyh);
+       if (asyh->set.core   ) head->func->core_set(head, asyh);
        if (asyh->set.curs   ) head->func->curs_set(head, asyh);
        if (asyh->set.base   ) head->func->base    (head, asyh);
        if (asyh->set.ovly   ) head->func->ovly    (head, asyh);
index dae841d..0bac6be 100644 (file)
@@ -21,6 +21,7 @@ struct nv50_head {
 
 struct nv50_head *nv50_head_create(struct drm_device *, int index);
 void nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh);
+void nv50_head_flush_set_wndw(struct nv50_head *head, struct nv50_head_atom *asyh);
 void nv50_head_flush_clr(struct nv50_head *head,
                         struct nv50_head_atom *asyh, bool flush);
 
index 0b86c44..59759c4 100644 (file)
@@ -4,7 +4,8 @@
 
 struct nv_device_v0 {
        __u8  version;
-       __u8  pad01[7];
+       __u8  priv;
+       __u8  pad02[6];
        __u64 device;   /* device identifier, ~0 for client default */
 };
 
index ba2c28e..c68cc95 100644 (file)
@@ -61,8 +61,6 @@
 #define NV10_CHANNEL_DMA                              /* cl506b.h */ 0x0000006e
 #define NV17_CHANNEL_DMA                              /* cl506b.h */ 0x0000176e
 #define NV40_CHANNEL_DMA                              /* cl506b.h */ 0x0000406e
-#define NV50_CHANNEL_DMA                              /* cl506e.h */ 0x0000506e
-#define G82_CHANNEL_DMA                               /* cl826e.h */ 0x0000826e
 
 #define NV50_CHANNEL_GPFIFO                           /* cl506f.h */ 0x0000506f
 #define G82_CHANNEL_GPFIFO                            /* cl826f.h */ 0x0000826f
index 347d2c0..5d9395e 100644 (file)
@@ -9,7 +9,6 @@ struct nvif_client {
        const struct nvif_driver *driver;
        u64 version;
        u8 route;
-       bool super;
 };
 
 int  nvif_client_ctor(struct nvif_client *parent, const char *name, u64 device,
index 8e85b93..7a3af05 100644 (file)
@@ -11,7 +11,7 @@ struct nvif_driver {
        void (*fini)(void *priv);
        int (*suspend)(void *priv);
        int (*resume)(void *priv);
-       int (*ioctl)(void *priv, bool super, void *data, u32 size, void **hack);
+       int (*ioctl)(void *priv, void *data, u32 size, void **hack);
        void __iomem *(*map)(void *priv, u64 handle, u32 size);
        void (*unmap)(void *priv, void __iomem *ptr, u32 size);
        bool keep;
index 5d7017f..2f86606 100644 (file)
@@ -13,7 +13,6 @@ struct nvkm_client {
        struct nvkm_client_notify *notify[32];
        struct rb_root objroot;
 
-       bool super;
        void *data;
        int (*ntfy)(const void *, u32, const void *, u32);
 
index 71ed147..f52918a 100644 (file)
@@ -4,5 +4,5 @@
 #include <core/os.h>
 struct nvkm_client;
 
-int nvkm_ioctl(struct nvkm_client *, bool, void *, u32, void **);
+int nvkm_ioctl(struct nvkm_client *, void *, u32, void **);
 #endif
index 0911e73..70e7887 100644 (file)
@@ -15,7 +15,6 @@ struct nvkm_vma {
        u8   refd:3; /* Current page type (index, or NONE for unreferenced). */
        bool used:1; /* Region allocated. */
        bool part:1; /* Region was split from an allocated region by map(). */
-       bool user:1; /* Region user-allocated. */
        bool busy:1; /* Region busy (for temporarily preventing user access). */
        bool mapped:1; /* Region contains valid pages. */
        struct nvkm_memory *memory; /* Memory currently mapped into VMA. */
index b45ec30..4107b70 100644 (file)
@@ -570,11 +570,9 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
        }
 
        client->route = NVDRM_OBJECT_ABI16;
-       client->super = true;
        ret = nvif_object_ctor(&chan->chan->user, "abi16Ntfy", info->handle,
                               NV_DMA_IN_MEMORY, &args, sizeof(args),
                               &ntfy->object);
-       client->super = false;
        client->route = NVDRM_OBJECT_NVIF;
        if (ret)
                goto done;
index 4036260..80099ef 100644 (file)
@@ -86,12 +86,6 @@ nouveau_channel_del(struct nouveau_channel **pchan)
        struct nouveau_channel *chan = *pchan;
        if (chan) {
                struct nouveau_cli *cli = (void *)chan->user.client;
-               bool super;
-
-               if (cli) {
-                       super = cli->base.super;
-                       cli->base.super = true;
-               }
 
                if (chan->fence)
                        nouveau_fence(chan->drm)->context_del(chan);
@@ -111,9 +105,6 @@ nouveau_channel_del(struct nouveau_channel **pchan)
                        nouveau_bo_unpin(chan->push.buffer);
                nouveau_bo_ref(NULL, &chan->push.buffer);
                kfree(chan);
-
-               if (cli)
-                       cli->base.super = super;
        }
        *pchan = NULL;
 }
@@ -512,20 +503,16 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
                    struct nouveau_channel **pchan)
 {
        struct nouveau_cli *cli = (void *)device->object.client;
-       bool super;
        int ret;
 
        /* hack until fencenv50 is fixed, and agp access relaxed */
-       super = cli->base.super;
-       cli->base.super = true;
-
        ret = nouveau_channel_ind(drm, device, arg0, priv, pchan);
        if (ret) {
                NV_PRINTK(dbg, cli, "ib channel create, %d\n", ret);
                ret = nouveau_channel_dma(drm, device, pchan);
                if (ret) {
                        NV_PRINTK(dbg, cli, "dma channel create, %d\n", ret);
-                       goto done;
+                       return ret;
                }
        }
 
@@ -533,15 +520,13 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
        if (ret) {
                NV_PRINTK(err, cli, "channel failed to initialise, %d\n", ret);
                nouveau_channel_del(pchan);
-               goto done;
+               return ret;
        }
 
        ret = nouveau_svmm_join((*pchan)->vmm->svmm, (*pchan)->inst);
        if (ret)
                nouveau_channel_del(pchan);
 
-done:
-       cli->base.super = super;
        return ret;
 }
 
index a616cf4..ba4cd5f 100644 (file)
@@ -244,6 +244,7 @@ nouveau_cli_init(struct nouveau_drm *drm, const char *sname,
        ret = nvif_device_ctor(&cli->base.object, "drmDevice", 0, NV_DEVICE,
                               &(struct nv_device_v0) {
                                        .device = ~0,
+                                       .priv = true,
                               }, sizeof(struct nv_device_v0),
                               &cli->device);
        if (ret) {
@@ -1086,8 +1087,6 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)
        if (ret)
                goto done;
 
-       cli->base.super = false;
-
        fpriv->driver_priv = cli;
 
        mutex_lock(&drm->client.mutex);
index 0de6549..2ca3207 100644 (file)
@@ -41,8 +41,6 @@ nouveau_mem_map(struct nouveau_mem *mem,
                struct gf100_vmm_map_v0 gf100;
        } args;
        u32 argc = 0;
-       bool super;
-       int ret;
 
        switch (vmm->object.oclass) {
        case NVIF_CLASS_VMM_NV04:
@@ -73,12 +71,7 @@ nouveau_mem_map(struct nouveau_mem *mem,
                return -ENOSYS;
        }
 
-       super = vmm->object.client->super;
-       vmm->object.client->super = true;
-       ret = nvif_vmm_map(vmm, vma->addr, mem->mem.size, &args, argc,
-                          &mem->mem, 0);
-       vmm->object.client->super = super;
-       return ret;
+       return nvif_vmm_map(vmm, vma->addr, mem->mem.size, &args, argc, &mem->mem, 0);
 }
 
 void
@@ -99,7 +92,6 @@ nouveau_mem_host(struct ttm_resource *reg, struct ttm_tt *tt)
        struct nouveau_drm *drm = cli->drm;
        struct nvif_mmu *mmu = &cli->mmu;
        struct nvif_mem_ram_v0 args = {};
-       bool super = cli->base.super;
        u8 type;
        int ret;
 
@@ -122,11 +114,9 @@ nouveau_mem_host(struct ttm_resource *reg, struct ttm_tt *tt)
                args.dma = tt->dma_address;
 
        mutex_lock(&drm->master.lock);
-       cli->base.super = true;
        ret = nvif_mem_ctor_type(mmu, "ttmHostMem", cli->mem->oclass, type, PAGE_SHIFT,
                                 reg->num_pages << PAGE_SHIFT,
                                 &args, sizeof(args), &mem->mem);
-       cli->base.super = super;
        mutex_unlock(&drm->master.lock);
        return ret;
 }
@@ -138,12 +128,10 @@ nouveau_mem_vram(struct ttm_resource *reg, bool contig, u8 page)
        struct nouveau_cli *cli = mem->cli;
        struct nouveau_drm *drm = cli->drm;
        struct nvif_mmu *mmu = &cli->mmu;
-       bool super = cli->base.super;
        u64 size = ALIGN(reg->num_pages << PAGE_SHIFT, 1 << page);
        int ret;
 
        mutex_lock(&drm->master.lock);
-       cli->base.super = true;
        switch (cli->mem->oclass) {
        case NVIF_CLASS_MEM_GF100:
                ret = nvif_mem_ctor_type(mmu, "ttmVram", cli->mem->oclass,
@@ -167,7 +155,6 @@ nouveau_mem_vram(struct ttm_resource *reg, bool contig, u8 page)
                WARN_ON(1);
                break;
        }
-       cli->base.super = super;
        mutex_unlock(&drm->master.lock);
 
        reg->start = mem->mem.addr >> PAGE_SHIFT;
index b3f29b1..52f5793 100644 (file)
@@ -52,9 +52,9 @@ nvkm_client_map(void *priv, u64 handle, u32 size)
 }
 
 static int
-nvkm_client_ioctl(void *priv, bool super, void *data, u32 size, void **hack)
+nvkm_client_ioctl(void *priv, void *data, u32 size, void **hack)
 {
-       return nvkm_ioctl(priv, super, data, size, hack);
+       return nvkm_ioctl(priv, data, size, hack);
 }
 
 static int
index 82b583f..b0c3422 100644 (file)
@@ -237,14 +237,11 @@ void
 nouveau_svmm_invalidate(struct nouveau_svmm *svmm, u64 start, u64 limit)
 {
        if (limit > start) {
-               bool super = svmm->vmm->vmm.object.client->super;
-               svmm->vmm->vmm.object.client->super = true;
                nvif_object_mthd(&svmm->vmm->vmm.object, NVIF_VMM_V0_PFNCLR,
                                 &(struct nvif_vmm_pfnclr_v0) {
                                        .addr = start,
                                        .size = limit - start,
                                 }, sizeof(struct nvif_vmm_pfnclr_v0));
-               svmm->vmm->vmm.object.client->super = super;
        }
 }
 
@@ -634,9 +631,7 @@ static int nouveau_atomic_range_fault(struct nouveau_svmm *svmm,
                NVIF_VMM_PFNMAP_V0_A |
                NVIF_VMM_PFNMAP_V0_HOST;
 
-       svmm->vmm->vmm.object.client->super = true;
        ret = nvif_object_ioctl(&svmm->vmm->vmm.object, args, size, NULL);
-       svmm->vmm->vmm.object.client->super = false;
        mutex_unlock(&svmm->mutex);
 
        unlock_page(page);
@@ -702,9 +697,7 @@ static int nouveau_range_fault(struct nouveau_svmm *svmm,
 
        nouveau_hmm_convert_pfn(drm, &range, args);
 
-       svmm->vmm->vmm.object.client->super = true;
        ret = nvif_object_ioctl(&svmm->vmm->vmm.object, args, size, NULL);
-       svmm->vmm->vmm.object.client->super = false;
        mutex_unlock(&svmm->mutex);
 
 out:
@@ -928,10 +921,8 @@ nouveau_pfns_map(struct nouveau_svmm *svmm, struct mm_struct *mm,
 
        mutex_lock(&svmm->mutex);
 
-       svmm->vmm->vmm.object.client->super = true;
        ret = nvif_object_ioctl(&svmm->vmm->vmm.object, args, sizeof(*args) +
                                npages * sizeof(args->p.phys[0]), NULL);
-       svmm->vmm->vmm.object.client->super = false;
 
        mutex_unlock(&svmm->mutex);
 }
index 9dc10b1..5da1f4d 100644 (file)
@@ -32,6 +32,9 @@
 #include <nvif/event.h>
 #include <nvif/ioctl.h>
 
+#include <nvif/class.h>
+#include <nvif/cl0080.h>
+
 struct usif_notify_p {
        struct drm_pending_event base;
        struct {
@@ -261,7 +264,7 @@ usif_object_dtor(struct usif_object *object)
 }
 
 static int
-usif_object_new(struct drm_file *f, void *data, u32 size, void *argv, u32 argc)
+usif_object_new(struct drm_file *f, void *data, u32 size, void *argv, u32 argc, bool parent_abi16)
 {
        struct nouveau_cli *cli = nouveau_cli(f);
        struct nvif_client *client = &cli->base;
@@ -271,23 +274,48 @@ usif_object_new(struct drm_file *f, void *data, u32 size, void *argv, u32 argc)
        struct usif_object *object;
        int ret = -ENOSYS;
 
+       if ((ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true)))
+               return ret;
+
+       switch (args->v0.oclass) {
+       case NV_DMA_FROM_MEMORY:
+       case NV_DMA_TO_MEMORY:
+       case NV_DMA_IN_MEMORY:
+               return -EINVAL;
+       case NV_DEVICE: {
+               union {
+                       struct nv_device_v0 v0;
+               } *args = data;
+
+               if ((ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false)))
+                       return ret;
+
+               args->v0.priv = false;
+               break;
+       }
+       default:
+               if (!parent_abi16)
+                       return -EINVAL;
+               break;
+       }
+
        if (!(object = kmalloc(sizeof(*object), GFP_KERNEL)))
                return -ENOMEM;
        list_add(&object->head, &cli->objects);
 
-       if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
-               object->route = args->v0.route;
-               object->token = args->v0.token;
-               args->v0.route = NVDRM_OBJECT_USIF;
-               args->v0.token = (unsigned long)(void *)object;
-               ret = nvif_client_ioctl(client, argv, argc);
-               args->v0.token = object->token;
-               args->v0.route = object->route;
+       object->route = args->v0.route;
+       object->token = args->v0.token;
+       args->v0.route = NVDRM_OBJECT_USIF;
+       args->v0.token = (unsigned long)(void *)object;
+       ret = nvif_client_ioctl(client, argv, argc);
+       if (ret) {
+               usif_object_dtor(object);
+               return ret;
        }
 
-       if (ret)
-               usif_object_dtor(object);
-       return ret;
+       args->v0.token = object->token;
+       args->v0.route = object->route;
+       return 0;
 }
 
 int
@@ -301,6 +329,7 @@ usif_ioctl(struct drm_file *filp, void __user *user, u32 argc)
                struct nvif_ioctl_v0 v0;
        } *argv = data;
        struct usif_object *object;
+       bool abi16 = false;
        u8 owner;
        int ret;
 
@@ -331,11 +360,13 @@ usif_ioctl(struct drm_file *filp, void __user *user, u32 argc)
                        mutex_unlock(&cli->mutex);
                        goto done;
                }
+
+               abi16 = true;
        }
 
        switch (argv->v0.type) {
        case NVIF_IOCTL_V0_NEW:
-               ret = usif_object_new(filp, data, size, argv, argc);
+               ret = usif_object_new(filp, data, size, argv, argc, abi16);
                break;
        case NVIF_IOCTL_V0_NTFY_NEW:
                ret = usif_notify_new(filp, data, size, argv, argc);
index 12644f8..a3264a0 100644 (file)
@@ -32,7 +32,7 @@
 int
 nvif_client_ioctl(struct nvif_client *client, void *data, u32 size)
 {
-       return client->driver->ioctl(client->object.priv, client->super, data, size, NULL);
+       return client->driver->ioctl(client->object.priv, data, size, NULL);
 }
 
 int
@@ -80,7 +80,6 @@ nvif_client_ctor(struct nvif_client *parent, const char *name, u64 device,
        client->object.client = client;
        client->object.handle = ~0;
        client->route = NVIF_IOCTL_V0_ROUTE_NVIF;
-       client->super = true;
        client->driver = parent->driver;
 
        if (ret == 0) {
index 671a5c0..dce1ece 100644 (file)
@@ -44,8 +44,7 @@ nvif_object_ioctl(struct nvif_object *object, void *data, u32 size, void **hack)
        } else
                return -ENOSYS;
 
-       return client->driver->ioctl(client->object.priv, client->super,
-                                    data, size, hack);
+       return client->driver->ioctl(client->object.priv, data, size, hack);
 }
 
 void
index d777df5..735cb68 100644 (file)
@@ -426,8 +426,7 @@ nvkm_ioctl_path(struct nvkm_client *client, u64 handle, u32 type,
 }
 
 int
-nvkm_ioctl(struct nvkm_client *client, bool supervisor,
-          void *data, u32 size, void **hack)
+nvkm_ioctl(struct nvkm_client *client, void *data, u32 size, void **hack)
 {
        struct nvkm_object *object = &client->object;
        union {
@@ -435,7 +434,6 @@ nvkm_ioctl(struct nvkm_client *client, bool supervisor,
        } *args = data;
        int ret = -ENOSYS;
 
-       client->super = supervisor;
        nvif_ioctl(object, "size %d\n", size);
 
        if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
index b930f53..93ddf63 100644 (file)
@@ -2624,6 +2624,26 @@ nv174_chipset = {
        .dma      = { 0x00000001, gv100_dma_new },
 };
 
+static const struct nvkm_device_chip
+nv177_chipset = {
+       .name = "GA107",
+       .bar      = { 0x00000001, tu102_bar_new },
+       .bios     = { 0x00000001, nvkm_bios_new },
+       .devinit  = { 0x00000001, ga100_devinit_new },
+       .fb       = { 0x00000001, ga102_fb_new },
+       .gpio     = { 0x00000001, ga102_gpio_new },
+       .i2c      = { 0x00000001, gm200_i2c_new },
+       .imem     = { 0x00000001, nv50_instmem_new },
+       .mc       = { 0x00000001, ga100_mc_new },
+       .mmu      = { 0x00000001, tu102_mmu_new },
+       .pci      = { 0x00000001, gp100_pci_new },
+       .privring = { 0x00000001, gm200_privring_new },
+       .timer    = { 0x00000001, gk20a_timer_new },
+       .top      = { 0x00000001, ga100_top_new },
+       .disp     = { 0x00000001, ga102_disp_new },
+       .dma      = { 0x00000001, gv100_dma_new },
+};
+
 static int
 nvkm_device_event_ctor(struct nvkm_object *object, void *data, u32 size,
                       struct nvkm_notify *notify)
@@ -3049,6 +3069,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
                case 0x168: device->chip = &nv168_chipset; break;
                case 0x172: device->chip = &nv172_chipset; break;
                case 0x174: device->chip = &nv174_chipset; break;
+               case 0x177: device->chip = &nv177_chipset; break;
                default:
                        if (nvkm_boolopt(device->cfgopt, "NvEnableUnsupportedChipsets", false)) {
                                switch (device->chipset) {
index fea9d8f..f28894f 100644 (file)
@@ -397,7 +397,7 @@ nvkm_udevice_new(const struct nvkm_oclass *oclass, void *data, u32 size,
                return ret;
 
        /* give priviledged clients register access */
-       if (client->super)
+       if (args->v0.priv)
                func = &nvkm_udevice_super;
        else
                func = &nvkm_udevice;
index 55fbfe2..9669472 100644 (file)
@@ -440,7 +440,7 @@ nvkm_dp_train(struct nvkm_dp *dp, u32 dataKBps)
        return ret;
 }
 
-static void
+void
 nvkm_dp_disable(struct nvkm_outp *outp, struct nvkm_ior *ior)
 {
        struct nvkm_dp *dp = nvkm_dp(outp);
index 428b3f4..e484d0c 100644 (file)
@@ -32,6 +32,7 @@ struct nvkm_dp {
 
 int nvkm_dp_new(struct nvkm_disp *, int index, struct dcb_output *,
                struct nvkm_outp **);
+void nvkm_dp_disable(struct nvkm_outp *, struct nvkm_ior *);
 
 /* DPCD Receiver Capabilities */
 #define DPCD_RC00_DPCD_REV                                              0x00000
index dffcac2..129982f 100644 (file)
@@ -22,6 +22,7 @@
  * Authors: Ben Skeggs
  */
 #include "outp.h"
+#include "dp.h"
 #include "ior.h"
 
 #include <subdev/bios.h>
@@ -257,6 +258,14 @@ nvkm_outp_init_route(struct nvkm_outp *outp)
        if (!ior->arm.head || ior->arm.proto != proto) {
                OUTP_DBG(outp, "no heads (%x %d %d)", ior->arm.head,
                         ior->arm.proto, proto);
+
+               /* The EFI GOP driver on Ampere can leave unused DP links routed,
+                * which we don't expect.  The DisableLT IED script *should* get
+                * us back to where we need to be.
+                */
+               if (ior->func->route.get && !ior->arm.head && outp->info.type == DCB_OUTPUT_DP)
+                       nvkm_dp_disable(outp, ior);
+
                return;
        }
 
index d20cc06..797131e 100644 (file)
@@ -26,7 +26,6 @@
 #include <core/client.h>
 #include <core/gpuobj.h>
 #include <subdev/fb.h>
-#include <subdev/instmem.h>
 
 #include <nvif/cl0002.h>
 #include <nvif/unpack.h>
@@ -72,11 +71,7 @@ nvkm_dmaobj_ctor(const struct nvkm_dmaobj_func *func, struct nvkm_dma *dma,
        union {
                struct nv_dma_v0 v0;
        } *args = *pdata;
-       struct nvkm_device *device = dma->engine.subdev.device;
-       struct nvkm_client *client = oclass->client;
        struct nvkm_object *parent = oclass->parent;
-       struct nvkm_instmem *instmem = device->imem;
-       struct nvkm_fb *fb = device->fb;
        void *data = *pdata;
        u32 size = *psize;
        int ret = -ENOSYS;
@@ -109,23 +104,13 @@ nvkm_dmaobj_ctor(const struct nvkm_dmaobj_func *func, struct nvkm_dma *dma,
                dmaobj->target = NV_MEM_TARGET_VM;
                break;
        case NV_DMA_V0_TARGET_VRAM:
-               if (!client->super) {
-                       if (dmaobj->limit >= fb->ram->size - instmem->reserved)
-                               return -EACCES;
-                       if (device->card_type >= NV_50)
-                               return -EACCES;
-               }
                dmaobj->target = NV_MEM_TARGET_VRAM;
                break;
        case NV_DMA_V0_TARGET_PCI:
-               if (!client->super)
-                       return -EACCES;
                dmaobj->target = NV_MEM_TARGET_PCI;
                break;
        case NV_DMA_V0_TARGET_PCI_US:
        case NV_DMA_V0_TARGET_AGP:
-               if (!client->super)
-                       return -EACCES;
                dmaobj->target = NV_MEM_TARGET_PCI_NOSNOOP;
                break;
        default:
index 90e9a09..3209eb7 100644 (file)
@@ -27,8 +27,6 @@ nvkm-y += nvkm/engine/fifo/dmanv04.o
 nvkm-y += nvkm/engine/fifo/dmanv10.o
 nvkm-y += nvkm/engine/fifo/dmanv17.o
 nvkm-y += nvkm/engine/fifo/dmanv40.o
-nvkm-y += nvkm/engine/fifo/dmanv50.o
-nvkm-y += nvkm/engine/fifo/dmag84.o
 
 nvkm-y += nvkm/engine/fifo/gpfifonv50.o
 nvkm-y += nvkm/engine/fifo/gpfifog84.o
index af8bdf2..3a95730 100644 (file)
@@ -48,8 +48,6 @@ void nv50_fifo_chan_object_dtor(struct nvkm_fifo_chan *, int);
 int g84_fifo_chan_ctor(struct nv50_fifo *, u64 vmm, u64 push,
                       const struct nvkm_oclass *, struct nv50_fifo_chan *);
 
-extern const struct nvkm_fifo_chan_oclass nv50_fifo_dma_oclass;
 extern const struct nvkm_fifo_chan_oclass nv50_fifo_gpfifo_oclass;
-extern const struct nvkm_fifo_chan_oclass g84_fifo_dma_oclass;
 extern const struct nvkm_fifo_chan_oclass g84_fifo_gpfifo_oclass;
 #endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c
deleted file mode 100644 (file)
index fc34cdd..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2012 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: Ben Skeggs
- */
-#include "channv50.h"
-
-#include <core/client.h>
-#include <core/ramht.h>
-
-#include <nvif/class.h>
-#include <nvif/cl826e.h>
-#include <nvif/unpack.h>
-
-static int
-g84_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
-                void *data, u32 size, struct nvkm_object **pobject)
-{
-       struct nvkm_object *parent = oclass->parent;
-       union {
-               struct g82_channel_dma_v0 v0;
-       } *args = data;
-       struct nv50_fifo *fifo = nv50_fifo(base);
-       struct nv50_fifo_chan *chan;
-       int ret = -ENOSYS;
-
-       nvif_ioctl(parent, "create channel dma size %d\n", size);
-       if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
-               nvif_ioctl(parent, "create channel dma vers %d vmm %llx "
-                                  "pushbuf %llx offset %016llx\n",
-                          args->v0.version, args->v0.vmm, args->v0.pushbuf,
-                          args->v0.offset);
-               if (!args->v0.pushbuf)
-                       return -EINVAL;
-       } else
-               return ret;
-
-       if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
-               return -ENOMEM;
-       *pobject = &chan->base.object;
-
-       ret = g84_fifo_chan_ctor(fifo, args->v0.vmm, args->v0.pushbuf,
-                                oclass, chan);
-       if (ret)
-               return ret;
-
-       args->v0.chid = chan->base.chid;
-
-       nvkm_kmap(chan->ramfc);
-       nvkm_wo32(chan->ramfc, 0x08, lower_32_bits(args->v0.offset));
-       nvkm_wo32(chan->ramfc, 0x0c, upper_32_bits(args->v0.offset));
-       nvkm_wo32(chan->ramfc, 0x10, lower_32_bits(args->v0.offset));
-       nvkm_wo32(chan->ramfc, 0x14, upper_32_bits(args->v0.offset));
-       nvkm_wo32(chan->ramfc, 0x3c, 0x003f6078);
-       nvkm_wo32(chan->ramfc, 0x44, 0x01003fff);
-       nvkm_wo32(chan->ramfc, 0x48, chan->base.push->node->offset >> 4);
-       nvkm_wo32(chan->ramfc, 0x4c, 0xffffffff);
-       nvkm_wo32(chan->ramfc, 0x60, 0x7fffffff);
-       nvkm_wo32(chan->ramfc, 0x78, 0x00000000);
-       nvkm_wo32(chan->ramfc, 0x7c, 0x30000001);
-       nvkm_wo32(chan->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
-                                    (4 << 24) /* SEARCH_FULL */ |
-                                    (chan->ramht->gpuobj->node->offset >> 4));
-       nvkm_wo32(chan->ramfc, 0x88, chan->cache->addr >> 10);
-       nvkm_wo32(chan->ramfc, 0x98, chan->base.inst->addr >> 12);
-       nvkm_done(chan->ramfc);
-       return 0;
-}
-
-const struct nvkm_fifo_chan_oclass
-g84_fifo_dma_oclass = {
-       .base.oclass = G82_CHANNEL_DMA,
-       .base.minver = 0,
-       .base.maxver = 0,
-       .ctor = g84_fifo_dma_new,
-};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c
deleted file mode 100644 (file)
index 8043718..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2012 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: Ben Skeggs
- */
-#include "channv50.h"
-
-#include <core/client.h>
-#include <core/ramht.h>
-
-#include <nvif/class.h>
-#include <nvif/cl506e.h>
-#include <nvif/unpack.h>
-
-static int
-nv50_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
-                 void *data, u32 size, struct nvkm_object **pobject)
-{
-       struct nvkm_object *parent = oclass->parent;
-       union {
-               struct nv50_channel_dma_v0 v0;
-       } *args = data;
-       struct nv50_fifo *fifo = nv50_fifo(base);
-       struct nv50_fifo_chan *chan;
-       int ret = -ENOSYS;
-
-       nvif_ioctl(parent, "create channel dma size %d\n", size);
-       if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
-               nvif_ioctl(parent, "create channel dma vers %d vmm %llx "
-                                  "pushbuf %llx offset %016llx\n",
-                          args->v0.version, args->v0.vmm, args->v0.pushbuf,
-                          args->v0.offset);
-               if (!args->v0.pushbuf)
-                       return -EINVAL;
-       } else
-               return ret;
-
-       if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
-               return -ENOMEM;
-       *pobject = &chan->base.object;
-
-       ret = nv50_fifo_chan_ctor(fifo, args->v0.vmm, args->v0.pushbuf,
-                                 oclass, chan);
-       if (ret)
-               return ret;
-
-       args->v0.chid = chan->base.chid;
-
-       nvkm_kmap(chan->ramfc);
-       nvkm_wo32(chan->ramfc, 0x08, lower_32_bits(args->v0.offset));
-       nvkm_wo32(chan->ramfc, 0x0c, upper_32_bits(args->v0.offset));
-       nvkm_wo32(chan->ramfc, 0x10, lower_32_bits(args->v0.offset));
-       nvkm_wo32(chan->ramfc, 0x14, upper_32_bits(args->v0.offset));
-       nvkm_wo32(chan->ramfc, 0x3c, 0x003f6078);
-       nvkm_wo32(chan->ramfc, 0x44, 0x01003fff);
-       nvkm_wo32(chan->ramfc, 0x48, chan->base.push->node->offset >> 4);
-       nvkm_wo32(chan->ramfc, 0x4c, 0xffffffff);
-       nvkm_wo32(chan->ramfc, 0x60, 0x7fffffff);
-       nvkm_wo32(chan->ramfc, 0x78, 0x00000000);
-       nvkm_wo32(chan->ramfc, 0x7c, 0x30000001);
-       nvkm_wo32(chan->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
-                                    (4 << 24) /* SEARCH_FULL */ |
-                                    (chan->ramht->gpuobj->node->offset >> 4));
-       nvkm_done(chan->ramfc);
-       return 0;
-}
-
-const struct nvkm_fifo_chan_oclass
-nv50_fifo_dma_oclass = {
-       .base.oclass = NV50_CHANNEL_DMA,
-       .base.minver = 0,
-       .base.maxver = 0,
-       .ctor = nv50_fifo_dma_new,
-};
index c0a7d0f..3885c38 100644 (file)
@@ -119,7 +119,6 @@ g84_fifo = {
        .uevent_init = g84_fifo_uevent_init,
        .uevent_fini = g84_fifo_uevent_fini,
        .chan = {
-               &g84_fifo_dma_oclass,
                &g84_fifo_gpfifo_oclass,
                NULL
        },
index b6900a5..ae6c4d8 100644 (file)
@@ -341,8 +341,6 @@ gk104_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
                                   "runlist %016llx priv %d\n",
                           args->v0.version, args->v0.vmm, args->v0.ioffset,
                           args->v0.ilength, args->v0.runlist, args->v0.priv);
-               if (args->v0.priv && !oclass->client->super)
-                       return -EINVAL;
                return gk104_fifo_gpfifo_new_(fifo,
                                              &args->v0.runlist,
                                              &args->v0.chid,
index ee4967b..743791c 100644 (file)
@@ -226,8 +226,6 @@ gv100_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
                                   "runlist %016llx priv %d\n",
                           args->v0.version, args->v0.vmm, args->v0.ioffset,
                           args->v0.ilength, args->v0.runlist, args->v0.priv);
-               if (args->v0.priv && !oclass->client->super)
-                       return -EINVAL;
                return gv100_fifo_gpfifo_new_(&gv100_fifo_gpfifo, fifo,
                                              &args->v0.runlist,
                                              &args->v0.chid,
index abef7fb..99aafa1 100644 (file)
@@ -65,8 +65,6 @@ tu102_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
                                   "runlist %016llx priv %d\n",
                           args->v0.version, args->v0.vmm, args->v0.ioffset,
                           args->v0.ilength, args->v0.runlist, args->v0.priv);
-               if (args->v0.priv && !oclass->client->super)
-                       return -EINVAL;
                return gv100_fifo_gpfifo_new_(&tu102_fifo_gpfifo, fifo,
                                              &args->v0.runlist,
                                              &args->v0.chid,
index be94156..a08742c 100644 (file)
@@ -136,7 +136,6 @@ nv50_fifo = {
        .pause = nv04_fifo_pause,
        .start = nv04_fifo_start,
        .chan = {
-               &nv50_fifo_dma_oclass,
                &nv50_fifo_gpfifo_oclass,
                NULL
        },
index fac2f9a..e530bb8 100644 (file)
@@ -41,7 +41,7 @@ nvkm_umem_search(struct nvkm_client *client, u64 handle)
 
        object = nvkm_object_search(client, handle, &nvkm_umem);
        if (IS_ERR(object)) {
-               if (client->super && client != master) {
+               if (client != master) {
                        spin_lock(&master->lock);
                        list_for_each_entry(umem, &master->umem, head) {
                                if (umem->object.object == handle) {
@@ -53,8 +53,7 @@ nvkm_umem_search(struct nvkm_client *client, u64 handle)
                }
        } else {
                umem = nvkm_umem(object);
-               if (!umem->priv || client->super)
-                       memory = nvkm_memory_ref(umem->memory);
+               memory = nvkm_memory_ref(umem->memory);
        }
 
        return memory ? memory : ERR_PTR(-ENOENT);
@@ -167,7 +166,6 @@ nvkm_umem_new(const struct nvkm_oclass *oclass, void *argv, u32 argc,
        nvkm_object_ctor(&nvkm_umem, oclass, &umem->object);
        umem->mmu = mmu;
        umem->type = mmu->type[type].type;
-       umem->priv = oclass->client->super;
        INIT_LIST_HEAD(&umem->head);
        *pobject = &umem->object;
 
index 85cf692..d56a594 100644 (file)
@@ -8,7 +8,6 @@ struct nvkm_umem {
        struct nvkm_object object;
        struct nvkm_mmu *mmu;
        u8 type:8;
-       bool priv:1;
        bool mappable:1;
        bool io:1;
 
index 0e4b894..6870fda 100644 (file)
@@ -34,7 +34,7 @@ nvkm_ummu_sclass(struct nvkm_object *object, int index,
 {
        struct nvkm_mmu *mmu = nvkm_ummu(object)->mmu;
 
-       if (mmu->func->mem.user.oclass && oclass->client->super) {
+       if (mmu->func->mem.user.oclass) {
                if (index-- == 0) {
                        oclass->base = mmu->func->mem.user;
                        oclass->ctor = nvkm_umem_new;
index c43b824..d6a1f8d 100644 (file)
@@ -45,7 +45,6 @@ nvkm_uvmm_search(struct nvkm_client *client, u64 handle)
 static int
 nvkm_uvmm_mthd_pfnclr(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
 {
-       struct nvkm_client *client = uvmm->object.client;
        union {
                struct nvif_vmm_pfnclr_v0 v0;
        } *args = argv;
@@ -59,9 +58,6 @@ nvkm_uvmm_mthd_pfnclr(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
        } else
                return ret;
 
-       if (!client->super)
-               return -ENOENT;
-
        if (size) {
                mutex_lock(&vmm->mutex);
                ret = nvkm_vmm_pfn_unmap(vmm, addr, size);
@@ -74,7 +70,6 @@ nvkm_uvmm_mthd_pfnclr(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
 static int
 nvkm_uvmm_mthd_pfnmap(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
 {
-       struct nvkm_client *client = uvmm->object.client;
        union {
                struct nvif_vmm_pfnmap_v0 v0;
        } *args = argv;
@@ -93,9 +88,6 @@ nvkm_uvmm_mthd_pfnmap(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
        } else
                return ret;
 
-       if (!client->super)
-               return -ENOENT;
-
        if (size) {
                mutex_lock(&vmm->mutex);
                ret = nvkm_vmm_pfn_map(vmm, page, addr, size, phys);
@@ -108,7 +100,6 @@ nvkm_uvmm_mthd_pfnmap(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
 static int
 nvkm_uvmm_mthd_unmap(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
 {
-       struct nvkm_client *client = uvmm->object.client;
        union {
                struct nvif_vmm_unmap_v0 v0;
        } *args = argv;
@@ -130,9 +121,8 @@ nvkm_uvmm_mthd_unmap(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
                goto done;
        }
 
-       if (ret = -ENOENT, (!vma->user && !client->super) || vma->busy) {
-               VMM_DEBUG(vmm, "denied %016llx: %d %d %d", addr,
-                         vma->user, !client->super, vma->busy);
+       if (ret = -ENOENT, vma->busy) {
+               VMM_DEBUG(vmm, "denied %016llx: %d", addr, vma->busy);
                goto done;
        }
 
@@ -181,9 +171,8 @@ nvkm_uvmm_mthd_map(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
                goto fail;
        }
 
-       if (ret = -ENOENT, (!vma->user && !client->super) || vma->busy) {
-               VMM_DEBUG(vmm, "denied %016llx: %d %d %d", addr,
-                         vma->user, !client->super, vma->busy);
+       if (ret = -ENOENT, vma->busy) {
+               VMM_DEBUG(vmm, "denied %016llx: %d", addr, vma->busy);
                goto fail;
        }
 
@@ -230,7 +219,6 @@ fail:
 static int
 nvkm_uvmm_mthd_put(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
 {
-       struct nvkm_client *client = uvmm->object.client;
        union {
                struct nvif_vmm_put_v0 v0;
        } *args = argv;
@@ -252,9 +240,8 @@ nvkm_uvmm_mthd_put(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
                goto done;
        }
 
-       if (ret = -ENOENT, (!vma->user && !client->super) || vma->busy) {
-               VMM_DEBUG(vmm, "denied %016llx: %d %d %d", addr,
-                         vma->user, !client->super, vma->busy);
+       if (ret = -ENOENT, vma->busy) {
+               VMM_DEBUG(vmm, "denied %016llx: %d", addr, vma->busy);
                goto done;
        }
 
@@ -268,7 +255,6 @@ done:
 static int
 nvkm_uvmm_mthd_get(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
 {
-       struct nvkm_client *client = uvmm->object.client;
        union {
                struct nvif_vmm_get_v0 v0;
        } *args = argv;
@@ -297,7 +283,6 @@ nvkm_uvmm_mthd_get(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
                return ret;
 
        args->v0.addr = vma->addr;
-       vma->user = !client->super;
        return ret;
 }
 
index 710f3f8..8bf00b3 100644 (file)
@@ -774,7 +774,6 @@ nvkm_vma_tail(struct nvkm_vma *vma, u64 tail)
        new->refd = vma->refd;
        new->used = vma->used;
        new->part = vma->part;
-       new->user = vma->user;
        new->busy = vma->busy;
        new->mapped = vma->mapped;
        list_add(&new->head, &vma->head);
@@ -951,7 +950,7 @@ nvkm_vmm_node_split(struct nvkm_vmm *vmm,
 static void
 nvkm_vma_dump(struct nvkm_vma *vma)
 {
-       printk(KERN_ERR "%016llx %016llx %c%c%c%c%c%c%c%c%c %p\n",
+       printk(KERN_ERR "%016llx %016llx %c%c%c%c%c%c%c%c %p\n",
               vma->addr, (u64)vma->size,
               vma->used ? '-' : 'F',
               vma->mapref ? 'R' : '-',
@@ -959,7 +958,6 @@ nvkm_vma_dump(struct nvkm_vma *vma)
               vma->page != NVKM_VMA_PAGE_NONE ? '0' + vma->page : '-',
               vma->refd != NVKM_VMA_PAGE_NONE ? '0' + vma->refd : '-',
               vma->part ? 'P' : '-',
-              vma->user ? 'U' : '-',
               vma->busy ? 'B' : '-',
               vma->mapped ? 'M' : '-',
               vma->memory);
@@ -1024,7 +1022,6 @@ nvkm_vmm_ctor_managed(struct nvkm_vmm *vmm, u64 addr, u64 size)
        vma->mapref = true;
        vma->sparse = false;
        vma->used = true;
-       vma->user = true;
        nvkm_vmm_node_insert(vmm, vma);
        list_add_tail(&vma->head, &vmm->list);
        return 0;
@@ -1615,7 +1612,6 @@ nvkm_vmm_put_locked(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
        vma->page = NVKM_VMA_PAGE_NONE;
        vma->refd = NVKM_VMA_PAGE_NONE;
        vma->used = false;
-       vma->user = false;
        nvkm_vmm_put_region(vmm, vma);
 }
 
index f02abd9..b5e7337 100644 (file)
@@ -534,15 +534,13 @@ int
 gp100_vmm_mthd(struct nvkm_vmm *vmm,
               struct nvkm_client *client, u32 mthd, void *argv, u32 argc)
 {
-       if (client->super) {
-               switch (mthd) {
-               case GP100_VMM_VN_FAULT_REPLAY:
-                       return gp100_vmm_fault_replay(vmm, argv, argc);
-               case GP100_VMM_VN_FAULT_CANCEL:
-                       return gp100_vmm_fault_cancel(vmm, argv, argc);
-               default:
-                       break;
-               }
+       switch (mthd) {
+       case GP100_VMM_VN_FAULT_REPLAY:
+               return gp100_vmm_fault_replay(vmm, argv, argc);
+       case GP100_VMM_VN_FAULT_CANCEL:
+               return gp100_vmm_fault_cancel(vmm, argv, argc);
+       default:
+               break;
        }
        return -EINVAL;
 }
index 74e3b46..2df59b3 100644 (file)
@@ -78,9 +78,7 @@ static int ttm_global_init(void)
 
        ttm_debugfs_root = debugfs_create_dir("ttm", NULL);
        if (IS_ERR(ttm_debugfs_root)) {
-               ret = PTR_ERR(ttm_debugfs_root);
                ttm_debugfs_root = NULL;
-               goto out;
        }
 
        /* Limit the number of pages in the pool to about 50% of the total
index cceaf69..6304d1d 100644 (file)
@@ -1224,14 +1224,14 @@ static int bcm_iproc_i2c_unreg_slave(struct i2c_client *slave)
 
        disable_irq(iproc_i2c->irq);
 
+       tasklet_kill(&iproc_i2c->slave_rx_tasklet);
+
        /* disable all slave interrupts */
        tmp = iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET);
        tmp &= ~(IE_S_ALL_INTERRUPT_MASK <<
                        IE_S_ALL_INTERRUPT_SHIFT);
        iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, tmp);
 
-       tasklet_kill(&iproc_i2c->slave_rx_tasklet);
-
        /* Erase the slave address programmed */
        tmp = iproc_i2c_rd_reg(iproc_i2c, S_CFG_SMBUS_ADDR_OFFSET);
        tmp &= ~BIT(S_CFG_EN_NIC_SMB_ADDR3_SHIFT);
index cb64fe6..77f576e 100644 (file)
@@ -141,7 +141,7 @@ static ssize_t i2cdev_read(struct file *file, char __user *buf, size_t count,
        if (count > 8192)
                count = 8192;
 
-       tmp = kmalloc(count, GFP_KERNEL);
+       tmp = kzalloc(count, GFP_KERNEL);
        if (tmp == NULL)
                return -ENOMEM;
 
@@ -150,7 +150,8 @@ static ssize_t i2cdev_read(struct file *file, char __user *buf, size_t count,
 
        ret = i2c_master_recv(client, tmp, count);
        if (ret >= 0)
-               ret = copy_to_user(buf, tmp, count) ? -EFAULT : ret;
+               if (copy_to_user(buf, tmp, ret))
+                       ret = -EFAULT;
        kfree(tmp);
        return ret;
 }
index 0e56ace..8d8b1ba 100644 (file)
@@ -231,6 +231,7 @@ config DMARD10
 
 config FXLS8962AF
        tristate
+       depends on I2C || !I2C # cannot be built-in for modular I2C
 
 config FXLS8962AF_I2C
        tristate "NXP FXLS8962AF/FXLS8964AF Accelerometer I2C Driver"
@@ -247,6 +248,7 @@ config FXLS8962AF_I2C
 config FXLS8962AF_SPI
        tristate "NXP FXLS8962AF/FXLS8964AF Accelerometer SPI Driver"
        depends on SPI
+       depends on I2C || !I2C
        select FXLS8962AF
        select REGMAP_SPI
        help
index 078d878..0019f1e 100644 (file)
@@ -637,7 +637,7 @@ static int fxls8962af_i2c_raw_read_errata3(struct fxls8962af_data *data,
                        return ret;
        }
 
-       return ret;
+       return 0;
 }
 
 static int fxls8962af_fifo_transfer(struct fxls8962af_data *data,
index 6ef0960..f9c8385 100644 (file)
@@ -664,8 +664,8 @@ static int palmas_adc_wakeup_configure(struct palmas_gpadc *adc)
 
        adc_period = adc->auto_conversion_period;
        for (i = 0; i < 16; ++i) {
-               if (((1000 * (1 << i)) / 32) < adc_period)
-                       continue;
+               if (((1000 * (1 << i)) / 32) >= adc_period)
+                       break;
        }
        if (i > 0)
                i--;
index 2383eac..a2b83f0 100644 (file)
@@ -568,7 +568,6 @@ static int ti_ads7950_probe(struct spi_device *spi)
        st->ring_xfer.tx_buf = &st->tx_buf[0];
        st->ring_xfer.rx_buf = &st->rx_buf[0];
        /* len will be set later */
-       st->ring_xfer.cs_change = true;
 
        spi_message_add_tail(&st->ring_xfer, &st->ring_msg);
 
index 2a957f1..9e0fce9 100644 (file)
@@ -25,6 +25,8 @@
 #include <linux/iio/trigger_consumer.h>
 #include <linux/iio/triggered_buffer.h>
 
+#include <linux/time.h>
+
 #define HDC100X_REG_TEMP                       0x00
 #define HDC100X_REG_HUMIDITY                   0x01
 
@@ -166,7 +168,7 @@ static int hdc100x_get_measurement(struct hdc100x_data *data,
                                   struct iio_chan_spec const *chan)
 {
        struct i2c_client *client = data->client;
-       int delay = data->adc_int_us[chan->address];
+       int delay = data->adc_int_us[chan->address] + 1*USEC_PER_MSEC;
        int ret;
        __be16 val;
 
@@ -316,7 +318,7 @@ static irqreturn_t hdc100x_trigger_handler(int irq, void *p)
        struct iio_dev *indio_dev = pf->indio_dev;
        struct hdc100x_data *data = iio_priv(indio_dev);
        struct i2c_client *client = data->client;
-       int delay = data->adc_int_us[0] + data->adc_int_us[1];
+       int delay = data->adc_int_us[0] + data->adc_int_us[1] + 2*USEC_PER_MSEC;
        int ret;
 
        /* dual read starts at temp register */
index a5b421f..b9a06ca 100644 (file)
@@ -411,12 +411,11 @@ int __adis_initial_startup(struct adis *adis)
        int ret;
 
        /* check if the device has rst pin low */
-       gpio = devm_gpiod_get_optional(&adis->spi->dev, "reset", GPIOD_ASIS);
+       gpio = devm_gpiod_get_optional(&adis->spi->dev, "reset", GPIOD_OUT_HIGH);
        if (IS_ERR(gpio))
                return PTR_ERR(gpio);
 
        if (gpio) {
-               gpiod_set_value_cansleep(gpio, 1);
                msleep(10);
                /* bring device out of reset */
                gpiod_set_value_cansleep(gpio, 0);
index 7abeb57..b8e5e37 100644 (file)
@@ -945,7 +945,6 @@ int mlx5_ib_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
        u32 *cqb = NULL;
        void *cqc;
        int cqe_size;
-       unsigned int irqn;
        int eqn;
        int err;
 
@@ -984,7 +983,7 @@ int mlx5_ib_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
                INIT_WORK(&cq->notify_work, notify_soft_wc_handler);
        }
 
-       err = mlx5_vector2eqn(dev->mdev, vector, &eqn, &irqn);
+       err = mlx5_vector2eqn(dev->mdev, vector, &eqn);
        if (err)
                goto err_cqb;
 
@@ -1007,7 +1006,6 @@ int mlx5_ib_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
                goto err_cqb;
 
        mlx5_ib_dbg(dev, "cqn 0x%x\n", cq->mcq.cqn);
-       cq->mcq.irqn = irqn;
        if (udata)
                cq->mcq.tasklet_ctx.comp = mlx5_ib_cq_comp;
        else
index eb9b0a2..c869b2a 100644 (file)
@@ -975,7 +975,6 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_EQN)(
        struct mlx5_ib_dev *dev;
        int user_vector;
        int dev_eqn;
-       unsigned int irqn;
        int err;
 
        if (uverbs_copy_from(&user_vector, attrs,
@@ -987,7 +986,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_EQN)(
                return PTR_ERR(c);
        dev = to_mdev(c->ibucontext.device);
 
-       err = mlx5_vector2eqn(dev->mdev, user_vector, &dev_eqn, &irqn);
+       err = mlx5_vector2eqn(dev->mdev, user_vector, &dev_eqn);
        if (err < 0)
                return err;
 
index 27cc5f0..f6fae64 100644 (file)
@@ -20,18 +20,13 @@ void qcom_icc_pre_aggregate(struct icc_node *node)
 {
        size_t i;
        struct qcom_icc_node *qn;
-       struct qcom_icc_provider *qp;
 
        qn = node->data;
-       qp = to_qcom_provider(node->provider);
 
        for (i = 0; i < QCOM_ICC_NUM_BUCKETS; i++) {
                qn->sum_avg[i] = 0;
                qn->max_peak[i] = 0;
        }
-
-       for (i = 0; i < qn->num_bcms; i++)
-               qcom_icc_bcm_voter_add(qp->voter, qn->bcms[i]);
 }
 EXPORT_SYMBOL_GPL(qcom_icc_pre_aggregate);
 
@@ -49,8 +44,10 @@ int qcom_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
 {
        size_t i;
        struct qcom_icc_node *qn;
+       struct qcom_icc_provider *qp;
 
        qn = node->data;
+       qp = to_qcom_provider(node->provider);
 
        if (!tag)
                tag = QCOM_ICC_TAG_ALWAYS;
@@ -70,6 +67,9 @@ int qcom_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
        *agg_avg += avg_bw;
        *agg_peak = max_t(u32, *agg_peak, peak_bw);
 
+       for (i = 0; i < qn->num_bcms; i++)
+               qcom_icc_bcm_voter_add(qp->voter, qn->bcms[i]);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(qcom_icc_aggregate);
index 98ba927..6f0df62 100644 (file)
@@ -768,6 +768,7 @@ static void iommu_dma_free_noncontiguous(struct device *dev, size_t size,
        __iommu_dma_unmap(dev, sgt->sgl->dma_address, size);
        __iommu_dma_free_pages(sh->pages, PAGE_ALIGN(size) >> PAGE_SHIFT);
        sg_free_table(&sh->sgt);
+       kfree(sh);
 }
 #endif /* CONFIG_DMA_REMAP */
 
index c6cf44a..9ec374e 100644 (file)
@@ -511,7 +511,7 @@ void intel_pasid_tear_down_entry(struct intel_iommu *iommu, struct device *dev,
                                 u32 pasid, bool fault_ignore)
 {
        struct pasid_entry *pte;
-       u16 did;
+       u16 did, pgtt;
 
        pte = intel_pasid_get_entry(dev, pasid);
        if (WARN_ON(!pte))
@@ -521,13 +521,19 @@ void intel_pasid_tear_down_entry(struct intel_iommu *iommu, struct device *dev,
                return;
 
        did = pasid_get_domain_id(pte);
+       pgtt = pasid_pte_get_pgtt(pte);
+
        intel_pasid_clear_entry(dev, pasid, fault_ignore);
 
        if (!ecap_coherent(iommu->ecap))
                clflush_cache_range(pte, sizeof(*pte));
 
        pasid_cache_invalidation_with_pasid(iommu, did, pasid);
-       qi_flush_piotlb(iommu, did, pasid, 0, -1, 0);
+
+       if (pgtt == PASID_ENTRY_PGTT_PT || pgtt == PASID_ENTRY_PGTT_FL_ONLY)
+               qi_flush_piotlb(iommu, did, pasid, 0, -1, 0);
+       else
+               iommu->flush.flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH);
 
        /* Device IOTLB doesn't need to be flushed in caching mode. */
        if (!cap_caching_mode(iommu->cap))
index 5ff61c3..c11bc8b 100644 (file)
@@ -99,6 +99,12 @@ static inline bool pasid_pte_is_present(struct pasid_entry *pte)
        return READ_ONCE(pte->val[0]) & PASID_PTE_PRESENT;
 }
 
+/* Get PGTT field of a PASID table entry */
+static inline u16 pasid_pte_get_pgtt(struct pasid_entry *pte)
+{
+       return (u16)((READ_ONCE(pte->val[0]) >> 6) & 0x7);
+}
+
 extern unsigned int intel_pasid_max_id;
 int intel_pasid_alloc_table(struct device *dev);
 void intel_pasid_free_table(struct device *dev);
index 9b0f22b..4b9b3f3 100644 (file)
@@ -675,7 +675,6 @@ static int intel_svm_unbind_mm(struct device *dev, u32 pasid)
                        kfree_rcu(sdev, rcu);
 
                        if (list_empty(&svm->devs)) {
-                               intel_svm_free_pasid(mm);
                                if (svm->notifier.ops) {
                                        mmu_notifier_unregister(&svm->notifier, mm);
                                        /* Clear mm's pasid. */
@@ -690,6 +689,8 @@ static int intel_svm_unbind_mm(struct device *dev, u32 pasid)
                                kfree(svm);
                        }
                }
+               /* Drop a PASID reference and free it if no reference. */
+               intel_svm_free_pasid(mm);
        }
 out:
        return ret;
index 5419c4b..63f0af1 100644 (file)
@@ -924,6 +924,9 @@ void iommu_group_remove_device(struct device *dev)
        struct iommu_group *group = dev->iommu_group;
        struct group_device *tmp_device, *device = NULL;
 
+       if (!group)
+               return;
+
        dev_info(dev, "Removing from iommu group %d\n", group->id);
 
        /* Pre-notify listeners that a device is being removed. */
index 3461b0a..cbfdade 100644 (file)
@@ -89,16 +89,13 @@ static void tpci200_unregister(struct tpci200_board *tpci200)
        free_irq(tpci200->info->pdev->irq, (void *) tpci200);
 
        pci_iounmap(tpci200->info->pdev, tpci200->info->interface_regs);
-       pci_iounmap(tpci200->info->pdev, tpci200->info->cfg_regs);
 
        pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR);
        pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR);
        pci_release_region(tpci200->info->pdev, TPCI200_MEM16_SPACE_BAR);
        pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR);
-       pci_release_region(tpci200->info->pdev, TPCI200_CFG_MEM_BAR);
 
        pci_disable_device(tpci200->info->pdev);
-       pci_dev_put(tpci200->info->pdev);
 }
 
 static void tpci200_enable_irq(struct tpci200_board *tpci200,
@@ -257,7 +254,7 @@ static int tpci200_register(struct tpci200_board *tpci200)
                        "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 2 !",
                        tpci200->info->pdev->bus->number,
                        tpci200->info->pdev->devfn);
-               goto out_disable_pci;
+               goto err_disable_device;
        }
 
        /* Request IO ID INT space (Bar 3) */
@@ -269,7 +266,7 @@ static int tpci200_register(struct tpci200_board *tpci200)
                        "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 3 !",
                        tpci200->info->pdev->bus->number,
                        tpci200->info->pdev->devfn);
-               goto out_release_ip_space;
+               goto err_ip_interface_bar;
        }
 
        /* Request MEM8 space (Bar 5) */
@@ -280,7 +277,7 @@ static int tpci200_register(struct tpci200_board *tpci200)
                        "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 5!",
                        tpci200->info->pdev->bus->number,
                        tpci200->info->pdev->devfn);
-               goto out_release_ioid_int_space;
+               goto err_io_id_int_spaces_bar;
        }
 
        /* Request MEM16 space (Bar 4) */
@@ -291,7 +288,7 @@ static int tpci200_register(struct tpci200_board *tpci200)
                        "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 4!",
                        tpci200->info->pdev->bus->number,
                        tpci200->info->pdev->devfn);
-               goto out_release_mem8_space;
+               goto err_mem8_space_bar;
        }
 
        /* Map internal tpci200 driver user space */
@@ -305,7 +302,7 @@ static int tpci200_register(struct tpci200_board *tpci200)
                        tpci200->info->pdev->bus->number,
                        tpci200->info->pdev->devfn);
                res = -ENOMEM;
-               goto out_release_mem8_space;
+               goto err_mem16_space_bar;
        }
 
        /* Initialize lock that protects interface_regs */
@@ -344,18 +341,22 @@ static int tpci200_register(struct tpci200_board *tpci200)
                        "(bn 0x%X, sn 0x%X) unable to register IRQ !",
                        tpci200->info->pdev->bus->number,
                        tpci200->info->pdev->devfn);
-               goto out_release_ioid_int_space;
+               goto err_interface_regs;
        }
 
        return 0;
 
-out_release_mem8_space:
+err_interface_regs:
+       pci_iounmap(tpci200->info->pdev, tpci200->info->interface_regs);
+err_mem16_space_bar:
+       pci_release_region(tpci200->info->pdev, TPCI200_MEM16_SPACE_BAR);
+err_mem8_space_bar:
        pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR);
-out_release_ioid_int_space:
+err_io_id_int_spaces_bar:
        pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR);
-out_release_ip_space:
+err_ip_interface_bar:
        pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR);
-out_disable_pci:
+err_disable_device:
        pci_disable_device(tpci200->info->pdev);
        return res;
 }
@@ -527,7 +528,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
        tpci200->info = kzalloc(sizeof(struct tpci200_infos), GFP_KERNEL);
        if (!tpci200->info) {
                ret = -ENOMEM;
-               goto out_err_info;
+               goto err_tpci200;
        }
 
        pci_dev_get(pdev);
@@ -538,7 +539,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
        if (ret) {
                dev_err(&pdev->dev, "Failed to allocate PCI Configuration Memory");
                ret = -EBUSY;
-               goto out_err_pci_request;
+               goto err_tpci200_info;
        }
        tpci200->info->cfg_regs = ioremap(
                        pci_resource_start(pdev, TPCI200_CFG_MEM_BAR),
@@ -546,7 +547,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
        if (!tpci200->info->cfg_regs) {
                dev_err(&pdev->dev, "Failed to map PCI Configuration Memory");
                ret = -EFAULT;
-               goto out_err_ioremap;
+               goto err_request_region;
        }
 
        /* Disable byte swapping for 16 bit IP module access. This will ensure
@@ -569,7 +570,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
        if (ret) {
                dev_err(&pdev->dev, "error during tpci200 install\n");
                ret = -ENODEV;
-               goto out_err_install;
+               goto err_cfg_regs;
        }
 
        /* Register the carrier in the industry pack bus driver */
@@ -581,7 +582,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
                dev_err(&pdev->dev,
                        "error registering the carrier on ipack driver\n");
                ret = -EFAULT;
-               goto out_err_bus_register;
+               goto err_tpci200_install;
        }
 
        /* save the bus number given by ipack to logging purpose */
@@ -592,19 +593,16 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
                tpci200_create_device(tpci200, i);
        return 0;
 
-out_err_bus_register:
+err_tpci200_install:
        tpci200_uninstall(tpci200);
-       /* tpci200->info->cfg_regs is unmapped in tpci200_uninstall */
-       tpci200->info->cfg_regs = NULL;
-out_err_install:
-       if (tpci200->info->cfg_regs)
-               iounmap(tpci200->info->cfg_regs);
-out_err_ioremap:
+err_cfg_regs:
+       pci_iounmap(tpci200->info->pdev, tpci200->info->cfg_regs);
+err_request_region:
        pci_release_region(pdev, TPCI200_CFG_MEM_BAR);
-out_err_pci_request:
-       pci_dev_put(pdev);
+err_tpci200_info:
        kfree(tpci200->info);
-out_err_info:
+       pci_dev_put(pdev);
+err_tpci200:
        kfree(tpci200);
        return ret;
 }
@@ -614,6 +612,12 @@ static void __tpci200_pci_remove(struct tpci200_board *tpci200)
        ipack_bus_unregister(tpci200->info->ipack_bus);
        tpci200_uninstall(tpci200);
 
+       pci_iounmap(tpci200->info->pdev, tpci200->info->cfg_regs);
+
+       pci_release_region(tpci200->info->pdev, TPCI200_CFG_MEM_BAR);
+
+       pci_dev_put(tpci200->info->pdev);
+
        kfree(tpci200->info);
        kfree(tpci200);
 }
index d333130..c3229d8 100644 (file)
@@ -2018,8 +2018,8 @@ static void dw_mci_tasklet_func(struct tasklet_struct *t)
                                        continue;
                                }
 
-                               dw_mci_stop_dma(host);
                                send_stop_abort(host, data);
+                               dw_mci_stop_dma(host);
                                state = STATE_SENDING_STOP;
                                break;
                        }
@@ -2043,10 +2043,10 @@ static void dw_mci_tasklet_func(struct tasklet_struct *t)
                         */
                        if (test_and_clear_bit(EVENT_DATA_ERROR,
                                               &host->pending_events)) {
-                               dw_mci_stop_dma(host);
                                if (!(host->data_status & (SDMMC_INT_DRTO |
                                                           SDMMC_INT_EBE)))
                                        send_stop_abort(host, data);
+                               dw_mci_stop_dma(host);
                                state = STATE_DATA_ERROR;
                                break;
                        }
@@ -2079,10 +2079,10 @@ static void dw_mci_tasklet_func(struct tasklet_struct *t)
                         */
                        if (test_and_clear_bit(EVENT_DATA_ERROR,
                                               &host->pending_events)) {
-                               dw_mci_stop_dma(host);
                                if (!(host->data_status & (SDMMC_INT_DRTO |
                                                           SDMMC_INT_EBE)))
                                        send_stop_abort(host, data);
+                               dw_mci_stop_dma(host);
                                state = STATE_DATA_ERROR;
                                break;
                        }
index 51db30a..fdaa11f 100644 (file)
@@ -479,8 +479,9 @@ static int sdmmc_post_sig_volt_switch(struct mmci_host *host,
        u32 status;
        int ret = 0;
 
-       if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
-               spin_lock_irqsave(&host->lock, flags);
+       spin_lock_irqsave(&host->lock, flags);
+       if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180 &&
+           host->pwr_reg & MCI_STM32_VSWITCHEN) {
                mmci_write_pwrreg(host, host->pwr_reg | MCI_STM32_VSWITCH);
                spin_unlock_irqrestore(&host->lock, flags);
 
@@ -492,9 +493,11 @@ static int sdmmc_post_sig_volt_switch(struct mmci_host *host,
 
                writel_relaxed(MCI_STM32_VSWENDC | MCI_STM32_CKSTOPC,
                               host->base + MMCICLEAR);
+               spin_lock_irqsave(&host->lock, flags);
                mmci_write_pwrreg(host, host->pwr_reg &
                                  ~(MCI_STM32_VSWITCHEN | MCI_STM32_VSWITCH));
        }
+       spin_unlock_irqrestore(&host->lock, flags);
 
        return ret;
 }
index cce390f..e7565c6 100644 (file)
@@ -173,6 +173,23 @@ static unsigned int sdhci_iproc_get_max_clock(struct sdhci_host *host)
                return pltfm_host->clock;
 }
 
+/*
+ * There is a known bug on BCM2711's SDHCI core integration where the
+ * controller will hang when the difference between the core clock and the bus
+ * clock is too great. Specifically this can be reproduced under the following
+ * conditions:
+ *
+ *  - No SD card plugged in, polling thread is running, probing cards at
+ *    100 kHz.
+ *  - BCM2711's core clock configured at 500MHz or more
+ *
+ * So we set 200kHz as the minimum clock frequency available for that SoC.
+ */
+static unsigned int sdhci_iproc_bcm2711_get_min_clock(struct sdhci_host *host)
+{
+       return 200000;
+}
+
 static const struct sdhci_ops sdhci_iproc_ops = {
        .set_clock = sdhci_set_clock,
        .get_max_clock = sdhci_iproc_get_max_clock,
@@ -271,13 +288,15 @@ static const struct sdhci_ops sdhci_iproc_bcm2711_ops = {
        .set_clock = sdhci_set_clock,
        .set_power = sdhci_set_power_and_bus_voltage,
        .get_max_clock = sdhci_iproc_get_max_clock,
+       .get_min_clock = sdhci_iproc_bcm2711_get_min_clock,
        .set_bus_width = sdhci_set_bus_width,
        .reset = sdhci_reset,
        .set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
 static const struct sdhci_pltfm_data sdhci_bcm2711_pltfm_data = {
-       .quirks = SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,
+       .quirks = SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12 |
+                 SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
        .ops = &sdhci_iproc_bcm2711_ops,
 };
 
index e44b7a6..290a14c 100644 (file)
@@ -2089,6 +2089,23 @@ static void sdhci_msm_cqe_disable(struct mmc_host *mmc, bool recovery)
        sdhci_cqe_disable(mmc, recovery);
 }
 
+static void sdhci_msm_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)
+{
+       u32 count, start = 15;
+
+       __sdhci_set_timeout(host, cmd);
+       count = sdhci_readb(host, SDHCI_TIMEOUT_CONTROL);
+       /*
+        * Update software timeout value if its value is less than hardware data
+        * timeout value. Qcom SoC hardware data timeout value was calculated
+        * using 4 * MCLK * 2^(count + 13). where MCLK = 1 / host->clock.
+        */
+       if (cmd && cmd->data && host->clock > 400000 &&
+           host->clock <= 50000000 &&
+           ((1 << (count + start)) > (10 * host->clock)))
+               host->data_timeout = 22LL * NSEC_PER_SEC;
+}
+
 static const struct cqhci_host_ops sdhci_msm_cqhci_ops = {
        .enable         = sdhci_msm_cqe_enable,
        .disable        = sdhci_msm_cqe_disable,
@@ -2438,6 +2455,7 @@ static const struct sdhci_ops sdhci_msm_ops = {
        .irq    = sdhci_msm_cqe_irq,
        .dump_vendor_regs = sdhci_msm_dump_vendor_regs,
        .set_power = sdhci_set_power_noreg,
+       .set_timeout = sdhci_msm_set_timeout,
 };
 
 static const struct sdhci_pltfm_data sdhci_msm_pdata = {
index 3097e93..a761134 100644 (file)
@@ -119,7 +119,7 @@ static int cfi_use_status_reg(struct cfi_private *cfi)
        struct cfi_pri_amdstd *extp = cfi->cmdset_priv;
        u8 poll_mask = CFI_POLL_STATUS_REG | CFI_POLL_DQ;
 
-       return extp->MinorVersion >= '5' &&
+       return extp && extp->MinorVersion >= '5' &&
                (extp->SoftwareFeatures & poll_mask) == CFI_POLL_STATUS_REG;
 }
 
index efc2003..99400d0 100644 (file)
@@ -229,7 +229,7 @@ static int mchp48l640_write(struct mtd_info *mtd, loff_t to, size_t len,
                woff += ws;
        }
 
-       return ret;
+       return 0;
 }
 
 static int mchp48l640_read_page(struct mtd_info *mtd, loff_t from, size_t len,
@@ -255,6 +255,7 @@ static int mchp48l640_read_page(struct mtd_info *mtd, loff_t from, size_t len,
        if (!ret)
                *retlen += len;
 
+       kfree(cmd);
        return ret;
 
 fail:
@@ -286,7 +287,7 @@ static int mchp48l640_read(struct mtd_info *mtd, loff_t from, size_t len,
                woff += ws;
        }
 
-       return ret;
+       return 0;
 };
 
 static const struct mchp48_caps mchp48l640_caps = {
index 6ce4bc5..44bea3f 100644 (file)
@@ -419,6 +419,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
        if (tr->discard) {
                blk_queue_flag_set(QUEUE_FLAG_DISCARD, new->rq);
                blk_queue_max_discard_sectors(new->rq, UINT_MAX);
+               new->rq->limits.discard_granularity = tr->blksize;
        }
 
        gd->queue = new->rq;
@@ -525,14 +526,10 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
        if (!blktrans_notifier.list.next)
                register_mtd_user(&blktrans_notifier);
 
-
-       mutex_lock(&mtd_table_mutex);
-
        ret = register_blkdev(tr->major, tr->name);
        if (ret < 0) {
                printk(KERN_WARNING "Unable to register %s block device on major %d: %d\n",
                       tr->name, tr->major, ret);
-               mutex_unlock(&mtd_table_mutex);
                return ret;
        }
 
@@ -542,12 +539,12 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
        tr->blkshift = ffs(tr->blksize) - 1;
 
        INIT_LIST_HEAD(&tr->devs);
-       list_add(&tr->list, &blktrans_majors);
 
+       mutex_lock(&mtd_table_mutex);
+       list_add(&tr->list, &blktrans_majors);
        mtd_for_each_device(mtd)
                if (mtd->type != MTD_ABSENT)
                        tr->add_mtd(tr, mtd);
-
        mutex_unlock(&mtd_table_mutex);
        return 0;
 }
@@ -564,8 +561,8 @@ int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr)
        list_for_each_entry_safe(dev, next, &tr->devs, list)
                tr->remove_dev(dev);
 
-       unregister_blkdev(tr->major, tr->name);
        mutex_unlock(&mtd_table_mutex);
+       unregister_blkdev(tr->major, tr->name);
 
        BUG_ON(!list_empty(&tr->devs));
        return 0;
index b5ccd30..c8fd7f7 100644 (file)
@@ -806,7 +806,9 @@ static ssize_t mtd_otp_size(struct mtd_info *mtd, bool is_user)
 
 err:
        kfree(info);
-       return ret;
+
+       /* ENODATA means there is no OTP region. */
+       return ret == -ENODATA ? 0 : ret;
 }
 
 static struct nvmem_device *mtd_otp_nvmem_register(struct mtd_info *mtd,
index 57a5831..3d6c6e8 100644 (file)
@@ -5228,12 +5228,18 @@ static bool of_get_nand_on_flash_bbt(struct device_node *np)
 static int of_get_nand_secure_regions(struct nand_chip *chip)
 {
        struct device_node *dn = nand_get_flash_node(chip);
+       struct property *prop;
        int nr_elem, i, j;
 
-       nr_elem = of_property_count_elems_of_size(dn, "secure-regions", sizeof(u64));
-       if (!nr_elem)
+       /* Only proceed if the "secure-regions" property is present in DT */
+       prop = of_find_property(dn, "secure-regions", NULL);
+       if (!prop)
                return 0;
 
+       nr_elem = of_property_count_elems_of_size(dn, "secure-regions", sizeof(u64));
+       if (nr_elem <= 0)
+               return nr_elem;
+
        chip->nr_secure_regions = nr_elem / 2;
        chip->secure_regions = kcalloc(chip->nr_secure_regions, sizeof(*chip->secure_regions),
                                       GFP_KERNEL);
index a7ee0af..54e321a 100644 (file)
@@ -71,12 +71,18 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
                family = AF_INET6;
 
        if (bareudp->ethertype == htons(ETH_P_IP)) {
-               struct iphdr *iphdr;
+               __u8 ipversion;
 
-               iphdr = (struct iphdr *)(skb->data + BAREUDP_BASE_HLEN);
-               if (iphdr->version == 4) {
-                       proto = bareudp->ethertype;
-               } else if (bareudp->multi_proto_mode && (iphdr->version == 6)) {
+               if (skb_copy_bits(skb, BAREUDP_BASE_HLEN, &ipversion,
+                                 sizeof(ipversion))) {
+                       bareudp->dev->stats.rx_dropped++;
+                       goto drop;
+               }
+               ipversion >>= 4;
+
+               if (ipversion == 4) {
+                       proto = htons(ETH_P_IP);
+               } else if (ipversion == 6 && bareudp->multi_proto_mode) {
                        proto = htons(ETH_P_IPV6);
                } else {
                        bareudp->dev->stats.rx_dropped++;
index bba2a44..43bca31 100644 (file)
@@ -1164,10 +1164,10 @@ static int m_can_set_bittiming(struct net_device *dev)
                                    FIELD_PREP(TDCR_TDCO_MASK, tdco));
                }
 
-               reg_btp = FIELD_PREP(NBTP_NBRP_MASK, brp) |
-                         FIELD_PREP(NBTP_NSJW_MASK, sjw) |
-                         FIELD_PREP(NBTP_NTSEG1_MASK, tseg1) |
-                         FIELD_PREP(NBTP_NTSEG2_MASK, tseg2);
+               reg_btp |= FIELD_PREP(DBTP_DBRP_MASK, brp) |
+                       FIELD_PREP(DBTP_DSJW_MASK, sjw) |
+                       FIELD_PREP(DBTP_DTSEG1_MASK, tseg1) |
+                       FIELD_PREP(DBTP_DTSEG2_MASK, tseg2);
 
                m_can_write(cdev, M_CAN_DBTP, reg_btp);
        }
index 9fdcc4b..5c54ae1 100644 (file)
@@ -912,6 +912,7 @@ static int hellcreek_fdb_dump(struct dsa_switch *ds, int port,
 {
        struct hellcreek *hellcreek = ds->priv;
        u16 entries;
+       int ret = 0;
        size_t i;
 
        mutex_lock(&hellcreek->reg_lock);
@@ -943,12 +944,14 @@ static int hellcreek_fdb_dump(struct dsa_switch *ds, int port,
                if (!(entry.portmask & BIT(port)))
                        continue;
 
-               cb(entry.mac, 0, entry.is_static, data);
+               ret = cb(entry.mac, 0, entry.is_static, data);
+               if (ret)
+                       break;
        }
 
        mutex_unlock(&hellcreek->reg_lock);
 
-       return 0;
+       return ret;
 }
 
 static int hellcreek_vlan_filtering(struct dsa_switch *ds, int port,
index 3443740..d7ce281 100644 (file)
@@ -557,12 +557,12 @@ static int lan9303_alr_make_entry_raw(struct lan9303 *chip, u32 dat0, u32 dat1)
        return 0;
 }
 
-typedef void alr_loop_cb_t(struct lan9303 *chip, u32 dat0, u32 dat1,
-                          int portmap, void *ctx);
+typedef int alr_loop_cb_t(struct lan9303 *chip, u32 dat0, u32 dat1,
+                         int portmap, void *ctx);
 
-static void lan9303_alr_loop(struct lan9303 *chip, alr_loop_cb_t *cb, void *ctx)
+static int lan9303_alr_loop(struct lan9303 *chip, alr_loop_cb_t *cb, void *ctx)
 {
-       int i;
+       int ret = 0, i;
 
        mutex_lock(&chip->alr_mutex);
        lan9303_write_switch_reg(chip, LAN9303_SWE_ALR_CMD,
@@ -582,13 +582,17 @@ static void lan9303_alr_loop(struct lan9303 *chip, alr_loop_cb_t *cb, void *ctx)
                                                LAN9303_ALR_DAT1_PORT_BITOFFS;
                portmap = alrport_2_portmap[alrport];
 
-               cb(chip, dat0, dat1, portmap, ctx);
+               ret = cb(chip, dat0, dat1, portmap, ctx);
+               if (ret)
+                       break;
 
                lan9303_write_switch_reg(chip, LAN9303_SWE_ALR_CMD,
                                         LAN9303_ALR_CMD_GET_NEXT);
                lan9303_write_switch_reg(chip, LAN9303_SWE_ALR_CMD, 0);
        }
        mutex_unlock(&chip->alr_mutex);
+
+       return ret;
 }
 
 static void alr_reg_to_mac(u32 dat0, u32 dat1, u8 mac[6])
@@ -606,18 +610,20 @@ struct del_port_learned_ctx {
 };
 
 /* Clear learned (non-static) entry on given port */
-static void alr_loop_cb_del_port_learned(struct lan9303 *chip, u32 dat0,
-                                        u32 dat1, int portmap, void *ctx)
+static int alr_loop_cb_del_port_learned(struct lan9303 *chip, u32 dat0,
+                                       u32 dat1, int portmap, void *ctx)
 {
        struct del_port_learned_ctx *del_ctx = ctx;
        int port = del_ctx->port;
 
        if (((BIT(port) & portmap) == 0) || (dat1 & LAN9303_ALR_DAT1_STATIC))
-               return;
+               return 0;
 
        /* learned entries has only one port, we can just delete */
        dat1 &= ~LAN9303_ALR_DAT1_VALID; /* delete entry */
        lan9303_alr_make_entry_raw(chip, dat0, dat1);
+
+       return 0;
 }
 
 struct port_fdb_dump_ctx {
@@ -626,19 +632,19 @@ struct port_fdb_dump_ctx {
        dsa_fdb_dump_cb_t *cb;
 };
 
-static void alr_loop_cb_fdb_port_dump(struct lan9303 *chip, u32 dat0,
-                                     u32 dat1, int portmap, void *ctx)
+static int alr_loop_cb_fdb_port_dump(struct lan9303 *chip, u32 dat0,
+                                    u32 dat1, int portmap, void *ctx)
 {
        struct port_fdb_dump_ctx *dump_ctx = ctx;
        u8 mac[ETH_ALEN];
        bool is_static;
 
        if ((BIT(dump_ctx->port) & portmap) == 0)
-               return;
+               return 0;
 
        alr_reg_to_mac(dat0, dat1, mac);
        is_static = !!(dat1 & LAN9303_ALR_DAT1_STATIC);
-       dump_ctx->cb(mac, 0, is_static, dump_ctx->data);
+       return dump_ctx->cb(mac, 0, is_static, dump_ctx->data);
 }
 
 /* Set a static ALR entry. Delete entry if port_map is zero */
@@ -1210,9 +1216,7 @@ static int lan9303_port_fdb_dump(struct dsa_switch *ds, int port,
        };
 
        dev_dbg(chip->dev, "%s(%d)\n", __func__, port);
-       lan9303_alr_loop(chip, alr_loop_cb_fdb_port_dump, &dump_ctx);
-
-       return 0;
+       return lan9303_alr_loop(chip, alr_loop_cb_fdb_port_dump, &dump_ctx);
 }
 
 static int lan9303_port_mdb_prepare(struct dsa_switch *ds, int port,
index 314ae78..e78026e 100644 (file)
@@ -1404,11 +1404,17 @@ static int gswip_port_fdb_dump(struct dsa_switch *ds, int port,
                addr[1] = mac_bridge.key[2] & 0xff;
                addr[0] = (mac_bridge.key[2] >> 8) & 0xff;
                if (mac_bridge.val[1] & GSWIP_TABLE_MAC_BRIDGE_STATIC) {
-                       if (mac_bridge.val[0] & BIT(port))
-                               cb(addr, 0, true, data);
+                       if (mac_bridge.val[0] & BIT(port)) {
+                               err = cb(addr, 0, true, data);
+                               if (err)
+                                       return err;
+                       }
                } else {
-                       if (((mac_bridge.val[0] & GENMASK(7, 4)) >> 4) == port)
-                               cb(addr, 0, false, data);
+                       if (((mac_bridge.val[0] & GENMASK(7, 4)) >> 4) == port) {
+                               err = cb(addr, 0, false, data);
+                               if (err)
+                                       return err;
+                       }
                }
        }
        return 0;
index 560f684..c5142f8 100644 (file)
@@ -687,8 +687,8 @@ static void ksz8_r_vlan_entries(struct ksz_device *dev, u16 addr)
        shifts = ksz8->shifts;
 
        ksz8_r_table(dev, TABLE_VLAN, addr, &data);
-       addr *= dev->phy_port_cnt;
-       for (i = 0; i < dev->phy_port_cnt; i++) {
+       addr *= 4;
+       for (i = 0; i < 4; i++) {
                dev->vlan_cache[addr + i].table[0] = (u16)data;
                data >>= shifts[VLAN_TABLE];
        }
@@ -702,7 +702,7 @@ static void ksz8_r_vlan_table(struct ksz_device *dev, u16 vid, u16 *vlan)
        u64 buf;
 
        data = (u16 *)&buf;
-       addr = vid / dev->phy_port_cnt;
+       addr = vid / 4;
        index = vid & 3;
        ksz8_r_table(dev, TABLE_VLAN, addr, &buf);
        *vlan = data[index];
@@ -716,7 +716,7 @@ static void ksz8_w_vlan_table(struct ksz_device *dev, u16 vid, u16 vlan)
        u64 buf;
 
        data = (u16 *)&buf;
-       addr = vid / dev->phy_port_cnt;
+       addr = vid / 4;
        index = vid & 3;
        ksz8_r_table(dev, TABLE_VLAN, addr, &buf);
        data[index] = vlan;
@@ -1119,24 +1119,67 @@ static int ksz8_port_vlan_filtering(struct dsa_switch *ds, int port, bool flag,
        if (ksz_is_ksz88x3(dev))
                return -ENOTSUPP;
 
+       /* Discard packets with VID not enabled on the switch */
        ksz_cfg(dev, S_MIRROR_CTRL, SW_VLAN_ENABLE, flag);
 
+       /* Discard packets with VID not enabled on the ingress port */
+       for (port = 0; port < dev->phy_port_cnt; ++port)
+               ksz_port_cfg(dev, port, REG_PORT_CTRL_2, PORT_INGRESS_FILTER,
+                            flag);
+
        return 0;
 }
 
+static void ksz8_port_enable_pvid(struct ksz_device *dev, int port, bool state)
+{
+       if (ksz_is_ksz88x3(dev)) {
+               ksz_cfg(dev, REG_SW_INSERT_SRC_PVID,
+                       0x03 << (4 - 2 * port), state);
+       } else {
+               ksz_pwrite8(dev, port, REG_PORT_CTRL_12, state ? 0x0f : 0x00);
+       }
+}
+
 static int ksz8_port_vlan_add(struct dsa_switch *ds, int port,
                              const struct switchdev_obj_port_vlan *vlan,
                              struct netlink_ext_ack *extack)
 {
        bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
        struct ksz_device *dev = ds->priv;
+       struct ksz_port *p = &dev->ports[port];
        u16 data, new_pvid = 0;
        u8 fid, member, valid;
 
        if (ksz_is_ksz88x3(dev))
                return -ENOTSUPP;
 
-       ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged);
+       /* If a VLAN is added with untagged flag different from the
+        * port's Remove Tag flag, we need to change the latter.
+        * Ignore VID 0, which is always untagged.
+        * Ignore CPU port, which will always be tagged.
+        */
+       if (untagged != p->remove_tag && vlan->vid != 0 &&
+           port != dev->cpu_port) {
+               unsigned int vid;
+
+               /* Reject attempts to add a VLAN that requires the
+                * Remove Tag flag to be changed, unless there are no
+                * other VLANs currently configured.
+                */
+               for (vid = 1; vid < dev->num_vlans; ++vid) {
+                       /* Skip the VID we are going to add or reconfigure */
+                       if (vid == vlan->vid)
+                               continue;
+
+                       ksz8_from_vlan(dev, dev->vlan_cache[vid].table[0],
+                                      &fid, &member, &valid);
+                       if (valid && (member & BIT(port)))
+                               return -EINVAL;
+               }
+
+               ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged);
+               p->remove_tag = untagged;
+       }
 
        ksz8_r_vlan_table(dev, vlan->vid, &data);
        ksz8_from_vlan(dev, data, &fid, &member, &valid);
@@ -1160,9 +1203,11 @@ static int ksz8_port_vlan_add(struct dsa_switch *ds, int port,
                u16 vid;
 
                ksz_pread16(dev, port, REG_PORT_CTRL_VID, &vid);
-               vid &= 0xfff;
+               vid &= ~VLAN_VID_MASK;
                vid |= new_pvid;
                ksz_pwrite16(dev, port, REG_PORT_CTRL_VID, vid);
+
+               ksz8_port_enable_pvid(dev, port, true);
        }
 
        return 0;
@@ -1171,9 +1216,8 @@ static int ksz8_port_vlan_add(struct dsa_switch *ds, int port,
 static int ksz8_port_vlan_del(struct dsa_switch *ds, int port,
                              const struct switchdev_obj_port_vlan *vlan)
 {
-       bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
        struct ksz_device *dev = ds->priv;
-       u16 data, pvid, new_pvid = 0;
+       u16 data, pvid;
        u8 fid, member, valid;
 
        if (ksz_is_ksz88x3(dev))
@@ -1182,8 +1226,6 @@ static int ksz8_port_vlan_del(struct dsa_switch *ds, int port,
        ksz_pread16(dev, port, REG_PORT_CTRL_VID, &pvid);
        pvid = pvid & 0xFFF;
 
-       ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged);
-
        ksz8_r_vlan_table(dev, vlan->vid, &data);
        ksz8_from_vlan(dev, data, &fid, &member, &valid);
 
@@ -1195,14 +1237,11 @@ static int ksz8_port_vlan_del(struct dsa_switch *ds, int port,
                valid = 0;
        }
 
-       if (pvid == vlan->vid)
-               new_pvid = 1;
-
        ksz8_to_vlan(dev, fid, member, valid, &data);
        ksz8_w_vlan_table(dev, vlan->vid, data);
 
-       if (new_pvid != pvid)
-               ksz_pwrite16(dev, port, REG_PORT_CTRL_VID, pvid);
+       if (pvid == vlan->vid)
+               ksz8_port_enable_pvid(dev, port, false);
 
        return 0;
 }
@@ -1435,6 +1474,9 @@ static int ksz8_setup(struct dsa_switch *ds)
 
        ksz_cfg(dev, S_MIRROR_CTRL, SW_MIRROR_RX_TX, false);
 
+       if (!ksz_is_ksz88x3(dev))
+               ksz_cfg(dev, REG_SW_CTRL_19, SW_INS_TAG_ENABLE, true);
+
        /* set broadcast storm protection 10% rate */
        regmap_update_bits(dev->regmap[1], S_REPLACE_VID_CTRL,
                           BROADCAST_STORM_RATE,
@@ -1717,6 +1759,16 @@ static int ksz8_switch_init(struct ksz_device *dev)
        /* set the real number of ports */
        dev->ds->num_ports = dev->port_cnt;
 
+       /* We rely on software untagging on the CPU port, so that we
+        * can support both tagged and untagged VLANs
+        */
+       dev->ds->untag_bridge_pvid = true;
+
+       /* VLAN filtering is partly controlled by the global VLAN
+        * Enable flag
+        */
+       dev->ds->vlan_filtering_is_global = true;
+
        return 0;
 }
 
index a323556..6b40bc2 100644 (file)
 #define REG_PORT_4_OUT_RATE_3          0xEE
 #define REG_PORT_5_OUT_RATE_3          0xFE
 
+/* 88x3 specific */
+
+#define REG_SW_INSERT_SRC_PVID         0xC2
+
 /* PME */
 
 #define SW_PME_OUTPUT_ENABLE           BIT(1)
index 2e6bfd3..1597c63 100644 (file)
@@ -27,6 +27,7 @@ struct ksz_port_mib {
 struct ksz_port {
        u16 member;
        u16 vid_member;
+       bool remove_tag;                /* Remove Tag flag set, for ksz8795 only */
        int stp_state;
        struct phy_device phydev;
 
@@ -205,12 +206,8 @@ static inline int ksz_read64(struct ksz_device *dev, u32 reg, u64 *val)
        int ret;
 
        ret = regmap_bulk_read(dev->regmap[2], reg, value, 2);
-       if (!ret) {
-               /* Ick! ToDo: Add 64bit R/W to regmap on 32bit systems */
-               value[0] = swab32(value[0]);
-               value[1] = swab32(value[1]);
-               *val = swab64((u64)*value);
-       }
+       if (!ret)
+               *val = (u64)value[0] << 32 | value[1];
 
        return ret;
 }
index 69f21b7..632f0fc 100644 (file)
@@ -47,6 +47,7 @@ static const struct mt7530_mib_desc mt7530_mib[] = {
        MIB_DESC(2, 0x48, "TxBytes"),
        MIB_DESC(1, 0x60, "RxDrop"),
        MIB_DESC(1, 0x64, "RxFiltering"),
+       MIB_DESC(1, 0x68, "RxUnicast"),
        MIB_DESC(1, 0x6c, "RxMulticast"),
        MIB_DESC(1, 0x70, "RxBroadcast"),
        MIB_DESC(1, 0x74, "RxAlignErr"),
index 6686192..563d8a2 100644 (file)
         AR9331_SW_PORT_STATUS_RX_FLOW_EN | AR9331_SW_PORT_STATUS_TX_FLOW_EN | \
         AR9331_SW_PORT_STATUS_SPEED_M)
 
+#define AR9331_SW_REG_PORT_CTRL(_port)                 (0x104 + (_port) * 0x100)
+#define AR9331_SW_PORT_CTRL_HEAD_EN                    BIT(11)
+#define AR9331_SW_PORT_CTRL_PORT_STATE                 GENMASK(2, 0)
+#define AR9331_SW_PORT_CTRL_PORT_STATE_DISABLED                0
+#define AR9331_SW_PORT_CTRL_PORT_STATE_BLOCKING                1
+#define AR9331_SW_PORT_CTRL_PORT_STATE_LISTENING       2
+#define AR9331_SW_PORT_CTRL_PORT_STATE_LEARNING                3
+#define AR9331_SW_PORT_CTRL_PORT_STATE_FORWARD         4
+
+#define AR9331_SW_REG_PORT_VLAN(_port)                 (0x108 + (_port) * 0x100)
+#define AR9331_SW_PORT_VLAN_8021Q_MODE                 GENMASK(31, 30)
+#define AR9331_SW_8021Q_MODE_SECURE                    3
+#define AR9331_SW_8021Q_MODE_CHECK                     2
+#define AR9331_SW_8021Q_MODE_FALLBACK                  1
+#define AR9331_SW_8021Q_MODE_NONE                      0
+#define AR9331_SW_PORT_VLAN_PORT_VID_MEMBER            GENMASK(25, 16)
+
 /* MIB registers */
 #define AR9331_MIB_COUNTER(x)                  (0x20000 + ((x) * 0x100))
 
@@ -371,12 +388,60 @@ static int ar9331_sw_mbus_init(struct ar9331_sw_priv *priv)
        return 0;
 }
 
-static int ar9331_sw_setup(struct dsa_switch *ds)
+static int ar9331_sw_setup_port(struct dsa_switch *ds, int port)
 {
        struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
        struct regmap *regmap = priv->regmap;
+       u32 port_mask, port_ctrl, val;
        int ret;
 
+       /* Generate default port settings */
+       port_ctrl = FIELD_PREP(AR9331_SW_PORT_CTRL_PORT_STATE,
+                              AR9331_SW_PORT_CTRL_PORT_STATE_FORWARD);
+
+       if (dsa_is_cpu_port(ds, port)) {
+               /* CPU port should be allowed to communicate with all user
+                * ports.
+                */
+               port_mask = dsa_user_ports(ds);
+               /* Enable Atheros header on CPU port. This will allow us
+                * communicate with each port separately
+                */
+               port_ctrl |= AR9331_SW_PORT_CTRL_HEAD_EN;
+       } else if (dsa_is_user_port(ds, port)) {
+               /* User ports should communicate only with the CPU port.
+                */
+               port_mask = BIT(dsa_upstream_port(ds, port));
+       } else {
+               /* Other ports do not need to communicate at all */
+               port_mask = 0;
+       }
+
+       val = FIELD_PREP(AR9331_SW_PORT_VLAN_8021Q_MODE,
+                        AR9331_SW_8021Q_MODE_NONE) |
+               FIELD_PREP(AR9331_SW_PORT_VLAN_PORT_VID_MEMBER, port_mask);
+
+       ret = regmap_write(regmap, AR9331_SW_REG_PORT_VLAN(port), val);
+       if (ret)
+               goto error;
+
+       ret = regmap_write(regmap, AR9331_SW_REG_PORT_CTRL(port), port_ctrl);
+       if (ret)
+               goto error;
+
+       return 0;
+error:
+       dev_err(priv->dev, "%s: error: %i\n", __func__, ret);
+
+       return ret;
+}
+
+static int ar9331_sw_setup(struct dsa_switch *ds)
+{
+       struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
+       struct regmap *regmap = priv->regmap;
+       int ret, i;
+
        ret = ar9331_sw_reset(priv);
        if (ret)
                return ret;
@@ -402,6 +467,12 @@ static int ar9331_sw_setup(struct dsa_switch *ds)
        if (ret)
                goto error;
 
+       for (i = 0; i < ds->num_ports; i++) {
+               ret = ar9331_sw_setup_port(ds, i);
+               if (ret)
+                       goto error;
+       }
+
        ds->configure_vlan_while_not_filtering = false;
 
        return 0;
index 8667c97..49eb0ac 100644 (file)
@@ -1635,7 +1635,9 @@ static int sja1105_fdb_dump(struct dsa_switch *ds, int port,
                /* We need to hide the dsa_8021q VLANs from the user. */
                if (priv->vlan_state == SJA1105_VLAN_UNAWARE)
                        l2_lookup.vlanid = 0;
-               cb(macaddr, l2_lookup.vlanid, l2_lookup.lockeds, data);
+               rc = cb(macaddr, l2_lookup.vlanid, l2_lookup.lockeds, data);
+               if (rc)
+                       return rc;
        }
        return 0;
 }
@@ -3185,6 +3187,7 @@ static void sja1105_teardown(struct dsa_switch *ds)
        }
 
        sja1105_devlink_teardown(ds);
+       sja1105_mdiobus_unregister(ds);
        sja1105_flower_teardown(ds);
        sja1105_tas_teardown(ds);
        sja1105_ptp_clock_unregister(ds);
index 19aea8f..705d390 100644 (file)
@@ -284,8 +284,7 @@ static int sja1105_mdiobus_base_tx_register(struct sja1105_private *priv,
        struct mii_bus *bus;
        int rc = 0;
 
-       np = of_find_compatible_node(mdio_node, NULL,
-                                    "nxp,sja1110-base-tx-mdio");
+       np = of_get_compatible_child(mdio_node, "nxp,sja1110-base-tx-mdio");
        if (!np)
                return 0;
 
@@ -339,8 +338,7 @@ static int sja1105_mdiobus_base_t1_register(struct sja1105_private *priv,
        struct mii_bus *bus;
        int rc = 0;
 
-       np = of_find_compatible_node(mdio_node, NULL,
-                                    "nxp,sja1110-base-t1-mdio");
+       np = of_get_compatible_child(mdio_node, "nxp,sja1110-base-t1-mdio");
        if (!np)
                return 0;
 
index 8960658..8a97640 100644 (file)
@@ -72,7 +72,8 @@
 #include "bnxt_debugfs.h"
 
 #define BNXT_TX_TIMEOUT                (5 * HZ)
-#define BNXT_DEF_MSG_ENABLE    (NETIF_MSG_DRV | NETIF_MSG_HW)
+#define BNXT_DEF_MSG_ENABLE    (NETIF_MSG_DRV | NETIF_MSG_HW | \
+                                NETIF_MSG_TX_ERR)
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Broadcom BCM573xx network driver");
@@ -365,6 +366,33 @@ static u16 bnxt_xmit_get_cfa_action(struct sk_buff *skb)
        return md_dst->u.port_info.port_id;
 }
 
+static void bnxt_txr_db_kick(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
+                            u16 prod)
+{
+       bnxt_db_write(bp, &txr->tx_db, prod);
+       txr->kick_pending = 0;
+}
+
+static bool bnxt_txr_netif_try_stop_queue(struct bnxt *bp,
+                                         struct bnxt_tx_ring_info *txr,
+                                         struct netdev_queue *txq)
+{
+       netif_tx_stop_queue(txq);
+
+       /* netif_tx_stop_queue() must be done before checking
+        * tx index in bnxt_tx_avail() below, because in
+        * bnxt_tx_int(), we update tx index before checking for
+        * netif_tx_queue_stopped().
+        */
+       smp_mb();
+       if (bnxt_tx_avail(bp, txr) > bp->tx_wake_thresh) {
+               netif_tx_wake_queue(txq);
+               return false;
+       }
+
+       return true;
+}
+
 static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct bnxt *bp = netdev_priv(dev);
@@ -384,6 +412,7 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
        i = skb_get_queue_mapping(skb);
        if (unlikely(i >= bp->tx_nr_rings)) {
                dev_kfree_skb_any(skb);
+               atomic_long_inc(&dev->tx_dropped);
                return NETDEV_TX_OK;
        }
 
@@ -393,8 +422,12 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        free_size = bnxt_tx_avail(bp, txr);
        if (unlikely(free_size < skb_shinfo(skb)->nr_frags + 2)) {
-               netif_tx_stop_queue(txq);
-               return NETDEV_TX_BUSY;
+               /* We must have raced with NAPI cleanup */
+               if (net_ratelimit() && txr->kick_pending)
+                       netif_warn(bp, tx_err, dev,
+                                  "bnxt: ring busy w/ flush pending!\n");
+               if (bnxt_txr_netif_try_stop_queue(bp, txr, txq))
+                       return NETDEV_TX_BUSY;
        }
 
        length = skb->len;
@@ -426,7 +459,10 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
                if (ptp && ptp->tx_tstamp_en && !skb_is_gso(skb) &&
                    atomic_dec_if_positive(&ptp->tx_avail) >= 0) {
-                       if (!bnxt_ptp_parse(skb, &ptp->tx_seqid)) {
+                       if (!bnxt_ptp_parse(skb, &ptp->tx_seqid,
+                                           &ptp->tx_hdr_off)) {
+                               if (vlan_tag_flags)
+                                       ptp->tx_hdr_off += VLAN_HLEN;
                                lflags |= cpu_to_le32(TX_BD_FLAGS_STAMP);
                                skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
                        } else {
@@ -514,21 +550,16 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
 normal_tx:
        if (length < BNXT_MIN_PKT_SIZE) {
                pad = BNXT_MIN_PKT_SIZE - length;
-               if (skb_pad(skb, pad)) {
+               if (skb_pad(skb, pad))
                        /* SKB already freed. */
-                       tx_buf->skb = NULL;
-                       return NETDEV_TX_OK;
-               }
+                       goto tx_kick_pending;
                length = BNXT_MIN_PKT_SIZE;
        }
 
        mapping = dma_map_single(&pdev->dev, skb->data, len, DMA_TO_DEVICE);
 
-       if (unlikely(dma_mapping_error(&pdev->dev, mapping))) {
-               dev_kfree_skb_any(skb);
-               tx_buf->skb = NULL;
-               return NETDEV_TX_OK;
-       }
+       if (unlikely(dma_mapping_error(&pdev->dev, mapping)))
+               goto tx_free;
 
        dma_unmap_addr_set(tx_buf, mapping, mapping);
        flags = (len << TX_BD_LEN_SHIFT) | TX_BD_TYPE_LONG_TX_BD |
@@ -615,24 +646,17 @@ normal_tx:
        txr->tx_prod = prod;
 
        if (!netdev_xmit_more() || netif_xmit_stopped(txq))
-               bnxt_db_write(bp, &txr->tx_db, prod);
+               bnxt_txr_db_kick(bp, txr, prod);
+       else
+               txr->kick_pending = 1;
 
 tx_done:
 
        if (unlikely(bnxt_tx_avail(bp, txr) <= MAX_SKB_FRAGS + 1)) {
                if (netdev_xmit_more() && !tx_buf->is_push)
-                       bnxt_db_write(bp, &txr->tx_db, prod);
-
-               netif_tx_stop_queue(txq);
+                       bnxt_txr_db_kick(bp, txr, prod);
 
-               /* netif_tx_stop_queue() must be done before checking
-                * tx index in bnxt_tx_avail() below, because in
-                * bnxt_tx_int(), we update tx index before checking for
-                * netif_tx_queue_stopped().
-                */
-               smp_mb();
-               if (bnxt_tx_avail(bp, txr) > bp->tx_wake_thresh)
-                       netif_tx_wake_queue(txq);
+               bnxt_txr_netif_try_stop_queue(bp, txr, txq);
        }
        return NETDEV_TX_OK;
 
@@ -645,7 +669,6 @@ tx_dma_error:
        /* start back at beginning and unmap skb */
        prod = txr->tx_prod;
        tx_buf = &txr->tx_buf_ring[prod];
-       tx_buf->skb = NULL;
        dma_unmap_single(&pdev->dev, dma_unmap_addr(tx_buf, mapping),
                         skb_headlen(skb), PCI_DMA_TODEVICE);
        prod = NEXT_TX(prod);
@@ -659,7 +682,13 @@ tx_dma_error:
                               PCI_DMA_TODEVICE);
        }
 
+tx_free:
        dev_kfree_skb_any(skb);
+tx_kick_pending:
+       if (txr->kick_pending)
+               bnxt_txr_db_kick(bp, txr, txr->tx_prod);
+       txr->tx_buf_ring[txr->tx_prod].skb = NULL;
+       atomic_long_inc(&dev->tx_dropped);
        return NETDEV_TX_OK;
 }
 
@@ -729,14 +758,9 @@ next_tx_int:
        smp_mb();
 
        if (unlikely(netif_tx_queue_stopped(txq)) &&
-           (bnxt_tx_avail(bp, txr) > bp->tx_wake_thresh)) {
-               __netif_tx_lock(txq, smp_processor_id());
-               if (netif_tx_queue_stopped(txq) &&
-                   bnxt_tx_avail(bp, txr) > bp->tx_wake_thresh &&
-                   txr->dev_state != BNXT_DEV_STATE_CLOSING)
-                       netif_tx_wake_queue(txq);
-               __netif_tx_unlock(txq);
-       }
+           bnxt_tx_avail(bp, txr) > bp->tx_wake_thresh &&
+           READ_ONCE(txr->dev_state) != BNXT_DEV_STATE_CLOSING)
+               netif_tx_wake_queue(txq);
 }
 
 static struct page *__bnxt_alloc_rx_page(struct bnxt *bp, dma_addr_t *mapping,
@@ -1764,6 +1788,10 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
        if (!RX_CMP_VALID(rxcmp1, tmp_raw_cons))
                return -EBUSY;
 
+       /* The valid test of the entry must be done first before
+        * reading any further.
+        */
+       dma_rmb();
        prod = rxr->rx_prod;
 
        if (cmp_type == CMP_TYPE_RX_L2_TPA_START_CMP) {
@@ -1986,6 +2014,10 @@ static int bnxt_force_rx_discard(struct bnxt *bp,
        if (!RX_CMP_VALID(rxcmp1, tmp_raw_cons))
                return -EBUSY;
 
+       /* The valid test of the entry must be done first before
+        * reading any further.
+        */
+       dma_rmb();
        cmp_type = RX_CMP_TYPE(rxcmp);
        if (cmp_type == CMP_TYPE_RX_L2_CMP) {
                rxcmp1->rx_cmp_cfa_code_errors_v2 |=
@@ -2451,6 +2483,10 @@ static int bnxt_poll_nitroa0(struct napi_struct *napi, int budget)
                if (!TX_CMP_VALID(txcmp, raw_cons))
                        break;
 
+               /* The valid test of the entry must be done first before
+                * reading any further.
+                */
+               dma_rmb();
                if ((TX_CMP_TYPE(txcmp) & 0x30) == 0x10) {
                        tmp_raw_cons = NEXT_RAW_CMP(raw_cons);
                        cp_cons = RING_CMP(tmp_raw_cons);
@@ -9125,10 +9161,9 @@ static void bnxt_disable_napi(struct bnxt *bp)
        for (i = 0; i < bp->cp_nr_rings; i++) {
                struct bnxt_cp_ring_info *cpr = &bp->bnapi[i]->cp_ring;
 
+               napi_disable(&bp->bnapi[i]->napi);
                if (bp->bnapi[i]->rx_ring)
                        cancel_work_sync(&cpr->dim.work);
-
-               napi_disable(&bp->bnapi[i]->napi);
        }
 }
 
@@ -9162,9 +9197,11 @@ void bnxt_tx_disable(struct bnxt *bp)
        if (bp->tx_ring) {
                for (i = 0; i < bp->tx_nr_rings; i++) {
                        txr = &bp->tx_ring[i];
-                       txr->dev_state = BNXT_DEV_STATE_CLOSING;
+                       WRITE_ONCE(txr->dev_state, BNXT_DEV_STATE_CLOSING);
                }
        }
+       /* Make sure napi polls see @dev_state change */
+       synchronize_net();
        /* Drop carrier first to prevent TX timeout */
        netif_carrier_off(bp->dev);
        /* Stop all TX queues */
@@ -9178,8 +9215,10 @@ void bnxt_tx_enable(struct bnxt *bp)
 
        for (i = 0; i < bp->tx_nr_rings; i++) {
                txr = &bp->tx_ring[i];
-               txr->dev_state = 0;
+               WRITE_ONCE(txr->dev_state, 0);
        }
+       /* Make sure napi polls see @dev_state change */
+       synchronize_net();
        netif_tx_wake_all_queues(bp->dev);
        if (bp->link_info.link_up)
                netif_carrier_on(bp->dev);
@@ -10765,6 +10804,9 @@ static bool bnxt_rfs_supported(struct bnxt *bp)
                        return true;
                return false;
        }
+       /* 212 firmware is broken for aRFS */
+       if (BNXT_FW_MAJ(bp) == 212)
+               return false;
        if (BNXT_PF(bp) && !BNXT_CHIP_TYPE_NITRO_A0(bp))
                return true;
        if (bp->flags & BNXT_FLAG_NEW_RSS_CAP)
index bcf8d00..ba4e0fc 100644 (file)
@@ -786,6 +786,7 @@ struct bnxt_tx_ring_info {
        u16                     tx_prod;
        u16                     tx_cons;
        u16                     txq_index;
+       u8                      kick_pending;
        struct bnxt_db_info     tx_db;
 
        struct tx_bd            *tx_desc_ring[MAX_TX_PAGES];
index 3fc6781..94d07a9 100644 (file)
@@ -368,6 +368,7 @@ struct cmd_nums {
        #define HWRM_FUNC_PTP_TS_QUERY                    0x19fUL
        #define HWRM_FUNC_PTP_EXT_CFG                     0x1a0UL
        #define HWRM_FUNC_PTP_EXT_QCFG                    0x1a1UL
+       #define HWRM_FUNC_KEY_CTX_ALLOC                   0x1a2UL
        #define HWRM_SELFTEST_QLIST                       0x200UL
        #define HWRM_SELFTEST_EXEC                        0x201UL
        #define HWRM_SELFTEST_IRQ                         0x202UL
@@ -531,8 +532,8 @@ struct hwrm_err_output {
 #define HWRM_VERSION_MAJOR 1
 #define HWRM_VERSION_MINOR 10
 #define HWRM_VERSION_UPDATE 2
-#define HWRM_VERSION_RSVD 47
-#define HWRM_VERSION_STR "1.10.2.47"
+#define HWRM_VERSION_RSVD 52
+#define HWRM_VERSION_STR "1.10.2.52"
 
 /* hwrm_ver_get_input (size:192b/24B) */
 struct hwrm_ver_get_input {
@@ -585,6 +586,7 @@ struct hwrm_ver_get_output {
        #define VER_GET_RESP_DEV_CAPS_CFG_CFA_ADV_FLOW_MGNT_SUPPORTED              0x1000UL
        #define VER_GET_RESP_DEV_CAPS_CFG_CFA_TFLIB_SUPPORTED                      0x2000UL
        #define VER_GET_RESP_DEV_CAPS_CFG_CFA_TRUFLOW_SUPPORTED                    0x4000UL
+       #define VER_GET_RESP_DEV_CAPS_CFG_SECURE_BOOT_CAPABLE                      0x8000UL
        u8      roce_fw_maj_8b;
        u8      roce_fw_min_8b;
        u8      roce_fw_bld_8b;
@@ -886,7 +888,8 @@ struct hwrm_async_event_cmpl_reset_notify {
        #define ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_FW_EXCEPTION_FATAL        (0x2UL << 8)
        #define ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_FW_EXCEPTION_NON_FATAL    (0x3UL << 8)
        #define ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_FAST_RESET                (0x4UL << 8)
-       #define ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_LAST                     ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_FAST_RESET
+       #define ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_FW_ACTIVATION             (0x5UL << 8)
+       #define ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_LAST                     ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_FW_ACTIVATION
        #define ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_DELAY_IN_100MS_TICKS_MASK           0xffff0000UL
        #define ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_DELAY_IN_100MS_TICKS_SFT            16
 };
@@ -1236,13 +1239,14 @@ struct hwrm_async_event_cmpl_error_report_base {
        u8      timestamp_lo;
        __le16  timestamp_hi;
        __le32  event_data1;
-       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_MASK          0xffUL
-       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_SFT           0
-       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_RESERVED        0x0UL
-       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_PAUSE_STORM     0x1UL
-       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_INVALID_SIGNAL  0x2UL
-       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_NVM             0x3UL
-       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_LAST           ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_NVM
+       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_MASK                   0xffUL
+       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_SFT                    0
+       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_RESERVED                 0x0UL
+       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_PAUSE_STORM              0x1UL
+       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_INVALID_SIGNAL           0x2UL
+       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_NVM                      0x3UL
+       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_DOORBELL_DROP_THRESHOLD  0x4UL
+       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_LAST                    ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_DOORBELL_DROP_THRESHOLD
 };
 
 /* hwrm_async_event_cmpl_error_report_pause_storm (size:128b/16B) */
@@ -1446,6 +1450,8 @@ struct hwrm_func_vf_cfg_input {
        #define FUNC_VF_CFG_REQ_ENABLES_NUM_VNICS            0x200UL
        #define FUNC_VF_CFG_REQ_ENABLES_NUM_STAT_CTXS        0x400UL
        #define FUNC_VF_CFG_REQ_ENABLES_NUM_HW_RING_GRPS     0x800UL
+       #define FUNC_VF_CFG_REQ_ENABLES_NUM_TX_KEY_CTXS      0x1000UL
+       #define FUNC_VF_CFG_REQ_ENABLES_NUM_RX_KEY_CTXS      0x2000UL
        __le16  mtu;
        __le16  guest_vlan;
        __le16  async_event_cr;
@@ -1469,7 +1475,8 @@ struct hwrm_func_vf_cfg_input {
        __le16  num_vnics;
        __le16  num_stat_ctxs;
        __le16  num_hw_ring_grps;
-       u8      unused_0[4];
+       __le16  num_tx_key_ctxs;
+       __le16  num_rx_key_ctxs;
 };
 
 /* hwrm_func_vf_cfg_output (size:128b/16B) */
@@ -1493,7 +1500,7 @@ struct hwrm_func_qcaps_input {
        u8      unused_0[6];
 };
 
-/* hwrm_func_qcaps_output (size:704b/88B) */
+/* hwrm_func_qcaps_output (size:768b/96B) */
 struct hwrm_func_qcaps_output {
        __le16  error_code;
        __le16  req_type;
@@ -1587,7 +1594,8 @@ struct hwrm_func_qcaps_output {
        #define FUNC_QCAPS_RESP_MPC_CHNLS_CAP_TE_CFA      0x4UL
        #define FUNC_QCAPS_RESP_MPC_CHNLS_CAP_RE_CFA      0x8UL
        #define FUNC_QCAPS_RESP_MPC_CHNLS_CAP_PRIMATE     0x10UL
-       u8      unused_1;
+       __le16  max_key_ctxs_alloc;
+       u8      unused_1[7];
        u8      valid;
 };
 
@@ -1602,7 +1610,7 @@ struct hwrm_func_qcfg_input {
        u8      unused_0[6];
 };
 
-/* hwrm_func_qcfg_output (size:832b/104B) */
+/* hwrm_func_qcfg_output (size:896b/112B) */
 struct hwrm_func_qcfg_output {
        __le16  error_code;
        __le16  req_type;
@@ -1749,11 +1757,13 @@ struct hwrm_func_qcfg_output {
        #define FUNC_QCFG_RESP_PARTITION_MAX_BW_BW_VALUE_UNIT_PERCENT1_100  (0x1UL << 29)
        #define FUNC_QCFG_RESP_PARTITION_MAX_BW_BW_VALUE_UNIT_LAST         FUNC_QCFG_RESP_PARTITION_MAX_BW_BW_VALUE_UNIT_PERCENT1_100
        __le16  host_mtu;
-       u8      unused_3;
+       __le16  alloc_tx_key_ctxs;
+       __le16  alloc_rx_key_ctxs;
+       u8      unused_3[5];
        u8      valid;
 };
 
-/* hwrm_func_cfg_input (size:832b/104B) */
+/* hwrm_func_cfg_input (size:896b/112B) */
 struct hwrm_func_cfg_input {
        __le16  req_type;
        __le16  cmpl_ring;
@@ -1820,6 +1830,8 @@ struct hwrm_func_cfg_input {
        #define FUNC_CFG_REQ_ENABLES_PARTITION_MAX_BW         0x8000000UL
        #define FUNC_CFG_REQ_ENABLES_TPID                     0x10000000UL
        #define FUNC_CFG_REQ_ENABLES_HOST_MTU                 0x20000000UL
+       #define FUNC_CFG_REQ_ENABLES_TX_KEY_CTXS              0x40000000UL
+       #define FUNC_CFG_REQ_ENABLES_RX_KEY_CTXS              0x80000000UL
        __le16  admin_mtu;
        __le16  mru;
        __le16  num_rsscos_ctxs;
@@ -1929,6 +1941,9 @@ struct hwrm_func_cfg_input {
        #define FUNC_CFG_REQ_PARTITION_MAX_BW_BW_VALUE_UNIT_LAST         FUNC_CFG_REQ_PARTITION_MAX_BW_BW_VALUE_UNIT_PERCENT1_100
        __be16  tpid;
        __le16  host_mtu;
+       __le16  num_tx_key_ctxs;
+       __le16  num_rx_key_ctxs;
+       u8      unused_0[4];
 };
 
 /* hwrm_func_cfg_output (size:128b/16B) */
@@ -2099,6 +2114,7 @@ struct hwrm_func_drv_rgtr_input {
        #define FUNC_DRV_RGTR_REQ_FLAGS_MASTER_SUPPORT                   0x40UL
        #define FUNC_DRV_RGTR_REQ_FLAGS_FAST_RESET_SUPPORT               0x80UL
        #define FUNC_DRV_RGTR_REQ_FLAGS_RSS_STRICT_HASH_TYPE_SUPPORT     0x100UL
+       #define FUNC_DRV_RGTR_REQ_FLAGS_NPAR_1_2_SUPPORT                 0x200UL
        __le32  enables;
        #define FUNC_DRV_RGTR_REQ_ENABLES_OS_TYPE             0x1UL
        #define FUNC_DRV_RGTR_REQ_ENABLES_VER                 0x2UL
@@ -2268,7 +2284,7 @@ struct hwrm_func_resource_qcaps_input {
        u8      unused_0[6];
 };
 
-/* hwrm_func_resource_qcaps_output (size:448b/56B) */
+/* hwrm_func_resource_qcaps_output (size:512b/64B) */
 struct hwrm_func_resource_qcaps_output {
        __le16  error_code;
        __le16  req_type;
@@ -2300,11 +2316,15 @@ struct hwrm_func_resource_qcaps_output {
        __le16  max_tx_scheduler_inputs;
        __le16  flags;
        #define FUNC_RESOURCE_QCAPS_RESP_FLAGS_MIN_GUARANTEED     0x1UL
+       __le16  min_tx_key_ctxs;
+       __le16  max_tx_key_ctxs;
+       __le16  min_rx_key_ctxs;
+       __le16  max_rx_key_ctxs;
        u8      unused_0[5];
        u8      valid;
 };
 
-/* hwrm_func_vf_resource_cfg_input (size:448b/56B) */
+/* hwrm_func_vf_resource_cfg_input (size:512b/64B) */
 struct hwrm_func_vf_resource_cfg_input {
        __le16  req_type;
        __le16  cmpl_ring;
@@ -2331,6 +2351,10 @@ struct hwrm_func_vf_resource_cfg_input {
        __le16  max_hw_ring_grps;
        __le16  flags;
        #define FUNC_VF_RESOURCE_CFG_REQ_FLAGS_MIN_GUARANTEED     0x1UL
+       __le16  min_tx_key_ctxs;
+       __le16  max_tx_key_ctxs;
+       __le16  min_rx_key_ctxs;
+       __le16  max_rx_key_ctxs;
        u8      unused_0[2];
 };
 
@@ -2348,7 +2372,9 @@ struct hwrm_func_vf_resource_cfg_output {
        __le16  reserved_vnics;
        __le16  reserved_stat_ctx;
        __le16  reserved_hw_ring_grps;
-       u8      unused_0[7];
+       __le16  reserved_tx_key_ctxs;
+       __le16  reserved_rx_key_ctxs;
+       u8      unused_0[3];
        u8      valid;
 };
 
@@ -4220,7 +4246,7 @@ struct hwrm_port_lpbk_clr_stats_output {
        u8      valid;
 };
 
-/* hwrm_port_ts_query_input (size:256b/32B) */
+/* hwrm_port_ts_query_input (size:320b/40B) */
 struct hwrm_port_ts_query_input {
        __le16  req_type;
        __le16  cmpl_ring;
@@ -4238,8 +4264,11 @@ struct hwrm_port_ts_query_input {
        __le16  enables;
        #define PORT_TS_QUERY_REQ_ENABLES_TS_REQ_TIMEOUT     0x1UL
        #define PORT_TS_QUERY_REQ_ENABLES_PTP_SEQ_ID         0x2UL
+       #define PORT_TS_QUERY_REQ_ENABLES_PTP_HDR_OFFSET     0x4UL
        __le16  ts_req_timeout;
        __le32  ptp_seq_id;
+       __le16  ptp_hdr_offset;
+       u8      unused_1[6];
 };
 
 /* hwrm_port_ts_query_output (size:192b/24B) */
@@ -8172,6 +8201,7 @@ struct hwrm_fw_reset_input {
        u8      host_idx;
        u8      flags;
        #define FW_RESET_REQ_FLAGS_RESET_GRACEFUL     0x1UL
+       #define FW_RESET_REQ_FLAGS_FW_ACTIVATION      0x2UL
        u8      unused_0[4];
 };
 
@@ -8952,7 +8982,7 @@ struct hwrm_nvm_get_dir_info_output {
        u8      valid;
 };
 
-/* hwrm_nvm_write_input (size:384b/48B) */
+/* hwrm_nvm_write_input (size:448b/56B) */
 struct hwrm_nvm_write_input {
        __le16  req_type;
        __le16  cmpl_ring;
@@ -8968,7 +8998,11 @@ struct hwrm_nvm_write_input {
        __le16  option;
        __le16  flags;
        #define NVM_WRITE_REQ_FLAGS_KEEP_ORIG_ACTIVE_IMG     0x1UL
+       #define NVM_WRITE_REQ_FLAGS_BATCH_MODE               0x2UL
+       #define NVM_WRITE_REQ_FLAGS_BATCH_LAST               0x4UL
        __le32  dir_item_length;
+       __le32  offset;
+       __le32  len;
        __le32  unused_0;
 };
 
index ec381c2..81f40ab 100644 (file)
@@ -20,7 +20,7 @@
 #include "bnxt.h"
 #include "bnxt_ptp.h"
 
-int bnxt_ptp_parse(struct sk_buff *skb, u16 *seq_id)
+int bnxt_ptp_parse(struct sk_buff *skb, u16 *seq_id, u16 *hdr_off)
 {
        unsigned int ptp_class;
        struct ptp_header *hdr;
@@ -34,6 +34,7 @@ int bnxt_ptp_parse(struct sk_buff *skb, u16 *seq_id)
                if (!hdr)
                        return -EINVAL;
 
+               *hdr_off = (u8 *)hdr - skb->data;
                *seq_id  = ntohs(hdr->sequence_id);
                return 0;
        default:
@@ -91,6 +92,7 @@ static int bnxt_hwrm_port_ts_query(struct bnxt *bp, u32 flags, u64 *ts)
            PORT_TS_QUERY_REQ_FLAGS_PATH_TX) {
                req.enables = cpu_to_le16(BNXT_PTP_QTS_TX_ENABLES);
                req.ptp_seq_id = cpu_to_le32(bp->ptp_cfg->tx_seqid);
+               req.ptp_hdr_offset = cpu_to_le16(bp->ptp_cfg->tx_hdr_off);
                req.ts_req_timeout = cpu_to_le16(BNXT_PTP_QTS_TIMEOUT);
        }
        mutex_lock(&bp->hwrm_cmd_lock);
index 254ba7b..524f1c2 100644 (file)
@@ -10,8 +10,8 @@
 #ifndef BNXT_PTP_H
 #define BNXT_PTP_H
 
-#define BNXT_PTP_GRC_WIN       5
-#define BNXT_PTP_GRC_WIN_BASE  0x5000
+#define BNXT_PTP_GRC_WIN       6
+#define BNXT_PTP_GRC_WIN_BASE  0x6000
 
 #define BNXT_MAX_PHC_DRIFT     31000000
 #define BNXT_LO_TIMER_MASK     0x0000ffffffffUL
@@ -19,7 +19,8 @@
 
 #define BNXT_PTP_QTS_TIMEOUT   1000
 #define BNXT_PTP_QTS_TX_ENABLES        (PORT_TS_QUERY_REQ_ENABLES_PTP_SEQ_ID | \
-                                PORT_TS_QUERY_REQ_ENABLES_TS_REQ_TIMEOUT)
+                                PORT_TS_QUERY_REQ_ENABLES_TS_REQ_TIMEOUT | \
+                                PORT_TS_QUERY_REQ_ENABLES_PTP_HDR_OFFSET)
 
 struct bnxt_ptp_cfg {
        struct ptp_clock_info   ptp_info;
@@ -37,6 +38,7 @@ struct bnxt_ptp_cfg {
        #define BNXT_PHC_OVERFLOW_PERIOD        (19 * 3600 * HZ)
 
        u16                     tx_seqid;
+       u16                     tx_hdr_off;
        struct bnxt             *bp;
        atomic_t                tx_avail;
 #define BNXT_MAX_TX_TS 1
@@ -74,7 +76,7 @@ do {                                          \
        ((dst) = READ_ONCE(src))
 #endif
 
-int bnxt_ptp_parse(struct sk_buff *skb, u16 *seq_id);
+int bnxt_ptp_parse(struct sk_buff *skb, u16 *seq_id, u16 *hdr_off);
 int bnxt_hwtstamp_set(struct net_device *dev, struct ifreq *ifr);
 int bnxt_hwtstamp_get(struct net_device *dev, struct ifreq *ifr);
 int bnxt_get_tx_ts_p5(struct bnxt *bp, struct sk_buff *skb);
index 68b7864..98cc013 100644 (file)
@@ -3038,26 +3038,30 @@ static int dpaa2_switch_port_init(struct ethsw_port_priv *port_priv, u16 port)
        return err;
 }
 
-static void dpaa2_switch_takedown(struct fsl_mc_device *sw_dev)
+static void dpaa2_switch_ctrl_if_teardown(struct ethsw_core *ethsw)
+{
+       dpsw_ctrl_if_disable(ethsw->mc_io, 0, ethsw->dpsw_handle);
+       dpaa2_switch_free_dpio(ethsw);
+       dpaa2_switch_destroy_rings(ethsw);
+       dpaa2_switch_drain_bp(ethsw);
+       dpaa2_switch_free_dpbp(ethsw);
+}
+
+static void dpaa2_switch_teardown(struct fsl_mc_device *sw_dev)
 {
        struct device *dev = &sw_dev->dev;
        struct ethsw_core *ethsw = dev_get_drvdata(dev);
        int err;
 
+       dpaa2_switch_ctrl_if_teardown(ethsw);
+
+       destroy_workqueue(ethsw->workqueue);
+
        err = dpsw_close(ethsw->mc_io, 0, ethsw->dpsw_handle);
        if (err)
                dev_warn(dev, "dpsw_close err %d\n", err);
 }
 
-static void dpaa2_switch_ctrl_if_teardown(struct ethsw_core *ethsw)
-{
-       dpsw_ctrl_if_disable(ethsw->mc_io, 0, ethsw->dpsw_handle);
-       dpaa2_switch_free_dpio(ethsw);
-       dpaa2_switch_destroy_rings(ethsw);
-       dpaa2_switch_drain_bp(ethsw);
-       dpaa2_switch_free_dpbp(ethsw);
-}
-
 static int dpaa2_switch_remove(struct fsl_mc_device *sw_dev)
 {
        struct ethsw_port_priv *port_priv;
@@ -3068,8 +3072,6 @@ static int dpaa2_switch_remove(struct fsl_mc_device *sw_dev)
        dev = &sw_dev->dev;
        ethsw = dev_get_drvdata(dev);
 
-       dpaa2_switch_ctrl_if_teardown(ethsw);
-
        dpaa2_switch_teardown_irqs(sw_dev);
 
        dpsw_disable(ethsw->mc_io, 0, ethsw->dpsw_handle);
@@ -3084,9 +3086,7 @@ static int dpaa2_switch_remove(struct fsl_mc_device *sw_dev)
        kfree(ethsw->acls);
        kfree(ethsw->ports);
 
-       dpaa2_switch_takedown(sw_dev);
-
-       destroy_workqueue(ethsw->workqueue);
+       dpaa2_switch_teardown(sw_dev);
 
        fsl_mc_portal_free(ethsw->mc_io);
 
@@ -3199,7 +3199,7 @@ static int dpaa2_switch_probe(struct fsl_mc_device *sw_dev)
                               GFP_KERNEL);
        if (!(ethsw->ports)) {
                err = -ENOMEM;
-               goto err_takedown;
+               goto err_teardown;
        }
 
        ethsw->fdbs = kcalloc(ethsw->sw_attr.num_ifs, sizeof(*ethsw->fdbs),
@@ -3270,8 +3270,8 @@ err_free_fdbs:
 err_free_ports:
        kfree(ethsw->ports);
 
-err_takedown:
-       dpaa2_switch_takedown(sw_dev);
+err_teardown:
+       dpaa2_switch_teardown(sw_dev);
 
 err_free_cmdport:
        fsl_mc_portal_free(ethsw->mc_io);
index 3f25bd8..10a83e5 100644 (file)
@@ -3663,8 +3663,7 @@ u16 i40e_lan_select_queue(struct net_device *netdev,
 
        /* is DCB enabled at all? */
        if (vsi->tc_config.numtc == 1)
-               return i40e_swdcb_skb_tx_hash(netdev, skb,
-                                             netdev->real_num_tx_queues);
+               return netdev_pick_tx(netdev, skb, sb_dev);
 
        prio = skb->priority;
        hw = &vsi->back->hw;
index e8bd041..90793b3 100644 (file)
@@ -136,6 +136,7 @@ struct iavf_q_vector {
 struct iavf_mac_filter {
        struct list_head list;
        u8 macaddr[ETH_ALEN];
+       bool is_new_mac;        /* filter is new, wait for PF decision */
        bool remove;            /* filter needs to be removed */
        bool add;               /* filter needs to be added */
 };
index 44bafed..606a01c 100644 (file)
@@ -751,6 +751,7 @@ struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter,
 
                list_add_tail(&f->list, &adapter->mac_filter_list);
                f->add = true;
+               f->is_new_mac = true;
                adapter->aq_required |= IAVF_FLAG_AQ_ADD_MAC_FILTER;
        } else {
                f->remove = false;
@@ -1506,11 +1507,6 @@ static int iavf_reinit_interrupt_scheme(struct iavf_adapter *adapter)
        set_bit(__IAVF_VSI_DOWN, adapter->vsi.state);
 
        iavf_map_rings_to_vectors(adapter);
-
-       if (RSS_AQ(adapter))
-               adapter->aq_required |= IAVF_FLAG_AQ_CONFIGURE_RSS;
-       else
-               err = iavf_init_rss(adapter);
 err:
        return err;
 }
@@ -2200,6 +2196,14 @@ continue_reset:
                        goto reset_err;
        }
 
+       if (RSS_AQ(adapter)) {
+               adapter->aq_required |= IAVF_FLAG_AQ_CONFIGURE_RSS;
+       } else {
+               err = iavf_init_rss(adapter);
+               if (err)
+                       goto reset_err;
+       }
+
        adapter->aq_required |= IAVF_FLAG_AQ_GET_CONFIG;
        adapter->aq_required |= IAVF_FLAG_AQ_MAP_VECTORS;
 
index 0eab3c4..3c73596 100644 (file)
@@ -540,6 +540,47 @@ void iavf_del_ether_addrs(struct iavf_adapter *adapter)
        kfree(veal);
 }
 
+/**
+ * iavf_mac_add_ok
+ * @adapter: adapter structure
+ *
+ * Submit list of filters based on PF response.
+ **/
+static void iavf_mac_add_ok(struct iavf_adapter *adapter)
+{
+       struct iavf_mac_filter *f, *ftmp;
+
+       spin_lock_bh(&adapter->mac_vlan_list_lock);
+       list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
+               f->is_new_mac = false;
+       }
+       spin_unlock_bh(&adapter->mac_vlan_list_lock);
+}
+
+/**
+ * iavf_mac_add_reject
+ * @adapter: adapter structure
+ *
+ * Remove filters from list based on PF response.
+ **/
+static void iavf_mac_add_reject(struct iavf_adapter *adapter)
+{
+       struct net_device *netdev = adapter->netdev;
+       struct iavf_mac_filter *f, *ftmp;
+
+       spin_lock_bh(&adapter->mac_vlan_list_lock);
+       list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
+               if (f->remove && ether_addr_equal(f->macaddr, netdev->dev_addr))
+                       f->remove = false;
+
+               if (f->is_new_mac) {
+                       list_del(&f->list);
+                       kfree(f);
+               }
+       }
+       spin_unlock_bh(&adapter->mac_vlan_list_lock);
+}
+
 /**
  * iavf_add_vlans
  * @adapter: adapter structure
@@ -1492,6 +1533,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
                case VIRTCHNL_OP_ADD_ETH_ADDR:
                        dev_err(&adapter->pdev->dev, "Failed to add MAC filter, error %s\n",
                                iavf_stat_str(&adapter->hw, v_retval));
+                       iavf_mac_add_reject(adapter);
                        /* restore administratively set MAC address */
                        ether_addr_copy(adapter->hw.mac.addr, netdev->dev_addr);
                        break;
@@ -1639,10 +1681,11 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
                }
        }
        switch (v_opcode) {
-       case VIRTCHNL_OP_ADD_ETH_ADDR: {
+       case VIRTCHNL_OP_ADD_ETH_ADDR:
+               if (!v_retval)
+                       iavf_mac_add_ok(adapter);
                if (!ether_addr_equal(netdev->dev_addr, adapter->hw.mac.addr))
                        ether_addr_copy(netdev->dev_addr, adapter->hw.mac.addr);
-               }
                break;
        case VIRTCHNL_OP_GET_STATS: {
                struct iavf_eth_stats *stats =
index a450343..eadcb99 100644 (file)
@@ -234,6 +234,7 @@ enum ice_pf_state {
        ICE_VFLR_EVENT_PENDING,
        ICE_FLTR_OVERFLOW_PROMISC,
        ICE_VF_DIS,
+       ICE_VF_DEINIT_IN_PROGRESS,
        ICE_CFG_BUSY,
        ICE_SERVICE_SCHED,
        ICE_SERVICE_DIS,
index ef8d181..fe2ded7 100644 (file)
@@ -191,6 +191,14 @@ static int ice_add_mac_to_unsync_list(struct net_device *netdev, const u8 *addr)
        struct ice_netdev_priv *np = netdev_priv(netdev);
        struct ice_vsi *vsi = np->vsi;
 
+       /* Under some circumstances, we might receive a request to delete our
+        * own device address from our uc list. Because we store the device
+        * address in the VSI's MAC filter list, we need to ignore such
+        * requests and not delete our device address from this list.
+        */
+       if (ether_addr_equal(addr, netdev->dev_addr))
+               return 0;
+
        if (ice_fltr_add_mac_to_list(vsi, &vsi->tmp_unsync_list, addr,
                                     ICE_FWD_TO_VSI))
                return -EINVAL;
@@ -4194,6 +4202,11 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
        struct ice_hw *hw;
        int i, err;
 
+       if (pdev->is_virtfn) {
+               dev_err(dev, "can't probe a virtual function\n");
+               return -EINVAL;
+       }
+
        /* this driver uses devres, see
         * Documentation/driver-api/driver-model/devres.rst
         */
@@ -5119,7 +5132,7 @@ static int ice_set_mac_address(struct net_device *netdev, void *pi)
                return -EADDRNOTAVAIL;
 
        if (ether_addr_equal(netdev->dev_addr, mac)) {
-               netdev_warn(netdev, "already using mac %pM\n", mac);
+               netdev_dbg(netdev, "already using mac %pM\n", mac);
                return 0;
        }
 
@@ -5130,6 +5143,7 @@ static int ice_set_mac_address(struct net_device *netdev, void *pi)
                return -EBUSY;
        }
 
+       netif_addr_lock_bh(netdev);
        /* Clean up old MAC filter. Not an error if old filter doesn't exist */
        status = ice_fltr_remove_mac(vsi, netdev->dev_addr, ICE_FWD_TO_VSI);
        if (status && status != ICE_ERR_DOES_NOT_EXIST) {
@@ -5139,30 +5153,28 @@ static int ice_set_mac_address(struct net_device *netdev, void *pi)
 
        /* Add filter for new MAC. If filter exists, return success */
        status = ice_fltr_add_mac(vsi, mac, ICE_FWD_TO_VSI);
-       if (status == ICE_ERR_ALREADY_EXISTS) {
+       if (status == ICE_ERR_ALREADY_EXISTS)
                /* Although this MAC filter is already present in hardware it's
                 * possible in some cases (e.g. bonding) that dev_addr was
                 * modified outside of the driver and needs to be restored back
                 * to this value.
                 */
-               memcpy(netdev->dev_addr, mac, netdev->addr_len);
                netdev_dbg(netdev, "filter for MAC %pM already exists\n", mac);
-               return 0;
-       }
-
-       /* error if the new filter addition failed */
-       if (status)
+       else if (status)
+               /* error if the new filter addition failed */
                err = -EADDRNOTAVAIL;
 
 err_update_filters:
        if (err) {
                netdev_err(netdev, "can't set MAC %pM. filter update failed\n",
                           mac);
+               netif_addr_unlock_bh(netdev);
                return err;
        }
 
        /* change the netdev's MAC address */
        memcpy(netdev->dev_addr, mac, netdev->addr_len);
+       netif_addr_unlock_bh(netdev);
        netdev_dbg(vsi->netdev, "updated MAC address to %pM\n",
                   netdev->dev_addr);
 
index 5d5207b..9e3ddb9 100644 (file)
@@ -656,7 +656,7 @@ static int ice_ptp_cfg_clkout(struct ice_pf *pf, unsigned int chan,
         * maintaining phase
         */
        if (start_time < current_time)
-               start_time = div64_u64(current_time + NSEC_PER_MSEC - 1,
+               start_time = div64_u64(current_time + NSEC_PER_SEC - 1,
                                       NSEC_PER_SEC) * NSEC_PER_SEC + phase;
 
        start_time -= E810_OUT_PROP_DELAY_NS;
index 2826570..e93430a 100644 (file)
@@ -615,6 +615,8 @@ void ice_free_vfs(struct ice_pf *pf)
        struct ice_hw *hw = &pf->hw;
        unsigned int tmp, i;
 
+       set_bit(ICE_VF_DEINIT_IN_PROGRESS, pf->state);
+
        if (!pf->vf)
                return;
 
@@ -680,6 +682,7 @@ void ice_free_vfs(struct ice_pf *pf)
                                i);
 
        clear_bit(ICE_VF_DIS, pf->state);
+       clear_bit(ICE_VF_DEINIT_IN_PROGRESS, pf->state);
        clear_bit(ICE_FLAG_SRIOV_ENA, pf->flags);
 }
 
@@ -4415,6 +4418,10 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event)
        struct device *dev;
        int err = 0;
 
+       /* if de-init is underway, don't process messages from VF */
+       if (test_bit(ICE_VF_DEINIT_IN_PROGRESS, pf->state))
+               return;
+
        dev = ice_pf_to_dev(pf);
        if (ice_validate_vf_id(pf, vf_id)) {
                err = -EINVAL;
index 96dd1a4..b1d22e4 100644 (file)
@@ -52,8 +52,11 @@ static int ixgbe_xsk_pool_enable(struct ixgbe_adapter *adapter,
 
                /* Kick start the NAPI context so that receiving will start */
                err = ixgbe_xsk_wakeup(adapter->netdev, qid, XDP_WAKEUP_RX);
-               if (err)
+               if (err) {
+                       clear_bit(qid, adapter->af_xdp_zc_qps);
+                       xsk_pool_dma_unmap(pool, IXGBE_RX_DMA_ATTR);
                        return err;
+               }
        }
 
        return 0;
index b9fbc9f..cf8acab 100644 (file)
@@ -938,7 +938,7 @@ enum mvpp22_ptp_packet_format {
 #define MVPP2_BM_COOKIE_POOL_OFFS      8
 #define MVPP2_BM_COOKIE_CPU_OFFS       24
 
-#define MVPP2_BM_SHORT_FRAME_SIZE      704     /* frame size 128 */
+#define MVPP2_BM_SHORT_FRAME_SIZE      736     /* frame size 128 */
 #define MVPP2_BM_LONG_FRAME_SIZE       2240    /* frame size 1664 */
 #define MVPP2_BM_JUMBO_FRAME_SIZE      10432   /* frame size 9856 */
 /* BM short pool packet size
index 0b3e8f2..9a30916 100644 (file)
@@ -748,7 +748,7 @@ static void
 prestera_fdb_offload_notify(struct prestera_port *port,
                            struct switchdev_notifier_fdb_info *info)
 {
-       struct switchdev_notifier_fdb_info send_info;
+       struct switchdev_notifier_fdb_info send_info = {};
 
        send_info.addr = info->addr;
        send_info.vid = info->vid;
@@ -1123,7 +1123,7 @@ static int prestera_switchdev_blk_event(struct notifier_block *unused,
 static void prestera_fdb_event(struct prestera_switch *sw,
                               struct prestera_event *evt, void *arg)
 {
-       struct switchdev_notifier_fdb_info info;
+       struct switchdev_notifier_fdb_info info = {};
        struct net_device *dev = NULL;
        struct prestera_port *port;
        struct prestera_lag *lag;
index df3e493..360e093 100644 (file)
@@ -134,6 +134,7 @@ int mlx5_core_create_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq,
                              cq->cqn);
 
        cq->uar = dev->priv.uar;
+       cq->irqn = eq->core.irqn;
 
        return 0;
 
index 01a1d02..3f8a980 100644 (file)
@@ -1019,12 +1019,19 @@ int mlx5_fw_tracer_init(struct mlx5_fw_tracer *tracer)
        MLX5_NB_INIT(&tracer->nb, fw_tracer_event, DEVICE_TRACER);
        mlx5_eq_notifier_register(dev, &tracer->nb);
 
-       mlx5_fw_tracer_start(tracer);
-
+       err = mlx5_fw_tracer_start(tracer);
+       if (err) {
+               mlx5_core_warn(dev, "FWTracer: Failed to start tracer %d\n", err);
+               goto err_notifier_unregister;
+       }
        return 0;
 
+err_notifier_unregister:
+       mlx5_eq_notifier_unregister(dev, &tracer->nb);
+       mlx5_core_destroy_mkey(dev, &tracer->buff.mkey);
 err_dealloc_pd:
        mlx5_core_dealloc_pd(dev, tracer->buff.pdn);
+       cancel_work_sync(&tracer->read_fw_strings_work);
        return err;
 }
 
index 8f79f04..1e2d117 100644 (file)
@@ -124,6 +124,11 @@ static int mlx5e_route_lookup_ipv4_get(struct mlx5e_priv *priv,
        if (IS_ERR(rt))
                return PTR_ERR(rt);
 
+       if (rt->rt_type != RTN_UNICAST) {
+               ret = -ENETUNREACH;
+               goto err_rt_release;
+       }
+
        if (mlx5_lag_is_multipath(mdev) && rt->rt_gw_family != AF_INET) {
                ret = -ENETUNREACH;
                goto err_rt_release;
index 37c4408..24f919e 100644 (file)
@@ -1535,15 +1535,9 @@ static int mlx5e_alloc_cq_common(struct mlx5e_priv *priv,
 {
        struct mlx5_core_dev *mdev = priv->mdev;
        struct mlx5_core_cq *mcq = &cq->mcq;
-       int eqn_not_used;
-       unsigned int irqn;
        int err;
        u32 i;
 
-       err = mlx5_vector2eqn(mdev, param->eq_ix, &eqn_not_used, &irqn);
-       if (err)
-               return err;
-
        err = mlx5_cqwq_create(mdev, &param->wq, param->cqc, &cq->wq,
                               &cq->wq_ctrl);
        if (err)
@@ -1557,7 +1551,6 @@ static int mlx5e_alloc_cq_common(struct mlx5e_priv *priv,
        mcq->vector     = param->eq_ix;
        mcq->comp       = mlx5e_completion_event;
        mcq->event      = mlx5e_cq_error_event;
-       mcq->irqn       = irqn;
 
        for (i = 0; i < mlx5_cqwq_get_size(&cq->wq); i++) {
                struct mlx5_cqe64 *cqe = mlx5_cqwq_get_wqe(&cq->wq, i);
@@ -1605,11 +1598,10 @@ static int mlx5e_create_cq(struct mlx5e_cq *cq, struct mlx5e_cq_param *param)
        void *in;
        void *cqc;
        int inlen;
-       unsigned int irqn_not_used;
        int eqn;
        int err;
 
-       err = mlx5_vector2eqn(mdev, param->eq_ix, &eqn, &irqn_not_used);
+       err = mlx5_vector2eqn(mdev, param->eq_ix, &eqn);
        if (err)
                return err;
 
@@ -1891,30 +1883,30 @@ static int mlx5e_open_queues(struct mlx5e_channel *c,
        if (err)
                goto err_close_icosq;
 
+       err = mlx5e_open_rxq_rq(c, params, &cparam->rq);
+       if (err)
+               goto err_close_sqs;
+
        if (c->xdp) {
                err = mlx5e_open_xdpsq(c, params, &cparam->xdp_sq, NULL,
                                       &c->rq_xdpsq, false);
                if (err)
-                       goto err_close_sqs;
+                       goto err_close_rq;
        }
 
-       err = mlx5e_open_rxq_rq(c, params, &cparam->rq);
-       if (err)
-               goto err_close_xdp_sq;
-
        err = mlx5e_open_xdpsq(c, params, &cparam->xdp_sq, NULL, &c->xdpsq, true);
        if (err)
-               goto err_close_rq;
+               goto err_close_xdp_sq;
 
        return 0;
 
-err_close_rq:
-       mlx5e_close_rq(&c->rq);
-
 err_close_xdp_sq:
        if (c->xdp)
                mlx5e_close_xdpsq(&c->rq_xdpsq);
 
+err_close_rq:
+       mlx5e_close_rq(&c->rq);
+
 err_close_sqs:
        mlx5e_close_sqs(c);
 
@@ -1949,9 +1941,9 @@ err_close_async_icosq_cq:
 static void mlx5e_close_queues(struct mlx5e_channel *c)
 {
        mlx5e_close_xdpsq(&c->xdpsq);
-       mlx5e_close_rq(&c->rq);
        if (c->xdp)
                mlx5e_close_xdpsq(&c->rq_xdpsq);
+       mlx5e_close_rq(&c->rq);
        mlx5e_close_sqs(c);
        mlx5e_close_icosq(&c->icosq);
        mlx5e_close_icosq(&c->async_icosq);
@@ -1983,9 +1975,8 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
        struct mlx5e_channel *c;
        unsigned int irq;
        int err;
-       int eqn;
 
-       err = mlx5_vector2eqn(priv->mdev, ix, &eqn, &irq);
+       err = mlx5_vector2irqn(priv->mdev, ix, &irq);
        if (err)
                return err;
 
index 6e074cc..605c8ec 100644 (file)
@@ -855,8 +855,8 @@ clean:
        return err;
 }
 
-int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn,
-                   unsigned int *irqn)
+static int vector2eqnirqn(struct mlx5_core_dev *dev, int vector, int *eqn,
+                         unsigned int *irqn)
 {
        struct mlx5_eq_table *table = dev->priv.eq_table;
        struct mlx5_eq_comp *eq, *n;
@@ -865,8 +865,10 @@ int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn,
 
        list_for_each_entry_safe(eq, n, &table->comp_eqs_list, list) {
                if (i++ == vector) {
-                       *eqn = eq->core.eqn;
-                       *irqn = eq->core.irqn;
+                       if (irqn)
+                               *irqn = eq->core.irqn;
+                       if (eqn)
+                               *eqn = eq->core.eqn;
                        err = 0;
                        break;
                }
@@ -874,8 +876,18 @@ int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn,
 
        return err;
 }
+
+int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn)
+{
+       return vector2eqnirqn(dev, vector, eqn, NULL);
+}
 EXPORT_SYMBOL(mlx5_vector2eqn);
 
+int mlx5_vector2irqn(struct mlx5_core_dev *dev, int vector, unsigned int *irqn)
+{
+       return vector2eqnirqn(dev, vector, NULL, irqn);
+}
+
 unsigned int mlx5_comp_vectors_count(struct mlx5_core_dev *dev)
 {
        return dev->priv.eq_table->num_comp_eqs;
index a6e1d4f..69a3630 100644 (file)
@@ -69,7 +69,7 @@ static void
 mlx5_esw_bridge_fdb_offload_notify(struct net_device *dev, const unsigned char *addr, u16 vid,
                                   unsigned long val)
 {
-       struct switchdev_notifier_fdb_info send_info;
+       struct switchdev_notifier_fdb_info send_info = {};
 
        send_info.addr = addr;
        send_info.vid = vid;
@@ -579,7 +579,7 @@ static struct mlx5_esw_bridge *mlx5_esw_bridge_create(int ifindex,
        xa_init(&bridge->vports);
        bridge->ifindex = ifindex;
        bridge->refcnt = 1;
-       bridge->ageing_time = BR_DEFAULT_AGEING_TIME;
+       bridge->ageing_time = clock_t_to_jiffies(BR_DEFAULT_AGEING_TIME);
        list_add(&bridge->list, &br_offloads->bridges);
 
        return bridge;
@@ -1006,7 +1006,7 @@ int mlx5_esw_bridge_ageing_time_set(unsigned long ageing_time, struct mlx5_eswit
        if (!vport->bridge)
                return -EINVAL;
 
-       vport->bridge->ageing_time = ageing_time;
+       vport->bridge->ageing_time = clock_t_to_jiffies(ageing_time);
        return 0;
 }
 
index 794012c..d3ad78a 100644 (file)
@@ -501,6 +501,7 @@ err_sampler:
 err_offload_rule:
        mlx5_esw_vporttbl_put(esw, &per_vport_tbl_attr);
 err_default_tbl:
+       kfree(sample_flow);
        return ERR_PTR(err);
 }
 
index 011e766..3bb71a1 100644 (file)
@@ -48,6 +48,7 @@
 #include "lib/fs_chains.h"
 #include "en_tc.h"
 #include "en/mapping.h"
+#include "devlink.h"
 
 #define mlx5_esw_for_each_rep(esw, i, rep) \
        xa_for_each(&((esw)->offloads.vport_reps), i, rep)
@@ -3001,12 +3002,19 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
        if (cur_mlx5_mode == mlx5_mode)
                goto unlock;
 
-       if (mode == DEVLINK_ESWITCH_MODE_SWITCHDEV)
+       if (mode == DEVLINK_ESWITCH_MODE_SWITCHDEV) {
+               if (mlx5_devlink_trap_get_num_active(esw->dev)) {
+                       NL_SET_ERR_MSG_MOD(extack,
+                                          "Can't change mode while devlink traps are active");
+                       err = -EOPNOTSUPP;
+                       goto unlock;
+               }
                err = esw_offloads_start(esw, extack);
-       else if (mode == DEVLINK_ESWITCH_MODE_LEGACY)
+       } else if (mode == DEVLINK_ESWITCH_MODE_LEGACY) {
                err = esw_offloads_stop(esw, extack);
-       else
+       } else {
                err = -EINVAL;
+       }
 
 unlock:
        mlx5_esw_unlock(esw);
index bd66ab2..d5da4ab 100644 (file)
@@ -417,7 +417,6 @@ static int mlx5_fpga_conn_create_cq(struct mlx5_fpga_conn *conn, int cq_size)
        struct mlx5_wq_param wqp;
        struct mlx5_cqe64 *cqe;
        int inlen, err, eqn;
-       unsigned int irqn;
        void *cqc, *in;
        __be64 *pas;
        u32 i;
@@ -446,7 +445,7 @@ static int mlx5_fpga_conn_create_cq(struct mlx5_fpga_conn *conn, int cq_size)
                goto err_cqwq;
        }
 
-       err = mlx5_vector2eqn(mdev, smp_processor_id(), &eqn, &irqn);
+       err = mlx5_vector2eqn(mdev, smp_processor_id(), &eqn);
        if (err) {
                kvfree(in);
                goto err_cqwq;
@@ -476,7 +475,6 @@ static int mlx5_fpga_conn_create_cq(struct mlx5_fpga_conn *conn, int cq_size)
        *conn->cq.mcq.arm_db    = 0;
        conn->cq.mcq.vector     = 0;
        conn->cq.mcq.comp       = mlx5_fpga_conn_cq_complete;
-       conn->cq.mcq.irqn       = irqn;
        conn->cq.mcq.uar        = fdev->conn_res.uar;
        tasklet_setup(&conn->cq.tasklet, mlx5_fpga_conn_cq_tasklet);
 
index 624cede..d3d628b 100644 (file)
@@ -104,4 +104,6 @@ void mlx5_core_eq_free_irqs(struct mlx5_core_dev *dev);
 struct cpu_rmap *mlx5_eq_table_get_rmap(struct mlx5_core_dev *dev);
 #endif
 
+int mlx5_vector2irqn(struct mlx5_core_dev *dev, int vector, unsigned int *irqn);
+
 #endif
index eb1b316..c84ad87 100644 (file)
@@ -1784,16 +1784,14 @@ static int __init init(void)
        if (err)
                goto err_sf;
 
-#ifdef CONFIG_MLX5_CORE_EN
        err = mlx5e_init();
-       if (err) {
-               pci_unregister_driver(&mlx5_core_driver);
-               goto err_debug;
-       }
-#endif
+       if (err)
+               goto err_en;
 
        return 0;
 
+err_en:
+       mlx5_sf_driver_unregister();
 err_sf:
        pci_unregister_driver(&mlx5_core_driver);
 err_debug:
@@ -1803,9 +1801,7 @@ err_debug:
 
 static void __exit cleanup(void)
 {
-#ifdef CONFIG_MLX5_CORE_EN
        mlx5e_cleanup();
-#endif
        mlx5_sf_driver_unregister();
        pci_unregister_driver(&mlx5_core_driver);
        mlx5_unregister_debugfs();
index 343807a..da365b8 100644 (file)
@@ -206,8 +206,13 @@ int mlx5_firmware_flash(struct mlx5_core_dev *dev, const struct firmware *fw,
 int mlx5_fw_version_query(struct mlx5_core_dev *dev,
                          u32 *running_ver, u32 *stored_ver);
 
+#ifdef CONFIG_MLX5_CORE_EN
 int mlx5e_init(void);
 void mlx5e_cleanup(void);
+#else
+static inline int mlx5e_init(void){ return 0; }
+static inline void mlx5e_cleanup(void){}
+#endif
 
 static inline bool mlx5_sriov_is_enabled(struct mlx5_core_dev *dev)
 {
index b25f764..3465b36 100644 (file)
@@ -214,6 +214,7 @@ static struct mlx5_irq *irq_request(struct mlx5_irq_pool *pool, int i)
                err = -ENOMEM;
                goto err_cpumask;
        }
+       irq->pool = pool;
        kref_init(&irq->kref);
        irq->index = i;
        err = xa_err(xa_store(&pool->irqs, irq->index, irq, GFP_KERNEL));
@@ -222,7 +223,6 @@ static struct mlx5_irq *irq_request(struct mlx5_irq_pool *pool, int i)
                              irq->index, err);
                goto err_xa;
        }
-       irq->pool = pool;
        return irq;
 err_xa:
        free_cpumask_var(irq->mask);
@@ -251,8 +251,11 @@ int mlx5_irq_attach_nb(struct mlx5_irq *irq, struct notifier_block *nb)
 
 int mlx5_irq_detach_nb(struct mlx5_irq *irq, struct notifier_block *nb)
 {
+       int err = 0;
+
+       err = atomic_notifier_chain_unregister(&irq->nh, nb);
        irq_put(irq);
-       return atomic_notifier_chain_unregister(&irq->nh, nb);
+       return err;
 }
 
 struct cpumask *mlx5_irq_get_affinity_mask(struct mlx5_irq *irq)
@@ -437,6 +440,7 @@ irq_pool_alloc(struct mlx5_core_dev *dev, int start, int size, char *name,
        if (!pool)
                return ERR_PTR(-ENOMEM);
        pool->dev = dev;
+       mutex_init(&pool->lock);
        xa_init_flags(&pool->irqs, XA_FLAGS_ALLOC);
        pool->xa_num_irqs.min = start;
        pool->xa_num_irqs.max = start + size - 1;
@@ -445,7 +449,6 @@ irq_pool_alloc(struct mlx5_core_dev *dev, int start, int size, char *name,
                         name);
        pool->min_threshold = min_threshold * MLX5_EQ_REFS_PER_IRQ;
        pool->max_threshold = max_threshold * MLX5_EQ_REFS_PER_IRQ;
-       mutex_init(&pool->lock);
        mlx5_core_dbg(dev, "pool->name = %s, pool->size = %d, pool->start = %d",
                      name, size, start);
        return pool;
@@ -459,6 +462,7 @@ static void irq_pool_free(struct mlx5_irq_pool *pool)
        xa_for_each(&pool->irqs, index, irq)
                irq_release(&irq->kref);
        xa_destroy(&pool->irqs);
+       mutex_destroy(&pool->lock);
        kvfree(pool);
 }
 
index 12cf323..9df0e73 100644 (file)
@@ -749,7 +749,6 @@ static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev,
        struct mlx5_cqe64 *cqe;
        struct mlx5dr_cq *cq;
        int inlen, err, eqn;
-       unsigned int irqn;
        void *cqc, *in;
        __be64 *pas;
        int vector;
@@ -782,7 +781,7 @@ static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev,
                goto err_cqwq;
 
        vector = raw_smp_processor_id() % mlx5_comp_vectors_count(mdev);
-       err = mlx5_vector2eqn(mdev, vector, &eqn, &irqn);
+       err = mlx5_vector2eqn(mdev, vector, &eqn);
        if (err) {
                kvfree(in);
                goto err_cqwq;
@@ -818,7 +817,6 @@ static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev,
        *cq->mcq.arm_db = cpu_to_be32(2 << 28);
 
        cq->mcq.vector = 0;
-       cq->mcq.irqn = irqn;
        cq->mcq.uar = uar;
 
        return cq;
index f1950e4..e4dd4ee 100644 (file)
@@ -352,6 +352,7 @@ static void dr_ste_v0_set_rx_decap(u8 *hw_ste_p)
 {
        MLX5_SET(ste_rx_steering_mult, hw_ste_p, tunneling_action,
                 DR_STE_TUNL_ACTION_DECAP);
+       MLX5_SET(ste_rx_steering_mult, hw_ste_p, fail_on_error, 1);
 }
 
 static void dr_ste_v0_set_rx_pop_vlan(u8 *hw_ste_p)
@@ -365,6 +366,7 @@ static void dr_ste_v0_set_rx_decap_l3(u8 *hw_ste_p, bool vlan)
        MLX5_SET(ste_rx_steering_mult, hw_ste_p, tunneling_action,
                 DR_STE_TUNL_ACTION_L3_DECAP);
        MLX5_SET(ste_modify_packet, hw_ste_p, action_description, vlan ? 1 : 0);
+       MLX5_SET(ste_rx_steering_mult, hw_ste_p, fail_on_error, 1);
 }
 
 static void dr_ste_v0_set_rewrite_actions(u8 *hw_ste_p, u16 num_of_actions,
index 7e221ef..f69cbb3 100644 (file)
@@ -9079,7 +9079,7 @@ mlxsw_sp_rif_fid_fid_get(struct mlxsw_sp_rif *rif,
 
 static void mlxsw_sp_rif_fid_fdb_del(struct mlxsw_sp_rif *rif, const char *mac)
 {
-       struct switchdev_notifier_fdb_info info;
+       struct switchdev_notifier_fdb_info info = {};
        struct net_device *dev;
 
        dev = br_fdb_find_port(rif->dev, mac, 0);
@@ -9127,8 +9127,8 @@ mlxsw_sp_rif_vlan_fid_get(struct mlxsw_sp_rif *rif,
 
 static void mlxsw_sp_rif_vlan_fdb_del(struct mlxsw_sp_rif *rif, const char *mac)
 {
+       struct switchdev_notifier_fdb_info info = {};
        u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid);
-       struct switchdev_notifier_fdb_info info;
        struct net_device *br_dev;
        struct net_device *dev;
 
index c5ef9aa..8f90cd3 100644 (file)
@@ -2508,7 +2508,7 @@ mlxsw_sp_fdb_call_notifiers(enum switchdev_notifier_type type,
                            const char *mac, u16 vid,
                            struct net_device *dev, bool offloaded)
 {
-       struct switchdev_notifier_fdb_info info;
+       struct switchdev_notifier_fdb_info info = {};
 
        info.addr = mac;
        info.vid = vid;
index 0443f66..9a8e4f2 100644 (file)
@@ -277,7 +277,7 @@ static void sparx5_fdb_call_notifiers(enum switchdev_notifier_type type,
                                      const char *mac, u16 vid,
                                      struct net_device *dev, bool offloaded)
 {
-       struct switchdev_notifier_fdb_info info;
+       struct switchdev_notifier_fdb_info info = {};
 
        info.addr = mac;
        info.vid = vid;
index adfb978..2948d73 100644 (file)
@@ -1334,6 +1334,7 @@ void ocelot_apply_bridge_fwd_mask(struct ocelot *ocelot)
                        struct net_device *bond = ocelot_port->bond;
 
                        mask = ocelot_get_bridge_fwd_mask(ocelot, bridge);
+                       mask |= cpu_fwd_mask;
                        mask &= ~BIT(port);
                        if (bond) {
                                mask &= ~ocelot_get_bond_mask(ocelot, bond,
index ea4e834..7390fa3 100644 (file)
@@ -21,7 +21,7 @@ u32 __ocelot_read_ix(struct ocelot *ocelot, u32 reg, u32 offset)
                    ocelot->map[target][reg & REG_MASK] + offset, &val);
        return val;
 }
-EXPORT_SYMBOL(__ocelot_read_ix);
+EXPORT_SYMBOL_GPL(__ocelot_read_ix);
 
 void __ocelot_write_ix(struct ocelot *ocelot, u32 val, u32 reg, u32 offset)
 {
@@ -32,7 +32,7 @@ void __ocelot_write_ix(struct ocelot *ocelot, u32 val, u32 reg, u32 offset)
        regmap_write(ocelot->targets[target],
                     ocelot->map[target][reg & REG_MASK] + offset, val);
 }
-EXPORT_SYMBOL(__ocelot_write_ix);
+EXPORT_SYMBOL_GPL(__ocelot_write_ix);
 
 void __ocelot_rmw_ix(struct ocelot *ocelot, u32 val, u32 mask, u32 reg,
                     u32 offset)
@@ -45,7 +45,7 @@ void __ocelot_rmw_ix(struct ocelot *ocelot, u32 val, u32 mask, u32 reg,
                           ocelot->map[target][reg & REG_MASK] + offset,
                           mask, val);
 }
-EXPORT_SYMBOL(__ocelot_rmw_ix);
+EXPORT_SYMBOL_GPL(__ocelot_rmw_ix);
 
 u32 ocelot_port_readl(struct ocelot_port *port, u32 reg)
 {
@@ -58,7 +58,7 @@ u32 ocelot_port_readl(struct ocelot_port *port, u32 reg)
        regmap_read(port->target, ocelot->map[target][reg & REG_MASK], &val);
        return val;
 }
-EXPORT_SYMBOL(ocelot_port_readl);
+EXPORT_SYMBOL_GPL(ocelot_port_readl);
 
 void ocelot_port_writel(struct ocelot_port *port, u32 val, u32 reg)
 {
@@ -69,7 +69,7 @@ void ocelot_port_writel(struct ocelot_port *port, u32 val, u32 reg)
 
        regmap_write(port->target, ocelot->map[target][reg & REG_MASK], val);
 }
-EXPORT_SYMBOL(ocelot_port_writel);
+EXPORT_SYMBOL_GPL(ocelot_port_writel);
 
 void ocelot_port_rmwl(struct ocelot_port *port, u32 val, u32 mask, u32 reg)
 {
@@ -77,7 +77,7 @@ void ocelot_port_rmwl(struct ocelot_port *port, u32 val, u32 mask, u32 reg)
 
        ocelot_port_writel(port, (cur & (~mask)) | val, reg);
 }
-EXPORT_SYMBOL(ocelot_port_rmwl);
+EXPORT_SYMBOL_GPL(ocelot_port_rmwl);
 
 u32 __ocelot_target_read_ix(struct ocelot *ocelot, enum ocelot_target target,
                            u32 reg, u32 offset)
@@ -128,7 +128,7 @@ int ocelot_regfields_init(struct ocelot *ocelot,
 
        return 0;
 }
-EXPORT_SYMBOL(ocelot_regfields_init);
+EXPORT_SYMBOL_GPL(ocelot_regfields_init);
 
 static struct regmap_config ocelot_regmap_config = {
        .reg_bits       = 32,
@@ -148,4 +148,4 @@ struct regmap *ocelot_regmap_init(struct ocelot *ocelot, struct resource *res)
 
        return devm_regmap_init_mmio(ocelot->dev, regs, &ocelot_regmap_config);
 }
-EXPORT_SYMBOL(ocelot_regmap_init);
+EXPORT_SYMBOL_GPL(ocelot_regmap_init);
index 02a4610..c46a7f7 100644 (file)
@@ -327,6 +327,9 @@ static int qed_ll2_txq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)
        unsigned long flags;
        int rc = -EINVAL;
 
+       if (!p_ll2_conn)
+               return rc;
+
        spin_lock_irqsave(&p_tx->lock, flags);
        if (p_tx->b_completing_packet) {
                rc = -EBUSY;
@@ -500,7 +503,16 @@ static int qed_ll2_rxq_completion(struct qed_hwfn *p_hwfn, void *cookie)
        unsigned long flags = 0;
        int rc = 0;
 
+       if (!p_ll2_conn)
+               return rc;
+
        spin_lock_irqsave(&p_rx->lock, flags);
+
+       if (!QED_LL2_RX_REGISTERED(p_ll2_conn)) {
+               spin_unlock_irqrestore(&p_rx->lock, flags);
+               return 0;
+       }
+
        cq_new_idx = le16_to_cpu(*p_rx->p_fw_cons);
        cq_old_idx = qed_chain_get_cons_idx(&p_rx->rcq_chain);
 
@@ -821,6 +833,9 @@ static int qed_ll2_lb_rxq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)
        struct qed_ll2_info *p_ll2_conn = (struct qed_ll2_info *)p_cookie;
        int rc;
 
+       if (!p_ll2_conn)
+               return 0;
+
        if (!QED_LL2_RX_REGISTERED(p_ll2_conn))
                return 0;
 
@@ -844,6 +859,9 @@ static int qed_ll2_lb_txq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)
        u16 new_idx = 0, num_bds = 0;
        int rc;
 
+       if (!p_ll2_conn)
+               return 0;
+
        if (!QED_LL2_TX_REGISTERED(p_ll2_conn))
                return 0;
 
@@ -1728,6 +1746,8 @@ int qed_ll2_post_rx_buffer(void *cxt,
        if (!p_ll2_conn)
                return -EINVAL;
        p_rx = &p_ll2_conn->rx_queue;
+       if (!p_rx->set_prod_addr)
+               return -EIO;
 
        spin_lock_irqsave(&p_rx->lock, flags);
        if (!list_empty(&p_rx->free_descq))
index da864d1..4f4b792 100644 (file)
@@ -1285,8 +1285,7 @@ qed_rdma_create_qp(void *rdma_cxt,
 
        if (!rdma_cxt || !in_params || !out_params ||
            !p_hwfn->p_rdma_info->active) {
-               DP_ERR(p_hwfn->cdev,
-                      "qed roce create qp failed due to NULL entry (rdma_cxt=%p, in=%p, out=%p, roce_info=?\n",
+               pr_err("qed roce create qp failed due to NULL entry (rdma_cxt=%p, in=%p, out=%p, roce_info=?\n",
                       rdma_cxt, in_params, out_params);
                return NULL;
        }
index d8882d0..d51bac7 100644 (file)
@@ -3156,8 +3156,10 @@ int qlcnic_83xx_flash_read32(struct qlcnic_adapter *adapter, u32 flash_addr,
 
                indirect_addr = QLC_83XX_FLASH_DIRECT_DATA(addr);
                ret = QLCRD32(adapter, indirect_addr, &err);
-               if (err == -EIO)
+               if (err == -EIO) {
+                       qlcnic_83xx_unlock_flash(adapter);
                        return err;
+               }
 
                word = ret;
                *(u32 *)p_data  = word;
index c7af5bc..4d8e337 100644 (file)
@@ -3502,12 +3502,16 @@ static void rtl_hw_start_8106(struct rtl8169_private *tp)
        RTL_W8(tp, MCU, RTL_R8(tp, MCU) | EN_NDP | EN_OOB_RESET);
        RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN);
 
+       /* The default value is 0x13. Change it to 0x2f */
+       rtl_csi_access_enable(tp, 0x2f);
+
        rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000);
 
        /* disable EEE */
        rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000);
 
        rtl_pcie_state_l2l3_disable(tp);
+       rtl_hw_aspm_clkreq_enable(tp, true);
 }
 
 DECLARE_RTL_COND(rtl_mac_ocp_e00e_cond)
index a466336..1f06b92 100644 (file)
@@ -2715,7 +2715,7 @@ static void
 rocker_fdb_offload_notify(struct rocker_port *rocker_port,
                          struct switchdev_notifier_fdb_info *recv_info)
 {
-       struct switchdev_notifier_fdb_info info;
+       struct switchdev_notifier_fdb_info info = {};
 
        info.addr = recv_info->addr;
        info.vid = recv_info->vid;
index 967a634..e33a9d2 100644 (file)
@@ -1822,7 +1822,7 @@ static void ofdpa_port_fdb_learn_work(struct work_struct *work)
                container_of(work, struct ofdpa_fdb_learn_work, work);
        bool removing = (lw->flags & OFDPA_OP_FLAG_REMOVE);
        bool learned = (lw->flags & OFDPA_OP_FLAG_LEARNED);
-       struct switchdev_notifier_fdb_info info;
+       struct switchdev_notifier_fdb_info info = {};
 
        info.addr = lw->addr;
        info.vid = lw->vid;
index 9c29b36..599708a 100644 (file)
@@ -358,7 +358,7 @@ static int am65_cpsw_port_obj_del(struct net_device *ndev, const void *ctx,
 static void am65_cpsw_fdb_offload_notify(struct net_device *ndev,
                                         struct switchdev_notifier_fdb_info *rcv)
 {
-       struct switchdev_notifier_fdb_info info;
+       struct switchdev_notifier_fdb_info info = {};
 
        info.addr = rcv->addr;
        info.vid = rcv->vid;
index 57d279f..d1d0200 100644 (file)
@@ -920,7 +920,7 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
        struct cpdma_chan *txch;
        int ret, q_idx;
 
-       if (skb_padto(skb, CPSW_MIN_PACKET_SIZE)) {
+       if (skb_put_padto(skb, READ_ONCE(priv->tx_packet_min))) {
                cpsw_err(priv, tx_err, "packet pad failed\n");
                ndev->stats.tx_dropped++;
                return NET_XMIT_DROP;
@@ -1100,7 +1100,7 @@ static int cpsw_ndo_xdp_xmit(struct net_device *ndev, int n,
 
        for (i = 0; i < n; i++) {
                xdpf = frames[i];
-               if (xdpf->len < CPSW_MIN_PACKET_SIZE)
+               if (xdpf->len < READ_ONCE(priv->tx_packet_min))
                        break;
 
                if (cpsw_xdp_tx_frame(priv, xdpf, NULL, priv->emac_port))
@@ -1389,6 +1389,7 @@ static int cpsw_create_ports(struct cpsw_common *cpsw)
                priv->dev  = dev;
                priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
                priv->emac_port = i + 1;
+               priv->tx_packet_min = CPSW_MIN_PACKET_SIZE;
 
                if (is_valid_ether_addr(slave_data->mac_addr)) {
                        ether_addr_copy(priv->mac_addr, slave_data->mac_addr);
@@ -1686,6 +1687,7 @@ static int cpsw_dl_switch_mode_set(struct devlink *dl, u32 id,
 
                        priv = netdev_priv(sl_ndev);
                        slave->port_vlan = vlan;
+                       WRITE_ONCE(priv->tx_packet_min, CPSW_MIN_PACKET_SIZE_VLAN);
                        if (netif_running(sl_ndev))
                                cpsw_port_add_switch_def_ale_entries(priv,
                                                                     slave);
@@ -1714,6 +1716,7 @@ static int cpsw_dl_switch_mode_set(struct devlink *dl, u32 id,
 
                        priv = netdev_priv(slave->ndev);
                        slave->port_vlan = slave->data->dual_emac_res_vlan;
+                       WRITE_ONCE(priv->tx_packet_min, CPSW_MIN_PACKET_SIZE);
                        cpsw_port_add_dual_emac_def_ale_entries(priv, slave);
                }
 
index a323bea..2951fb7 100644 (file)
@@ -89,7 +89,8 @@ do {                                                          \
 
 #define CPSW_POLL_WEIGHT       64
 #define CPSW_RX_VLAN_ENCAP_HDR_SIZE            4
-#define CPSW_MIN_PACKET_SIZE   (VLAN_ETH_ZLEN)
+#define CPSW_MIN_PACKET_SIZE_VLAN      (VLAN_ETH_ZLEN)
+#define CPSW_MIN_PACKET_SIZE   (ETH_ZLEN)
 #define CPSW_MAX_PACKET_SIZE   (VLAN_ETH_FRAME_LEN +\
                                 ETH_FCS_LEN +\
                                 CPSW_RX_VLAN_ENCAP_HDR_SIZE)
@@ -380,6 +381,7 @@ struct cpsw_priv {
        u32 emac_port;
        struct cpsw_common *cpsw;
        int offload_fwd_mark;
+       u32 tx_packet_min;
 };
 
 #define ndev_to_cpsw(ndev) (((struct cpsw_priv *)netdev_priv(ndev))->cpsw)
index f7fb6e1..a7d97d4 100644 (file)
@@ -368,7 +368,7 @@ static int cpsw_port_obj_del(struct net_device *ndev, const void *ctx,
 static void cpsw_fdb_offload_notify(struct net_device *ndev,
                                    struct switchdev_notifier_fdb_info *rcv)
 {
-       struct switchdev_notifier_fdb_info info;
+       struct switchdev_notifier_fdb_info info = {};
 
        info.addr = rcv->addr;
        info.vid = rcv->vid;
index fcf3af7..8fe8887 100644 (file)
@@ -827,6 +827,12 @@ static void decode_data(struct sixpack *sp, unsigned char inbyte)
                return;
        }
 
+       if (sp->rx_count_cooked + 2 >= sizeof(sp->cooked_buf)) {
+               pr_err("6pack: cooked buffer overrun, data loss\n");
+               sp->rx_count = 0;
+               return;
+       }
+
        buf = sp->raw_buf;
        sp->cooked_buf[sp->rx_count_cooked++] =
                buf[0] | ((buf[1] << 2) & 0xc0);
index ebc976b..8caa61e 100644 (file)
@@ -418,7 +418,7 @@ static int hwsim_new_edge_nl(struct sk_buff *msg, struct genl_info *info)
        struct hwsim_edge *e;
        u32 v0, v1;
 
-       if (!info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID] &&
+       if (!info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID] ||
            !info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE])
                return -EINVAL;
 
@@ -528,14 +528,14 @@ static int hwsim_set_edge_lqi(struct sk_buff *msg, struct genl_info *info)
        u32 v0, v1;
        u8 lqi;
 
-       if (!info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID] &&
+       if (!info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID] ||
            !info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE])
                return -EINVAL;
 
        if (nla_parse_nested_deprecated(edge_attrs, MAC802154_HWSIM_EDGE_ATTR_MAX, info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE], hwsim_edge_policy, NULL))
                return -EINVAL;
 
-       if (!edge_attrs[MAC802154_HWSIM_EDGE_ATTR_ENDPOINT_ID] &&
+       if (!edge_attrs[MAC802154_HWSIM_EDGE_ATTR_ENDPOINT_ID] ||
            !edge_attrs[MAC802154_HWSIM_EDGE_ATTR_LQI])
                return -EINVAL;
 
index 110e4ee..ebd001f 100644 (file)
@@ -82,6 +82,17 @@ out:
 
 static int parent_count;
 
+static void mdio_mux_uninit_children(struct mdio_mux_parent_bus *pb)
+{
+       struct mdio_mux_child_bus *cb = pb->children;
+
+       while (cb) {
+               mdiobus_unregister(cb->mii_bus);
+               mdiobus_free(cb->mii_bus);
+               cb = cb->next;
+       }
+}
+
 int mdio_mux_init(struct device *dev,
                  struct device_node *mux_node,
                  int (*switch_fn)(int cur, int desired, void *data),
@@ -144,7 +155,7 @@ int mdio_mux_init(struct device *dev,
                cb = devm_kzalloc(dev, sizeof(*cb), GFP_KERNEL);
                if (!cb) {
                        ret_val = -ENOMEM;
-                       continue;
+                       goto err_loop;
                }
                cb->bus_number = v;
                cb->parent = pb;
@@ -152,8 +163,7 @@ int mdio_mux_init(struct device *dev,
                cb->mii_bus = mdiobus_alloc();
                if (!cb->mii_bus) {
                        ret_val = -ENOMEM;
-                       devm_kfree(dev, cb);
-                       continue;
+                       goto err_loop;
                }
                cb->mii_bus->priv = cb;
 
@@ -165,11 +175,15 @@ int mdio_mux_init(struct device *dev,
                cb->mii_bus->write = mdio_mux_write;
                r = of_mdiobus_register(cb->mii_bus, child_bus_node);
                if (r) {
+                       mdiobus_free(cb->mii_bus);
+                       if (r == -EPROBE_DEFER) {
+                               ret_val = r;
+                               goto err_loop;
+                       }
+                       devm_kfree(dev, cb);
                        dev_err(dev,
                                "Error: Failed to register MDIO bus for child %pOF\n",
                                child_bus_node);
-                       mdiobus_free(cb->mii_bus);
-                       devm_kfree(dev, cb);
                } else {
                        cb->next = pb->children;
                        pb->children = cb;
@@ -181,7 +195,10 @@ int mdio_mux_init(struct device *dev,
        }
 
        dev_err(dev, "Error: No acceptable child buses found\n");
-       devm_kfree(dev, pb);
+
+err_loop:
+       mdio_mux_uninit_children(pb);
+       of_node_put(child_bus_node);
 err_pb_kz:
        put_device(&parent_bus->dev);
 err_parent_bus:
@@ -193,14 +210,8 @@ EXPORT_SYMBOL_GPL(mdio_mux_init);
 void mdio_mux_uninit(void *mux_handle)
 {
        struct mdio_mux_parent_bus *pb = mux_handle;
-       struct mdio_mux_child_bus *cb = pb->children;
-
-       while (cb) {
-               mdiobus_unregister(cb->mii_bus);
-               mdiobus_free(cb->mii_bus);
-               cb = cb->next;
-       }
 
+       mdio_mux_uninit_children(pb);
        put_device(&pb->mii_bus->dev);
 }
 EXPORT_SYMBOL_GPL(mdio_mux_uninit);
index 63fda3f..4bd6133 100644 (file)
@@ -1089,7 +1089,7 @@ struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
 
        xpcs = kzalloc(sizeof(*xpcs), GFP_KERNEL);
        if (!xpcs)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        xpcs->mdiodev = mdiodev;
 
index 53bdd67..5c928f8 100644 (file)
@@ -1760,8 +1760,6 @@ static struct phy_driver ksphy_driver[] = {
        .name           = "Micrel KSZ87XX Switch",
        /* PHY_BASIC_FEATURES */
        .config_init    = kszphy_config_init,
-       .config_aneg    = ksz8873mll_config_aneg,
-       .read_status    = ksz8873mll_read_status,
        .match_phy_device = ksz8795_match_phy_device,
        .suspend        = genphy_suspend,
        .resume         = genphy_resume,
index 930e49e..7a099c3 100644 (file)
@@ -284,7 +284,7 @@ static struct channel *ppp_find_channel(struct ppp_net *pn, int unit);
 static int ppp_connect_channel(struct channel *pch, int unit);
 static int ppp_disconnect_channel(struct channel *pch);
 static void ppp_destroy_channel(struct channel *pch);
-static int unit_get(struct idr *p, void *ptr);
+static int unit_get(struct idr *p, void *ptr, int min);
 static int unit_set(struct idr *p, void *ptr, int n);
 static void unit_put(struct idr *p, int n);
 static void *unit_find(struct idr *p, int n);
@@ -1155,9 +1155,20 @@ static int ppp_unit_register(struct ppp *ppp, int unit, bool ifname_is_set)
        mutex_lock(&pn->all_ppp_mutex);
 
        if (unit < 0) {
-               ret = unit_get(&pn->units_idr, ppp);
+               ret = unit_get(&pn->units_idr, ppp, 0);
                if (ret < 0)
                        goto err;
+               if (!ifname_is_set) {
+                       while (1) {
+                               snprintf(ppp->dev->name, IFNAMSIZ, "ppp%i", ret);
+                               if (!__dev_get_by_name(ppp->ppp_net, ppp->dev->name))
+                                       break;
+                               unit_put(&pn->units_idr, ret);
+                               ret = unit_get(&pn->units_idr, ppp, ret + 1);
+                               if (ret < 0)
+                                       goto err;
+                       }
+               }
        } else {
                /* Caller asked for a specific unit number. Fail with -EEXIST
                 * if unavailable. For backward compatibility, return -EEXIST
@@ -1306,7 +1317,7 @@ static int ppp_nl_newlink(struct net *src_net, struct net_device *dev,
         * the PPP unit identifer as suffix (i.e. ppp<unit_id>). This allows
         * userspace to infer the device name using to the PPPIOCGUNIT ioctl.
         */
-       if (!tb[IFLA_IFNAME])
+       if (!tb[IFLA_IFNAME] || !nla_len(tb[IFLA_IFNAME]) || !*(char *)nla_data(tb[IFLA_IFNAME]))
                conf.ifname_is_set = false;
 
        err = ppp_dev_configure(src_net, dev, &conf);
@@ -3552,9 +3563,9 @@ static int unit_set(struct idr *p, void *ptr, int n)
 }
 
 /* get new free unit number and associate pointer with it */
-static int unit_get(struct idr *p, void *ptr)
+static int unit_get(struct idr *p, void *ptr, int min)
 {
-       return idr_alloc(p, ptr, 0, 0, GFP_KERNEL);
+       return idr_alloc(p, ptr, min, 0, GFP_KERNEL);
 }
 
 /* put unit number back to a pool */
index ac92bc5..38cda59 100644 (file)
@@ -63,6 +63,29 @@ void asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
                               value, index, data, size);
 }
 
+static int asix_check_host_enable(struct usbnet *dev, int in_pm)
+{
+       int i, ret;
+       u8 smsr;
+
+       for (i = 0; i < 30; ++i) {
+               ret = asix_set_sw_mii(dev, in_pm);
+               if (ret == -ENODEV || ret == -ETIMEDOUT)
+                       break;
+               usleep_range(1000, 1100);
+               ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG,
+                                   0, 0, 1, &smsr, in_pm);
+               if (ret == -ENODEV)
+                       break;
+               else if (ret < 0)
+                       continue;
+               else if (smsr & AX_HOST_EN)
+                       break;
+       }
+
+       return ret;
+}
+
 static void reset_asix_rx_fixup_info(struct asix_rx_fixup_info *rx)
 {
        /* Reset the variables that have a lifetime outside of
@@ -467,19 +490,11 @@ int asix_mdio_read(struct net_device *netdev, int phy_id, int loc)
 {
        struct usbnet *dev = netdev_priv(netdev);
        __le16 res;
-       u8 smsr;
-       int i = 0;
        int ret;
 
        mutex_lock(&dev->phy_mutex);
-       do {
-               ret = asix_set_sw_mii(dev, 0);
-               if (ret == -ENODEV || ret == -ETIMEDOUT)
-                       break;
-               usleep_range(1000, 1100);
-               ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG,
-                                   0, 0, 1, &smsr, 0);
-       } while (!(smsr & AX_HOST_EN) && (i++ < 30) && (ret != -ENODEV));
+
+       ret = asix_check_host_enable(dev, 0);
        if (ret == -ENODEV || ret == -ETIMEDOUT) {
                mutex_unlock(&dev->phy_mutex);
                return ret;
@@ -505,23 +520,14 @@ static int __asix_mdio_write(struct net_device *netdev, int phy_id, int loc,
 {
        struct usbnet *dev = netdev_priv(netdev);
        __le16 res = cpu_to_le16(val);
-       u8 smsr;
-       int i = 0;
        int ret;
 
        netdev_dbg(dev->net, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n",
                        phy_id, loc, val);
 
        mutex_lock(&dev->phy_mutex);
-       do {
-               ret = asix_set_sw_mii(dev, 0);
-               if (ret == -ENODEV)
-                       break;
-               usleep_range(1000, 1100);
-               ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG,
-                                   0, 0, 1, &smsr, 0);
-       } while (!(smsr & AX_HOST_EN) && (i++ < 30) && (ret != -ENODEV));
 
+       ret = asix_check_host_enable(dev, 0);
        if (ret == -ENODEV)
                goto out;
 
@@ -561,19 +567,11 @@ int asix_mdio_read_nopm(struct net_device *netdev, int phy_id, int loc)
 {
        struct usbnet *dev = netdev_priv(netdev);
        __le16 res;
-       u8 smsr;
-       int i = 0;
        int ret;
 
        mutex_lock(&dev->phy_mutex);
-       do {
-               ret = asix_set_sw_mii(dev, 1);
-               if (ret == -ENODEV || ret == -ETIMEDOUT)
-                       break;
-               usleep_range(1000, 1100);
-               ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG,
-                                   0, 0, 1, &smsr, 1);
-       } while (!(smsr & AX_HOST_EN) && (i++ < 30) && (ret != -ENODEV));
+
+       ret = asix_check_host_enable(dev, 1);
        if (ret == -ENODEV || ret == -ETIMEDOUT) {
                mutex_unlock(&dev->phy_mutex);
                return ret;
@@ -595,22 +593,14 @@ asix_mdio_write_nopm(struct net_device *netdev, int phy_id, int loc, int val)
 {
        struct usbnet *dev = netdev_priv(netdev);
        __le16 res = cpu_to_le16(val);
-       u8 smsr;
-       int i = 0;
        int ret;
 
        netdev_dbg(dev->net, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n",
                        phy_id, loc, val);
 
        mutex_lock(&dev->phy_mutex);
-       do {
-               ret = asix_set_sw_mii(dev, 1);
-               if (ret == -ENODEV)
-                       break;
-               usleep_range(1000, 1100);
-               ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG,
-                                   0, 0, 1, &smsr, 1);
-       } while (!(smsr & AX_HOST_EN) && (i++ < 30) && (ret != -ENODEV));
+
+       ret = asix_check_host_enable(dev, 1);
        if (ret == -ENODEV) {
                mutex_unlock(&dev->phy_mutex);
                return;
index e09b107..7983237 100644 (file)
@@ -3955,17 +3955,28 @@ static void rtl_clear_bp(struct r8152 *tp, u16 type)
        case RTL_VER_06:
                ocp_write_byte(tp, type, PLA_BP_EN, 0);
                break;
+       case RTL_VER_14:
+               ocp_write_word(tp, type, USB_BP2_EN, 0);
+
+               ocp_write_word(tp, type, USB_BP_8, 0);
+               ocp_write_word(tp, type, USB_BP_9, 0);
+               ocp_write_word(tp, type, USB_BP_10, 0);
+               ocp_write_word(tp, type, USB_BP_11, 0);
+               ocp_write_word(tp, type, USB_BP_12, 0);
+               ocp_write_word(tp, type, USB_BP_13, 0);
+               ocp_write_word(tp, type, USB_BP_14, 0);
+               ocp_write_word(tp, type, USB_BP_15, 0);
+               break;
        case RTL_VER_08:
        case RTL_VER_09:
        case RTL_VER_10:
        case RTL_VER_11:
        case RTL_VER_12:
        case RTL_VER_13:
-       case RTL_VER_14:
        case RTL_VER_15:
        default:
                if (type == MCU_TYPE_USB) {
-                       ocp_write_byte(tp, MCU_TYPE_USB, USB_BP2_EN, 0);
+                       ocp_write_word(tp, MCU_TYPE_USB, USB_BP2_EN, 0);
 
                        ocp_write_word(tp, MCU_TYPE_USB, USB_BP_8, 0);
                        ocp_write_word(tp, MCU_TYPE_USB, USB_BP_9, 0);
@@ -4331,7 +4342,6 @@ static bool rtl8152_is_fw_mac_ok(struct r8152 *tp, struct fw_mac *mac)
                case RTL_VER_11:
                case RTL_VER_12:
                case RTL_VER_13:
-               case RTL_VER_14:
                case RTL_VER_15:
                        fw_reg = 0xf800;
                        bp_ba_addr = PLA_BP_BA;
@@ -4339,6 +4349,13 @@ static bool rtl8152_is_fw_mac_ok(struct r8152 *tp, struct fw_mac *mac)
                        bp_start = PLA_BP_0;
                        max_bp = 8;
                        break;
+               case RTL_VER_14:
+                       fw_reg = 0xf800;
+                       bp_ba_addr = PLA_BP_BA;
+                       bp_en_addr = USB_BP2_EN;
+                       bp_start = PLA_BP_0;
+                       max_bp = 16;
+                       break;
                default:
                        goto out;
                }
index 56c3f85..eee4936 100644 (file)
@@ -63,7 +63,7 @@ static const unsigned long guest_offloads[] = {
        VIRTIO_NET_F_GUEST_CSUM
 };
 
-#define GUEST_OFFLOAD_LRO_MASK ((1ULL << VIRTIO_NET_F_GUEST_TSO4) | \
+#define GUEST_OFFLOAD_GRO_HW_MASK ((1ULL << VIRTIO_NET_F_GUEST_TSO4) | \
                                (1ULL << VIRTIO_NET_F_GUEST_TSO6) | \
                                (1ULL << VIRTIO_NET_F_GUEST_ECN)  | \
                                (1ULL << VIRTIO_NET_F_GUEST_UFO))
@@ -2515,7 +2515,7 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog,
                virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_ECN) ||
                virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_UFO) ||
                virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_CSUM))) {
-               NL_SET_ERR_MSG_MOD(extack, "Can't set XDP while host is implementing LRO/CSUM, disable LRO/CSUM first");
+               NL_SET_ERR_MSG_MOD(extack, "Can't set XDP while host is implementing GRO_HW/CSUM, disable GRO_HW/CSUM first");
                return -EOPNOTSUPP;
        }
 
@@ -2646,15 +2646,15 @@ static int virtnet_set_features(struct net_device *dev,
        u64 offloads;
        int err;
 
-       if ((dev->features ^ features) & NETIF_F_LRO) {
+       if ((dev->features ^ features) & NETIF_F_GRO_HW) {
                if (vi->xdp_enabled)
                        return -EBUSY;
 
-               if (features & NETIF_F_LRO)
+               if (features & NETIF_F_GRO_HW)
                        offloads = vi->guest_offloads_capable;
                else
                        offloads = vi->guest_offloads_capable &
-                                  ~GUEST_OFFLOAD_LRO_MASK;
+                                  ~GUEST_OFFLOAD_GRO_HW_MASK;
 
                err = virtnet_set_guest_offloads(vi, offloads);
                if (err)
@@ -3134,9 +3134,9 @@ static int virtnet_probe(struct virtio_device *vdev)
                dev->features |= NETIF_F_RXCSUM;
        if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||
            virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6))
-               dev->features |= NETIF_F_LRO;
+               dev->features |= NETIF_F_GRO_HW;
        if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS))
-               dev->hw_features |= NETIF_F_LRO;
+               dev->hw_features |= NETIF_F_GRO_HW;
 
        dev->vlan_features = dev->features;
 
index 2b1b944..8bbe2a7 100644 (file)
@@ -1367,6 +1367,8 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev,
        bool need_strict = rt6_need_strict(&ipv6_hdr(skb)->daddr);
        bool is_ndisc = ipv6_ndisc_frame(skb);
 
+       nf_reset_ct(skb);
+
        /* loopback, multicast & non-ND link-local traffic; do not push through
         * packet taps again. Reset pkt_type for upper layers to process skb.
         * For strict packets with a source LLA, determine the dst using the
@@ -1429,6 +1431,8 @@ static struct sk_buff *vrf_ip_rcv(struct net_device *vrf_dev,
        skb->skb_iif = vrf_dev->ifindex;
        IPCB(skb)->flags |= IPSKB_L3SLAVE;
 
+       nf_reset_ct(skb);
+
        if (ipv4_is_multicast(ip_hdr(skb)->daddr))
                goto out;
 
index 2403490..b4b1f75 100644 (file)
@@ -37,6 +37,7 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
        u32 sha1 = 0;
        u16 mac_type = 0, rf_id = 0;
        u8 *pnvm_data = NULL, *tmp;
+       bool hw_match = false;
        u32 size = 0;
        int ret;
 
@@ -83,6 +84,9 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
                                break;
                        }
 
+                       if (hw_match)
+                               break;
+
                        mac_type = le16_to_cpup((__le16 *)data);
                        rf_id = le16_to_cpup((__le16 *)(data + sizeof(__le16)));
 
@@ -90,15 +94,9 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
                                     "Got IWL_UCODE_TLV_HW_TYPE mac_type 0x%0x rf_id 0x%0x\n",
                                     mac_type, rf_id);
 
-                       if (mac_type != CSR_HW_REV_TYPE(trans->hw_rev) ||
-                           rf_id != CSR_HW_RFID_TYPE(trans->hw_rf_id)) {
-                               IWL_DEBUG_FW(trans,
-                                            "HW mismatch, skipping PNVM section, mac_type 0x%0x, rf_id 0x%0x.\n",
-                                            CSR_HW_REV_TYPE(trans->hw_rev), trans->hw_rf_id);
-                               ret = -ENOENT;
-                               goto out;
-                       }
-
+                       if (mac_type == CSR_HW_REV_TYPE(trans->hw_rev) &&
+                           rf_id == CSR_HW_RFID_TYPE(trans->hw_rf_id))
+                               hw_match = true;
                        break;
                case IWL_UCODE_TLV_SEC_RT: {
                        struct iwl_pnvm_section *section = (void *)data;
@@ -149,6 +147,15 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
        }
 
 done:
+       if (!hw_match) {
+               IWL_DEBUG_FW(trans,
+                            "HW mismatch, skipping PNVM section (need mac_type 0x%x rf_id 0x%x)\n",
+                            CSR_HW_REV_TYPE(trans->hw_rev),
+                            CSR_HW_RFID_TYPE(trans->hw_rf_id));
+               ret = -ENOENT;
+               goto out;
+       }
+
        if (!size) {
                IWL_DEBUG_FW(trans, "Empty PNVM, skipping.\n");
                ret = -ENOENT;
index 16baee3..0b8a0cd 100644 (file)
@@ -1110,12 +1110,80 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
                      IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
                      iwl_cfg_bz_a0_mr_a0, iwl_ax211_name),
 
+/* SoF with JF2 */
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+                     IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9560_160_name),
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+                     IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9560_name),
+
+/* SoF with JF */
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+                     IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9461_160_name),
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+                     IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9462_160_name),
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+                     IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9461_name),
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+                     IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9462_name),
+
 /* So with GF */
        _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
                      IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
                      IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
                      IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
-                     iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_name)
+                     iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_name),
+
+/* So with JF2 */
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+                     IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9560_160_name),
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+                     IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9560_name),
+
+/* So with JF */
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+                     IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9461_160_name),
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+                     IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9462_160_name),
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+                     IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9461_name),
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+                     IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9462_name)
 
 #endif /* CONFIG_IWLMVM */
 };
index 863aa18..4396077 100644 (file)
@@ -111,7 +111,7 @@ mt7915_mcu_get_cipher(int cipher)
        case WLAN_CIPHER_SUITE_SMS4:
                return MCU_CIPHER_WAPI;
        default:
-               return MT_CIPHER_NONE;
+               return MCU_CIPHER_NONE;
        }
 }
 
index edd3ba3..e68a562 100644 (file)
@@ -1073,7 +1073,8 @@ enum {
 };
 
 enum mcu_cipher_type {
-       MCU_CIPHER_WEP40 = 1,
+       MCU_CIPHER_NONE = 0,
+       MCU_CIPHER_WEP40,
        MCU_CIPHER_WEP104,
        MCU_CIPHER_WEP128,
        MCU_CIPHER_TKIP,
index cd690c6..9fbaacc 100644 (file)
@@ -111,7 +111,7 @@ mt7921_mcu_get_cipher(int cipher)
        case WLAN_CIPHER_SUITE_SMS4:
                return MCU_CIPHER_WAPI;
        default:
-               return MT_CIPHER_NONE;
+               return MCU_CIPHER_NONE;
        }
 }
 
index d76cf8f..de3c091 100644 (file)
@@ -199,7 +199,8 @@ struct sta_rec_sec {
 } __packed;
 
 enum mcu_cipher_type {
-       MCU_CIPHER_WEP40 = 1,
+       MCU_CIPHER_NONE = 0,
+       MCU_CIPHER_WEP40,
        MCU_CIPHER_WEP104,
        MCU_CIPHER_WEP128,
        MCU_CIPHER_TKIP,
index 804e6c4..519361e 100644 (file)
@@ -64,10 +64,9 @@ static struct ipc_chnl_cfg modem_cfg[] = {
 
 int ipc_chnl_cfg_get(struct ipc_chnl_cfg *chnl_cfg, int index)
 {
-       int array_size = ARRAY_SIZE(modem_cfg);
-
-       if (index >= array_size) {
-               pr_err("index: %d and array_size %d", index, array_size);
+       if (index >= ARRAY_SIZE(modem_cfg)) {
+               pr_err("index: %d and array size %zu", index,
+                      ARRAY_SIZE(modem_cfg));
                return -ECHRNG;
        }
 
index 1e18420..d0a98f3 100644 (file)
@@ -41,14 +41,14 @@ struct mhi_wwan_dev {
 /* Increment RX budget and schedule RX refill if necessary */
 static void mhi_wwan_rx_budget_inc(struct mhi_wwan_dev *mhiwwan)
 {
-       spin_lock(&mhiwwan->rx_lock);
+       spin_lock_bh(&mhiwwan->rx_lock);
 
        mhiwwan->rx_budget++;
 
        if (test_bit(MHI_WWAN_RX_REFILL, &mhiwwan->flags))
                schedule_work(&mhiwwan->rx_refill);
 
-       spin_unlock(&mhiwwan->rx_lock);
+       spin_unlock_bh(&mhiwwan->rx_lock);
 }
 
 /* Decrement RX budget if non-zero and return true on success */
@@ -56,7 +56,7 @@ static bool mhi_wwan_rx_budget_dec(struct mhi_wwan_dev *mhiwwan)
 {
        bool ret = false;
 
-       spin_lock(&mhiwwan->rx_lock);
+       spin_lock_bh(&mhiwwan->rx_lock);
 
        if (mhiwwan->rx_budget) {
                mhiwwan->rx_budget--;
@@ -64,7 +64,7 @@ static bool mhi_wwan_rx_budget_dec(struct mhi_wwan_dev *mhiwwan)
                        ret = true;
        }
 
-       spin_unlock(&mhiwwan->rx_lock);
+       spin_unlock_bh(&mhiwwan->rx_lock);
 
        return ret;
 }
@@ -130,9 +130,9 @@ static void mhi_wwan_ctrl_stop(struct wwan_port *port)
 {
        struct mhi_wwan_dev *mhiwwan = wwan_port_get_drvdata(port);
 
-       spin_lock(&mhiwwan->rx_lock);
+       spin_lock_bh(&mhiwwan->rx_lock);
        clear_bit(MHI_WWAN_RX_REFILL, &mhiwwan->flags);
-       spin_unlock(&mhiwwan->rx_lock);
+       spin_unlock_bh(&mhiwwan->rx_lock);
 
        cancel_work_sync(&mhiwwan->rx_refill);
 
index 674a81d..35ece98 100644 (file)
@@ -164,11 +164,14 @@ static struct wwan_device *wwan_create_dev(struct device *parent)
                goto done_unlock;
 
        id = ida_alloc(&wwan_dev_ids, GFP_KERNEL);
-       if (id < 0)
+       if (id < 0) {
+               wwandev = ERR_PTR(id);
                goto done_unlock;
+       }
 
        wwandev = kzalloc(sizeof(*wwandev), GFP_KERNEL);
        if (!wwandev) {
+               wwandev = ERR_PTR(-ENOMEM);
                ida_free(&wwan_dev_ids, id);
                goto done_unlock;
        }
@@ -182,7 +185,8 @@ static struct wwan_device *wwan_create_dev(struct device *parent)
        err = device_register(&wwandev->dev);
        if (err) {
                put_device(&wwandev->dev);
-               wwandev = NULL;
+               wwandev = ERR_PTR(err);
+               goto done_unlock;
        }
 
 done_unlock:
@@ -1014,8 +1018,8 @@ int wwan_register_ops(struct device *parent, const struct wwan_ops *ops,
                return -EINVAL;
 
        wwandev = wwan_create_dev(parent);
-       if (!wwandev)
-               return -ENOMEM;
+       if (IS_ERR(wwandev))
+               return PTR_ERR(wwandev);
 
        if (WARN_ON(wwandev->ops)) {
                wwan_remove_dev(wwandev);
index 2403b71..7454782 100644 (file)
@@ -2527,7 +2527,7 @@ static void deactivate_labels(void *region)
 
 static int init_active_labels(struct nd_region *nd_region)
 {
-       int i;
+       int i, rc = 0;
 
        for (i = 0; i < nd_region->ndr_mappings; i++) {
                struct nd_mapping *nd_mapping = &nd_region->mapping[i];
@@ -2546,13 +2546,14 @@ static int init_active_labels(struct nd_region *nd_region)
                        else if (test_bit(NDD_LABELING, &nvdimm->flags))
                                /* fail, labels needed to disambiguate dpa */;
                        else
-                               return 0;
+                               continue;
 
                        dev_err(&nd_region->dev, "%s: is %s, failing probe\n",
                                        dev_name(&nd_mapping->nvdimm->dev),
                                        test_bit(NDD_LOCKED, &nvdimm->flags)
                                        ? "locked" : "disabled");
-                       return -ENXIO;
+                       rc = -ENXIO;
+                       goto out;
                }
                nd_mapping->ndd = ndd;
                atomic_inc(&nvdimm->busy);
@@ -2586,13 +2587,17 @@ static int init_active_labels(struct nd_region *nd_region)
                        break;
        }
 
-       if (i < nd_region->ndr_mappings) {
+       if (i < nd_region->ndr_mappings)
+               rc = -ENOMEM;
+
+out:
+       if (rc) {
                deactivate_labels(nd_region);
-               return -ENOMEM;
+               return rc;
        }
 
        return devm_add_action_or_reset(&nd_region->dev, deactivate_labels,
-                       nd_region);
+                                       nd_region);
 }
 
 int nd_region_register_namespaces(struct nd_region *nd_region, int *err)
index b335c07..5543c54 100644 (file)
@@ -1856,9 +1856,6 @@ void dev_pm_opp_put_supported_hw(struct opp_table *opp_table)
        if (unlikely(!opp_table))
                return;
 
-       /* Make sure there are no concurrent readers while updating opp_table */
-       WARN_ON(!list_empty(&opp_table->opp_list));
-
        kfree(opp_table->supported_hw);
        opp_table->supported_hw = NULL;
        opp_table->supported_hw_count = 0;
@@ -1944,9 +1941,6 @@ void dev_pm_opp_put_prop_name(struct opp_table *opp_table)
        if (unlikely(!opp_table))
                return;
 
-       /* Make sure there are no concurrent readers while updating opp_table */
-       WARN_ON(!list_empty(&opp_table->opp_list));
-
        kfree(opp_table->prop_name);
        opp_table->prop_name = NULL;
 
@@ -2056,9 +2050,6 @@ void dev_pm_opp_put_regulators(struct opp_table *opp_table)
        if (!opp_table->regulators)
                goto put_opp_table;
 
-       /* Make sure there are no concurrent readers while updating opp_table */
-       WARN_ON(!list_empty(&opp_table->opp_list));
-
        if (opp_table->enabled) {
                for (i = opp_table->regulator_count - 1; i >= 0; i--)
                        regulator_disable(opp_table->regulators[i]);
@@ -2178,9 +2169,6 @@ void dev_pm_opp_put_clkname(struct opp_table *opp_table)
        if (unlikely(!opp_table))
                return;
 
-       /* Make sure there are no concurrent readers while updating opp_table */
-       WARN_ON(!list_empty(&opp_table->opp_list));
-
        clk_put(opp_table->clk);
        opp_table->clk = ERR_PTR(-EINVAL);
 
@@ -2279,9 +2267,6 @@ void dev_pm_opp_unregister_set_opp_helper(struct opp_table *opp_table)
        if (unlikely(!opp_table))
                return;
 
-       /* Make sure there are no concurrent readers while updating opp_table */
-       WARN_ON(!list_empty(&opp_table->opp_list));
-
        opp_table->set_opp = NULL;
 
        mutex_lock(&opp_table->lock);
index d298e38..67f2e07 100644 (file)
@@ -964,8 +964,9 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table)
                }
        }
 
-       /* There should be one of more OPP defined */
-       if (WARN_ON(!count)) {
+       /* There should be one or more OPPs defined */
+       if (!count) {
+               dev_err(dev, "%s: no supported OPPs", __func__);
                ret = -ENOENT;
                goto remove_static_opp;
        }
index 896a45b..654ac4a 100644 (file)
@@ -145,7 +145,7 @@ static int ixp4xx_pci_check_master_abort(struct ixp4xx_pci *p)
        return 0;
 }
 
-static int ixp4xx_pci_read(struct ixp4xx_pci *p, u32 addr, u32 cmd, u32 *data)
+static int ixp4xx_pci_read_indirect(struct ixp4xx_pci *p, u32 addr, u32 cmd, u32 *data)
 {
        ixp4xx_writel(p, IXP4XX_PCI_NP_AD, addr);
 
@@ -170,7 +170,7 @@ static int ixp4xx_pci_read(struct ixp4xx_pci *p, u32 addr, u32 cmd, u32 *data)
        return ixp4xx_pci_check_master_abort(p);
 }
 
-static int ixp4xx_pci_write(struct ixp4xx_pci *p, u32 addr, u32 cmd, u32 data)
+static int ixp4xx_pci_write_indirect(struct ixp4xx_pci *p, u32 addr, u32 cmd, u32 data)
 {
        ixp4xx_writel(p, IXP4XX_PCI_NP_AD, addr);
 
@@ -308,7 +308,7 @@ static int ixp4xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
        dev_dbg(p->dev, "read_config from %d size %d dev %d:%d:%d address: %08x cmd: %08x\n",
                where, size, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn), addr, cmd);
 
-       ret = ixp4xx_pci_read(p, addr, cmd, &val);
+       ret = ixp4xx_pci_read_indirect(p, addr, cmd, &val);
        if (ret)
                return PCIBIOS_DEVICE_NOT_FOUND;
 
@@ -356,7 +356,7 @@ static int ixp4xx_pci_write_config(struct pci_bus *bus,  unsigned int devfn,
        dev_dbg(p->dev, "write_config_byte %#x to %d size %d dev %d:%d:%d addr: %08x cmd %08x\n",
                value, where, size, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn), addr, cmd);
 
-       ret = ixp4xx_pci_write(p, addr, cmd, val);
+       ret = ixp4xx_pci_write_indirect(p, addr, cmd, val);
        if (ret)
                return PCIBIOS_DEVICE_NOT_FOUND;
 
index 9232255..e5e7533 100644 (file)
@@ -143,24 +143,25 @@ static inline __attribute_const__ u32 msi_mask(unsigned x)
  * reliably as devices without an INTx disable bit will then generate a
  * level IRQ which will never be cleared.
  */
-u32 __pci_msi_desc_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
+void __pci_msi_desc_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
 {
-       u32 mask_bits = desc->masked;
+       raw_spinlock_t *lock = &desc->dev->msi_lock;
+       unsigned long flags;
 
        if (pci_msi_ignore_mask || !desc->msi_attrib.maskbit)
-               return 0;
+               return;
 
-       mask_bits &= ~mask;
-       mask_bits |= flag;
+       raw_spin_lock_irqsave(lock, flags);
+       desc->masked &= ~mask;
+       desc->masked |= flag;
        pci_write_config_dword(msi_desc_to_pci_dev(desc), desc->mask_pos,
-                              mask_bits);
-
-       return mask_bits;
+                              desc->masked);
+       raw_spin_unlock_irqrestore(lock, flags);
 }
 
 static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
 {
-       desc->masked = __pci_msi_desc_mask_irq(desc, mask, flag);
+       __pci_msi_desc_mask_irq(desc, mask, flag);
 }
 
 static void __iomem *pci_msix_desc_addr(struct msi_desc *desc)
@@ -289,13 +290,31 @@ void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
                /* Don't touch the hardware now */
        } else if (entry->msi_attrib.is_msix) {
                void __iomem *base = pci_msix_desc_addr(entry);
+               bool unmasked = !(entry->masked & PCI_MSIX_ENTRY_CTRL_MASKBIT);
 
                if (!base)
                        goto skip;
 
+               /*
+                * The specification mandates that the entry is masked
+                * when the message is modified:
+                *
+                * "If software changes the Address or Data value of an
+                * entry while the entry is unmasked, the result is
+                * undefined."
+                */
+               if (unmasked)
+                       __pci_msix_desc_mask_irq(entry, PCI_MSIX_ENTRY_CTRL_MASKBIT);
+
                writel(msg->address_lo, base + PCI_MSIX_ENTRY_LOWER_ADDR);
                writel(msg->address_hi, base + PCI_MSIX_ENTRY_UPPER_ADDR);
                writel(msg->data, base + PCI_MSIX_ENTRY_DATA);
+
+               if (unmasked)
+                       __pci_msix_desc_mask_irq(entry, 0);
+
+               /* Ensure that the writes are visible in the device */
+               readl(base + PCI_MSIX_ENTRY_DATA);
        } else {
                int pos = dev->msi_cap;
                u16 msgctl;
@@ -316,6 +335,8 @@ void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
                        pci_write_config_word(dev, pos + PCI_MSI_DATA_32,
                                              msg->data);
                }
+               /* Ensure that the writes are visible in the device */
+               pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl);
        }
 
 skip:
@@ -636,21 +657,21 @@ static int msi_capability_init(struct pci_dev *dev, int nvec,
        /* Configure MSI capability structure */
        ret = pci_msi_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSI);
        if (ret) {
-               msi_mask_irq(entry, mask, ~mask);
+               msi_mask_irq(entry, mask, 0);
                free_msi_irqs(dev);
                return ret;
        }
 
        ret = msi_verify_entries(dev);
        if (ret) {
-               msi_mask_irq(entry, mask, ~mask);
+               msi_mask_irq(entry, mask, 0);
                free_msi_irqs(dev);
                return ret;
        }
 
        ret = populate_msi_sysfs(dev);
        if (ret) {
-               msi_mask_irq(entry, mask, ~mask);
+               msi_mask_irq(entry, mask, 0);
                free_msi_irqs(dev);
                return ret;
        }
@@ -691,6 +712,7 @@ static int msix_setup_entries(struct pci_dev *dev, void __iomem *base,
 {
        struct irq_affinity_desc *curmsk, *masks = NULL;
        struct msi_desc *entry;
+       void __iomem *addr;
        int ret, i;
        int vec_count = pci_msix_vec_count(dev);
 
@@ -711,6 +733,7 @@ static int msix_setup_entries(struct pci_dev *dev, void __iomem *base,
 
                entry->msi_attrib.is_msix       = 1;
                entry->msi_attrib.is_64         = 1;
+
                if (entries)
                        entry->msi_attrib.entry_nr = entries[i].entry;
                else
@@ -722,6 +745,10 @@ static int msix_setup_entries(struct pci_dev *dev, void __iomem *base,
                entry->msi_attrib.default_irq   = dev->irq;
                entry->mask_base                = base;
 
+               addr = pci_msix_desc_addr(entry);
+               if (addr)
+                       entry->masked = readl(addr + PCI_MSIX_ENTRY_VECTOR_CTRL);
+
                list_add_tail(&entry->list, dev_to_msi_list(&dev->dev));
                if (masks)
                        curmsk++;
@@ -732,26 +759,25 @@ out:
        return ret;
 }
 
-static void msix_program_entries(struct pci_dev *dev,
-                                struct msix_entry *entries)
+static void msix_update_entries(struct pci_dev *dev, struct msix_entry *entries)
 {
        struct msi_desc *entry;
-       int i = 0;
-       void __iomem *desc_addr;
 
        for_each_pci_msi_entry(entry, dev) {
-               if (entries)
-                       entries[i++].vector = entry->irq;
+               if (entries) {
+                       entries->vector = entry->irq;
+                       entries++;
+               }
+       }
+}
 
-               desc_addr = pci_msix_desc_addr(entry);
-               if (desc_addr)
-                       entry->masked = readl(desc_addr +
-                                             PCI_MSIX_ENTRY_VECTOR_CTRL);
-               else
-                       entry->masked = 0;
+static void msix_mask_all(void __iomem *base, int tsize)
+{
+       u32 ctrl = PCI_MSIX_ENTRY_CTRL_MASKBIT;
+       int i;
 
-               msix_mask_irq(entry, 1);
-       }
+       for (i = 0; i < tsize; i++, base += PCI_MSIX_ENTRY_SIZE)
+               writel(ctrl, base + PCI_MSIX_ENTRY_VECTOR_CTRL);
 }
 
 /**
@@ -768,22 +794,33 @@ static void msix_program_entries(struct pci_dev *dev,
 static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
                                int nvec, struct irq_affinity *affd)
 {
-       int ret;
-       u16 control;
        void __iomem *base;
+       int ret, tsize;
+       u16 control;
 
-       /* Ensure MSI-X is disabled while it is set up */
-       pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
+       /*
+        * Some devices require MSI-X to be enabled before the MSI-X
+        * registers can be accessed.  Mask all the vectors to prevent
+        * interrupts coming in before they're fully set up.
+        */
+       pci_msix_clear_and_set_ctrl(dev, 0, PCI_MSIX_FLAGS_MASKALL |
+                                   PCI_MSIX_FLAGS_ENABLE);
 
        pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
        /* Request & Map MSI-X table region */
-       base = msix_map_region(dev, msix_table_size(control));
-       if (!base)
-               return -ENOMEM;
+       tsize = msix_table_size(control);
+       base = msix_map_region(dev, tsize);
+       if (!base) {
+               ret = -ENOMEM;
+               goto out_disable;
+       }
+
+       /* Ensure that all table entries are masked. */
+       msix_mask_all(base, tsize);
 
        ret = msix_setup_entries(dev, base, entries, nvec, affd);
        if (ret)
-               return ret;
+               goto out_disable;
 
        ret = pci_msi_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX);
        if (ret)
@@ -794,15 +831,7 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
        if (ret)
                goto out_free;
 
-       /*
-        * Some devices require MSI-X to be enabled before we can touch the
-        * MSI-X registers.  We need to mask all the vectors to prevent
-        * interrupts coming in before they're fully set up.
-        */
-       pci_msix_clear_and_set_ctrl(dev, 0,
-                               PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE);
-
-       msix_program_entries(dev, entries);
+       msix_update_entries(dev, entries);
 
        ret = populate_msi_sysfs(dev);
        if (ret)
@@ -836,6 +865,9 @@ out_avail:
 out_free:
        free_msi_irqs(dev);
 
+out_disable:
+       pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
+
        return ret;
 }
 
@@ -930,8 +962,7 @@ static void pci_msi_shutdown(struct pci_dev *dev)
 
        /* Return the device with MSI unmasked as initial states */
        mask = msi_mask(desc->msi_attrib.multi_cap);
-       /* Keep cached state to be restored */
-       __pci_msi_desc_mask_irq(desc, mask, ~mask);
+       msi_mask_irq(desc, mask, 0);
 
        /* Restore dev->irq to its default pin-assertion IRQ */
        dev->irq = desc->msi_attrib.default_irq;
@@ -1016,10 +1047,8 @@ static void pci_msix_shutdown(struct pci_dev *dev)
        }
 
        /* Return the device with MSI-X masked as initial states */
-       for_each_pci_msi_entry(entry, dev) {
-               /* Keep cached states to be restored */
+       for_each_pci_msi_entry(entry, dev)
                __pci_msix_desc_mask_irq(entry, 1);
-       }
 
        pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
        pci_intx_for_msi(dev, 1);
index 5d63df7..7bbf267 100644 (file)
@@ -978,7 +978,7 @@ void pci_create_legacy_files(struct pci_bus *b)
        b->legacy_mem->size = 1024*1024;
        b->legacy_mem->attr.mode = 0600;
        b->legacy_mem->mmap = pci_mmap_legacy_mem;
-       b->legacy_io->mapping = iomem_get_mapping();
+       b->legacy_mem->mapping = iomem_get_mapping();
        pci_adjust_legacy_attr(b, pci_mmap_mem);
        error = device_create_bin_file(&b->dev, b->legacy_mem);
        if (error)
index 6d74386..ab3de15 100644 (file)
@@ -1900,6 +1900,7 @@ static void quirk_ryzen_xhci_d3hot(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x15e0, quirk_ryzen_xhci_d3hot);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x15e1, quirk_ryzen_xhci_d3hot);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x1639, quirk_ryzen_xhci_d3hot);
 
 #ifdef CONFIG_X86_IO_APIC
 static int dmi_disable_ioapicreroute(const struct dmi_system_id *d)
index 3e4ef2b..0bcd195 100644 (file)
@@ -701,32 +701,32 @@ static const struct pinctrl_pin_desc tglh_pins[] = {
 
 static const struct intel_padgroup tglh_community0_gpps[] = {
        TGL_GPP(0, 0, 24, 0),                           /* GPP_A */
-       TGL_GPP(1, 25, 44, 128),                        /* GPP_R */
-       TGL_GPP(2, 45, 70, 32),                         /* GPP_B */
-       TGL_GPP(3, 71, 78, INTEL_GPIO_BASE_NOMAP),      /* vGPIO_0 */
+       TGL_GPP(1, 25, 44, 32),                         /* GPP_R */
+       TGL_GPP(2, 45, 70, 64),                         /* GPP_B */
+       TGL_GPP(3, 71, 78, 96),                         /* vGPIO_0 */
 };
 
 static const struct intel_padgroup tglh_community1_gpps[] = {
-       TGL_GPP(0, 79, 104, 96),                        /* GPP_D */
-       TGL_GPP(1, 105, 128, 64),                       /* GPP_C */
-       TGL_GPP(2, 129, 136, 160),                      /* GPP_S */
-       TGL_GPP(3, 137, 153, 192),                      /* GPP_G */
-       TGL_GPP(4, 154, 180, 224),                      /* vGPIO */
+       TGL_GPP(0, 79, 104, 128),                       /* GPP_D */
+       TGL_GPP(1, 105, 128, 160),                      /* GPP_C */
+       TGL_GPP(2, 129, 136, 192),                      /* GPP_S */
+       TGL_GPP(3, 137, 153, 224),                      /* GPP_G */
+       TGL_GPP(4, 154, 180, 256),                      /* vGPIO */
 };
 
 static const struct intel_padgroup tglh_community3_gpps[] = {
-       TGL_GPP(0, 181, 193, 256),                      /* GPP_E */
-       TGL_GPP(1, 194, 217, 288),                      /* GPP_F */
+       TGL_GPP(0, 181, 193, 288),                      /* GPP_E */
+       TGL_GPP(1, 194, 217, 320),                      /* GPP_F */
 };
 
 static const struct intel_padgroup tglh_community4_gpps[] = {
-       TGL_GPP(0, 218, 241, 320),                      /* GPP_H */
+       TGL_GPP(0, 218, 241, 352),                      /* GPP_H */
        TGL_GPP(1, 242, 251, 384),                      /* GPP_J */
-       TGL_GPP(2, 252, 266, 352),                      /* GPP_K */
+       TGL_GPP(2, 252, 266, 416),                      /* GPP_K */
 };
 
 static const struct intel_padgroup tglh_community5_gpps[] = {
-       TGL_GPP(0, 267, 281, 416),                      /* GPP_I */
+       TGL_GPP(0, 267, 281, 448),                      /* GPP_I */
        TGL_GPP(1, 282, 290, INTEL_GPIO_BASE_NOMAP),    /* JTAG */
 };
 
index 5b3b048..45ebdeb 100644 (file)
@@ -925,12 +925,10 @@ int mtk_pinconf_adv_pull_set(struct mtk_pinctrl *hw,
                        err = hw->soc->bias_set(hw, desc, pullup);
                        if (err)
                                return err;
-               } else if (hw->soc->bias_set_combo) {
-                       err = hw->soc->bias_set_combo(hw, desc, pullup, arg);
-                       if (err)
-                               return err;
                } else {
-                       return -ENOTSUPP;
+                       err = mtk_pinconf_bias_set_rev1(hw, desc, pullup);
+                       if (err)
+                               err = mtk_pinconf_bias_set(hw, desc, pullup);
                }
        }
 
index a76be6c..5b76474 100644 (file)
@@ -444,8 +444,7 @@ static int amd_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
        unsigned long flags;
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
        struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
-       u32 wake_mask = BIT(WAKE_CNTRL_OFF_S0I3) | BIT(WAKE_CNTRL_OFF_S3) |
-                       BIT(WAKE_CNTRL_OFF_S4);
+       u32 wake_mask = BIT(WAKE_CNTRL_OFF_S0I3) | BIT(WAKE_CNTRL_OFF_S3);
 
        raw_spin_lock_irqsave(&gpio_dev->lock, flags);
        pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
index f831526..49e3268 100644 (file)
@@ -950,23 +950,37 @@ static int k210_fpioa_probe(struct platform_device *pdev)
                return ret;
 
        pdata->pclk = devm_clk_get_optional(dev, "pclk");
-       if (!IS_ERR(pdata->pclk))
-               clk_prepare_enable(pdata->pclk);
+       if (!IS_ERR(pdata->pclk)) {
+               ret = clk_prepare_enable(pdata->pclk);
+               if (ret)
+                       goto disable_clk;
+       }
 
        pdata->sysctl_map =
                syscon_regmap_lookup_by_phandle_args(np,
                                                "canaan,k210-sysctl-power",
                                                1, &pdata->power_offset);
-       if (IS_ERR(pdata->sysctl_map))
-               return PTR_ERR(pdata->sysctl_map);
+       if (IS_ERR(pdata->sysctl_map)) {
+               ret = PTR_ERR(pdata->sysctl_map);
+               goto disable_pclk;
+       }
 
        k210_fpioa_init_ties(pdata);
 
        pdata->pctl = pinctrl_register(&k210_pinctrl_desc, dev, (void *)pdata);
-       if (IS_ERR(pdata->pctl))
-               return PTR_ERR(pdata->pctl);
+       if (IS_ERR(pdata->pctl)) {
+               ret = PTR_ERR(pdata->pctl);
+               goto disable_pclk;
+       }
 
        return 0;
+
+disable_pclk:
+       clk_disable_unprepare(pdata->pclk);
+disable_clk:
+       clk_disable_unprepare(pdata->clk);
+
+       return ret;
 }
 
 static const struct of_device_id k210_fpioa_dt_ids[] = {
index 2f51b4f..cad4e60 100644 (file)
@@ -13,7 +13,7 @@ config PINCTRL_MSM
 
 config PINCTRL_APQ8064
        tristate "Qualcomm APQ8064 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -21,7 +21,7 @@ config PINCTRL_APQ8064
 
 config PINCTRL_APQ8084
        tristate "Qualcomm APQ8084 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -29,7 +29,7 @@ config PINCTRL_APQ8084
 
 config PINCTRL_IPQ4019
        tristate "Qualcomm IPQ4019 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -37,7 +37,7 @@ config PINCTRL_IPQ4019
 
 config PINCTRL_IPQ8064
        tristate "Qualcomm IPQ8064 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -45,7 +45,7 @@ config PINCTRL_IPQ8064
 
 config PINCTRL_IPQ8074
        tristate "Qualcomm Technologies, Inc. IPQ8074 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for
@@ -55,7 +55,7 @@ config PINCTRL_IPQ8074
 
 config PINCTRL_IPQ6018
        tristate "Qualcomm Technologies, Inc. IPQ6018 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for
@@ -65,7 +65,7 @@ config PINCTRL_IPQ6018
 
 config PINCTRL_MSM8226
        tristate "Qualcomm 8226 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -74,7 +74,7 @@ config PINCTRL_MSM8226
 
 config PINCTRL_MSM8660
        tristate "Qualcomm 8660 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -82,7 +82,7 @@ config PINCTRL_MSM8660
 
 config PINCTRL_MSM8960
        tristate "Qualcomm 8960 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -90,7 +90,7 @@ config PINCTRL_MSM8960
 
 config PINCTRL_MDM9615
        tristate "Qualcomm 9615 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -98,7 +98,7 @@ config PINCTRL_MDM9615
 
 config PINCTRL_MSM8X74
        tristate "Qualcomm 8x74 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -106,7 +106,7 @@ config PINCTRL_MSM8X74
 
 config PINCTRL_MSM8916
        tristate "Qualcomm 8916 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -114,7 +114,7 @@ config PINCTRL_MSM8916
 
 config PINCTRL_MSM8953
        tristate "Qualcomm 8953 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -124,7 +124,7 @@ config PINCTRL_MSM8953
 
 config PINCTRL_MSM8976
        tristate "Qualcomm 8976 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -134,7 +134,7 @@ config PINCTRL_MSM8976
 
 config PINCTRL_MSM8994
        tristate "Qualcomm 8994 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -143,7 +143,7 @@ config PINCTRL_MSM8994
 
 config PINCTRL_MSM8996
        tristate "Qualcomm MSM8996 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -151,7 +151,7 @@ config PINCTRL_MSM8996
 
 config PINCTRL_MSM8998
        tristate "Qualcomm MSM8998 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -159,7 +159,7 @@ config PINCTRL_MSM8998
 
 config PINCTRL_QCS404
        tristate "Qualcomm QCS404 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -167,7 +167,7 @@ config PINCTRL_QCS404
 
 config PINCTRL_QDF2XXX
        tristate "Qualcomm Technologies QDF2xxx pin controller driver"
-       depends on GPIOLIB && ACPI
+       depends on ACPI
        depends on PINCTRL_MSM
        help
          This is the GPIO driver for the TLMM block found on the
@@ -175,7 +175,7 @@ config PINCTRL_QDF2XXX
 
 config PINCTRL_QCOM_SPMI_PMIC
        tristate "Qualcomm SPMI PMIC pin controller driver"
-       depends on GPIOLIB && OF && SPMI
+       depends on OF && SPMI
        select REGMAP_SPMI
        select PINMUX
        select PINCONF
@@ -190,7 +190,7 @@ config PINCTRL_QCOM_SPMI_PMIC
 
 config PINCTRL_QCOM_SSBI_PMIC
        tristate "Qualcomm SSBI PMIC pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        select PINMUX
        select PINCONF
        select GENERIC_PINCONF
@@ -204,7 +204,7 @@ config PINCTRL_QCOM_SSBI_PMIC
 
 config PINCTRL_SC7180
        tristate "Qualcomm Technologies Inc SC7180 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -213,7 +213,7 @@ config PINCTRL_SC7180
 
 config PINCTRL_SC7280
        tristate "Qualcomm Technologies Inc SC7280 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -222,7 +222,7 @@ config PINCTRL_SC7280
 
 config PINCTRL_SC8180X
        tristate "Qualcomm Technologies Inc SC8180x pin controller driver"
-       depends on GPIOLIB && (OF || ACPI)
+       depends on (OF || ACPI)
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -231,7 +231,7 @@ config PINCTRL_SC8180X
 
 config PINCTRL_SDM660
        tristate "Qualcomm Technologies Inc SDM660 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
         This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -240,7 +240,7 @@ config PINCTRL_SDM660
 
 config PINCTRL_SDM845
        tristate "Qualcomm Technologies Inc SDM845 pin controller driver"
-       depends on GPIOLIB && (OF || ACPI)
+       depends on (OF || ACPI)
        depends on PINCTRL_MSM
        help
         This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -249,7 +249,7 @@ config PINCTRL_SDM845
 
 config PINCTRL_SDX55
        tristate "Qualcomm Technologies Inc SDX55 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
         This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -258,7 +258,7 @@ config PINCTRL_SDX55
 
 config PINCTRL_SM6125
        tristate "Qualcomm Technologies Inc SM6125 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
         This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -267,7 +267,7 @@ config PINCTRL_SM6125
 
 config PINCTRL_SM8150
        tristate "Qualcomm Technologies Inc SM8150 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
         This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -276,7 +276,7 @@ config PINCTRL_SM8150
 
 config PINCTRL_SM8250
        tristate "Qualcomm Technologies Inc SM8250 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -285,8 +285,7 @@ config PINCTRL_SM8250
 
 config PINCTRL_SM8350
        tristate "Qualcomm Technologies Inc SM8350 pin controller driver"
-       depends on GPIOLIB && OF
-       select PINCTRL_MSM
+       depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
          Qualcomm Technologies Inc TLMM block found on the Qualcomm
index dc8d39a..9c7679c 100644 (file)
@@ -1219,10 +1219,12 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev)
        }
 
        /*
-        * We suppose that we won't have any more functions than pins,
-        * we'll reallocate that later anyway
+        * Find an upper bound for the maximum number of functions: in
+        * the worst case we have gpio_in, gpio_out, irq and up to four
+        * special functions per pin, plus one entry for the sentinel.
+        * We'll reallocate that later anyway.
         */
-       pctl->functions = kcalloc(pctl->ngroups,
+       pctl->functions = kcalloc(4 * pctl->ngroups + 4,
                                  sizeof(*pctl->functions),
                                  GFP_KERNEL);
        if (!pctl->functions)
index 7d385c3..d12db6c 100644 (file)
@@ -508,6 +508,7 @@ config THINKPAD_ACPI
        depends on RFKILL || RFKILL = n
        depends on ACPI_VIDEO || ACPI_VIDEO = n
        depends on BACKLIGHT_CLASS_DEVICE
+       depends on I2C
        select ACPI_PLATFORM_PROFILE
        select HWMON
        select NVRAM
@@ -691,6 +692,7 @@ config INTEL_HID_EVENT
        tristate "INTEL HID Event"
        depends on ACPI
        depends on INPUT
+       depends on I2C
        select INPUT_SPARSEKMAP
        help
          This driver provides support for the Intel HID Event hotkey interface.
@@ -742,6 +744,7 @@ config INTEL_VBTN
        tristate "INTEL VIRTUAL BUTTON"
        depends on ACPI
        depends on INPUT
+       depends on I2C
        select INPUT_SPARSEKMAP
        help
          This driver provides support for the Intel Virtual Button interface.
index 0cb927f..a81dc4b 100644 (file)
@@ -41,6 +41,10 @@ static int wapf = -1;
 module_param(wapf, uint, 0444);
 MODULE_PARM_DESC(wapf, "WAPF value");
 
+static int tablet_mode_sw = -1;
+module_param(tablet_mode_sw, uint, 0444);
+MODULE_PARM_DESC(tablet_mode_sw, "Tablet mode detect: -1:auto 0:disable 1:kbd-dock 2:lid-flip");
+
 static struct quirk_entry *quirks;
 
 static bool asus_q500a_i8042_filter(unsigned char data, unsigned char str,
@@ -458,6 +462,15 @@ static const struct dmi_system_id asus_quirks[] = {
                },
                .driver_data = &quirk_asus_use_lid_flip_devid,
        },
+       {
+               .callback = dmi_matched,
+               .ident = "ASUS TP200s / E205SA",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "E205SA"),
+               },
+               .driver_data = &quirk_asus_use_lid_flip_devid,
+       },
        {},
 };
 
@@ -477,6 +490,21 @@ static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver)
        else
                wapf = quirks->wapf;
 
+       switch (tablet_mode_sw) {
+       case 0:
+               quirks->use_kbd_dock_devid = false;
+               quirks->use_lid_flip_devid = false;
+               break;
+       case 1:
+               quirks->use_kbd_dock_devid = true;
+               quirks->use_lid_flip_devid = false;
+               break;
+       case 2:
+               quirks->use_kbd_dock_devid = false;
+               quirks->use_lid_flip_devid = true;
+               break;
+       }
+
        if (quirks->i8042_filter) {
                ret = i8042_install_filter(quirks->i8042_filter);
                if (ret) {
diff --git a/drivers/platform/x86/dual_accel_detect.h b/drivers/platform/x86/dual_accel_detect.h
new file mode 100644 (file)
index 0000000..a9eae17
--- /dev/null
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Helper code to detect 360 degree hinges (yoga) style 2-in-1 devices using 2 accelerometers
+ * to allow the OS to determine the angle between the display and the base of the device.
+ *
+ * On Windows these are read by a special HingeAngleService process which calls undocumented
+ * ACPI methods, to let the firmware know if the 2-in-1 is in tablet- or laptop-mode.
+ * The firmware may use this to disable the kbd and touchpad to avoid spurious input in
+ * tablet-mode as well as to report SW_TABLET_MODE info to the OS.
+ *
+ * Since Linux does not call these undocumented methods, the SW_TABLET_MODE info reported
+ * by various drivers/platform/x86 drivers is incorrect. These drivers use the detection
+ * code in this file to disable SW_TABLET_MODE reporting to avoid reporting broken info
+ * (instead userspace can derive the status itself by directly reading the 2 accels).
+ */
+
+#include <linux/acpi.h>
+#include <linux/i2c.h>
+
+static int dual_accel_i2c_resource_count(struct acpi_resource *ares, void *data)
+{
+       struct acpi_resource_i2c_serialbus *sb;
+       int *count = data;
+
+       if (i2c_acpi_get_i2c_resource(ares, &sb))
+               *count = *count + 1;
+
+       return 1;
+}
+
+static int dual_accel_i2c_client_count(struct acpi_device *adev)
+{
+       int ret, count = 0;
+       LIST_HEAD(r);
+
+       ret = acpi_dev_get_resources(adev, &r, dual_accel_i2c_resource_count, &count);
+       if (ret < 0)
+               return ret;
+
+       acpi_dev_free_resource_list(&r);
+       return count;
+}
+
+static bool dual_accel_detect_bosc0200(void)
+{
+       struct acpi_device *adev;
+       int count;
+
+       adev = acpi_dev_get_first_match_dev("BOSC0200", NULL, -1);
+       if (!adev)
+               return false;
+
+       count = dual_accel_i2c_client_count(adev);
+
+       acpi_dev_put(adev);
+
+       return count == 2;
+}
+
+static bool dual_accel_detect(void)
+{
+       /* Systems which use a pair of accels with KIOX010A / KIOX020A ACPI ids */
+       if (acpi_dev_present("KIOX010A", NULL, -1) &&
+           acpi_dev_present("KIOX020A", NULL, -1))
+               return true;
+
+       /* Systems which use a single DUAL250E ACPI device to model 2 accels */
+       if (acpi_dev_present("DUAL250E", NULL, -1))
+               return true;
+
+       /* Systems which use a single BOSC0200 ACPI device to model 2 accels */
+       if (dual_accel_detect_bosc0200())
+               return true;
+
+       return false;
+}
index fbb224a..7f3a03f 100644 (file)
@@ -140,6 +140,7 @@ static u8 gigabyte_wmi_detect_sensor_usability(struct wmi_device *wdev)
        }}
 
 static const struct dmi_system_id gigabyte_wmi_known_working_platforms[] = {
+       DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B450M S2H V2"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE V2"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 GAMING X V2"),
@@ -147,6 +148,7 @@ static const struct dmi_system_id gigabyte_wmi_known_working_platforms[] = {
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550M DS3H"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("Z390 I AORUS PRO WIFI-CF"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 AORUS ELITE"),
+       DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 GAMING X"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 I AORUS PRO WIFI"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 UD"),
        { }
index e5fbe01..2e4e97a 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/suspend.h>
+#include "dual_accel_detect.h"
 
 /* When NOT in tablet mode, VGBS returns with the flag 0x40 */
 #define TABLET_MODE_FLAG BIT(6)
@@ -122,6 +123,7 @@ struct intel_hid_priv {
        struct input_dev *array;
        struct input_dev *switches;
        bool wakeup_mode;
+       bool dual_accel;
 };
 
 #define HID_EVENT_FILTER_UUID  "eeec56b3-4442-408f-a792-4edd4d758054"
@@ -451,22 +453,9 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
         * SW_TABLET_MODE report, in these cases we enable support when receiving
         * the first event instead of during driver setup.
         *
-        * Some 360 degree hinges (yoga) style 2-in-1 devices use 2 accelerometers
-        * to allow the OS to determine the angle between the display and the base
-        * of the device. On Windows these are read by a special HingeAngleService
-        * process which calls an ACPI DSM (Device Specific Method) on the
-        * ACPI KIOX010A device node for the sensor in the display, to let the
-        * firmware know if the 2-in-1 is in tablet- or laptop-mode so that it can
-        * disable the kbd and touchpad to avoid spurious input in tablet-mode.
-        *
-        * The linux kxcjk1013 driver calls the DSM for this once at probe time
-        * to ensure that the builtin kbd and touchpad work. On some devices this
-        * causes a "spurious" 0xcd event on the intel-hid ACPI dev. In this case
-        * there is not a functional tablet-mode switch, so we should not register
-        * the tablet-mode switch device.
+        * See dual_accel_detect.h for more info on the dual_accel check.
         */
-       if (!priv->switches && (event == 0xcc || event == 0xcd) &&
-           !acpi_dev_present("KIOX010A", NULL, -1)) {
+       if (!priv->switches && !priv->dual_accel && (event == 0xcc || event == 0xcd)) {
                dev_info(&device->dev, "switch event received, enable switches supports\n");
                err = intel_hid_switches_setup(device);
                if (err)
@@ -607,6 +596,8 @@ static int intel_hid_probe(struct platform_device *device)
                return -ENOMEM;
        dev_set_drvdata(&device->dev, priv);
 
+       priv->dual_accel = dual_accel_detect();
+
        err = intel_hid_input_setup(device);
        if (err) {
                pr_err("Failed to setup Intel HID hotkeys\n");
index 888a764..3091664 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/suspend.h>
+#include "dual_accel_detect.h"
 
 /* Returned when NOT in tablet mode on some HP Stream x360 11 models */
 #define VGBS_TABLET_MODE_FLAG_ALT      0x10
@@ -66,6 +67,7 @@ static const struct key_entry intel_vbtn_switchmap[] = {
 struct intel_vbtn_priv {
        struct input_dev *buttons_dev;
        struct input_dev *switches_dev;
+       bool dual_accel;
        bool has_buttons;
        bool has_switches;
        bool wakeup_mode;
@@ -160,6 +162,10 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
                input_dev = priv->buttons_dev;
        } else if ((ke = sparse_keymap_entry_from_scancode(priv->switches_dev, event))) {
                if (!priv->has_switches) {
+                       /* See dual_accel_detect.h for more info */
+                       if (priv->dual_accel)
+                               return;
+
                        dev_info(&device->dev, "Registering Intel Virtual Switches input-dev after receiving a switch event\n");
                        ret = input_register_device(priv->switches_dev);
                        if (ret)
@@ -248,11 +254,15 @@ static const struct dmi_system_id dmi_switches_allow_list[] = {
        {} /* Array terminator */
 };
 
-static bool intel_vbtn_has_switches(acpi_handle handle)
+static bool intel_vbtn_has_switches(acpi_handle handle, bool dual_accel)
 {
        unsigned long long vgbs;
        acpi_status status;
 
+       /* See dual_accel_detect.h for more info */
+       if (dual_accel)
+               return false;
+
        if (!dmi_check_system(dmi_switches_allow_list))
                return false;
 
@@ -263,13 +273,14 @@ static bool intel_vbtn_has_switches(acpi_handle handle)
 static int intel_vbtn_probe(struct platform_device *device)
 {
        acpi_handle handle = ACPI_HANDLE(&device->dev);
-       bool has_buttons, has_switches;
+       bool dual_accel, has_buttons, has_switches;
        struct intel_vbtn_priv *priv;
        acpi_status status;
        int err;
 
+       dual_accel = dual_accel_detect();
        has_buttons = acpi_has_method(handle, "VBDL");
-       has_switches = intel_vbtn_has_switches(handle);
+       has_switches = intel_vbtn_has_switches(handle, dual_accel);
 
        if (!has_buttons && !has_switches) {
                dev_warn(&device->dev, "failed to read Intel Virtual Button driver\n");
@@ -281,6 +292,7 @@ static int intel_vbtn_probe(struct platform_device *device)
                return -ENOMEM;
        dev_set_drvdata(&device->dev, priv);
 
+       priv->dual_accel = dual_accel;
        priv->has_buttons = has_buttons;
        priv->has_switches = has_switches;
 
index c37349f..d063d91 100644 (file)
@@ -94,6 +94,7 @@ static struct gpiod_lookup_table gpios_led_table = {
                                NULL, 1, GPIO_ACTIVE_LOW),
                GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_LED3,
                                NULL, 2, GPIO_ACTIVE_LOW),
+               {} /* Terminating entry */
        }
 };
 
@@ -123,6 +124,7 @@ static struct gpiod_lookup_table gpios_key_table = {
        .table = {
                GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_MODESW,
                                NULL, 0, GPIO_ACTIVE_LOW),
+               {} /* Terminating entry */
        }
 };
 
index 603156a..50ff04c 100644 (file)
@@ -73,6 +73,7 @@
 #include <linux/uaccess.h>
 #include <acpi/battery.h>
 #include <acpi/video.h>
+#include "dual_accel_detect.h"
 
 /* ThinkPad CMOS commands */
 #define TP_CMOS_VOLUME_DOWN    0
@@ -3232,7 +3233,7 @@ static int hotkey_init_tablet_mode(void)
                 * the laptop/tent/tablet mode to the EC. The bmc150 iio driver
                 * does not support this, so skip the hotkey on these models.
                 */
-               if (has_tablet_mode && !acpi_dev_present("BOSC0200", "1", -1))
+               if (has_tablet_mode && !dual_accel_detect())
                        tp_features.hotkey_tablet = TP_HOTKEY_TABLET_USES_GMMS;
                type = "GMMS";
        } else if (acpi_evalf(hkey_handle, &res, "MHKG", "qd")) {
index 8c20e52..e085c25 100644 (file)
@@ -90,7 +90,8 @@ config PTP_1588_CLOCK_INES
 config PTP_1588_CLOCK_PCH
        tristate "Intel PCH EG20T as PTP clock"
        depends on X86_32 || COMPILE_TEST
-       depends on HAS_IOMEM && NET
+       depends on HAS_IOMEM && PCI
+       depends on NET
        imply PTP_1588_CLOCK
        help
          This driver adds support for using the PCH EG20T as a PTP
index b3d96b7..41b92dc 100644 (file)
@@ -154,7 +154,7 @@ static int unregister_vclock(struct device *dev, void *data)
        struct ptp_clock *ptp = dev_get_drvdata(dev);
        struct ptp_clock_info *info = ptp->info;
        struct ptp_vclock *vclock;
-       u8 *num = data;
+       u32 *num = data;
 
        vclock = info_to_vclock(info);
        dev_info(dev->parent, "delete virtual clock ptp%d\n",
index 2abf86c..d7cdd9c 100644 (file)
@@ -279,7 +279,7 @@ static void qeth_l2_set_pnso_mode(struct qeth_card *card,
 
 static void qeth_l2_dev2br_fdb_flush(struct qeth_card *card)
 {
-       struct switchdev_notifier_fdb_info info;
+       struct switchdev_notifier_fdb_info info = {};
 
        QETH_CARD_TEXT(card, 2, "fdbflush");
 
@@ -679,7 +679,7 @@ static void qeth_l2_dev2br_fdb_notify(struct qeth_card *card, u8 code,
                                      struct net_if_token *token,
                                      struct mac_addr_lnid *addr_lnid)
 {
-       struct switchdev_notifier_fdb_info info;
+       struct switchdev_notifier_fdb_info info = {};
        u8 ntfy_mac[ETH_ALEN];
 
        ether_addr_copy(ntfy_mac, addr_lnid->mac);
index 5983e05..e29523a 100644 (file)
@@ -13193,6 +13193,8 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
        if (!phba)
                return -ENOMEM;
 
+       INIT_LIST_HEAD(&phba->poll_list);
+
        /* Perform generic PCI device enabling operation */
        error = lpfc_enable_pci_dev(phba);
        if (error)
@@ -13327,7 +13329,6 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
        /* Enable RAS FW log support */
        lpfc_sli4_ras_setup(phba);
 
-       INIT_LIST_HEAD(&phba->poll_list);
        timer_setup(&phba->cpuhp_poll_timer, lpfc_sli4_poll_hbtimer, 0);
        cpuhp_state_add_instance_nocalls(lpfc_cpuhp_state, &phba->cpuhp);
 
index 19b1c0c..cf4a3a2 100644 (file)
@@ -7851,7 +7851,7 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc)
                        return r;
        }
 
-       rc = _base_static_config_pages(ioc);
+       r = _base_static_config_pages(ioc);
        if (r)
                return r;
 
index 328bb96..37506b3 100644 (file)
@@ -1199,14 +1199,24 @@ static void storvsc_on_io_completion(struct storvsc_device *stor_device,
                vstor_packet->vm_srb.sense_info_length);
 
        if (vstor_packet->vm_srb.scsi_status != 0 ||
-           vstor_packet->vm_srb.srb_status != SRB_STATUS_SUCCESS)
-               storvsc_log(device, STORVSC_LOGGING_ERROR,
+           vstor_packet->vm_srb.srb_status != SRB_STATUS_SUCCESS) {
+
+               /*
+                * Log TEST_UNIT_READY errors only as warnings. Hyper-V can
+                * return errors when detecting devices using TEST_UNIT_READY,
+                * and logging these as errors produces unhelpful noise.
+                */
+               int loglevel = (stor_pkt->vm_srb.cdb[0] == TEST_UNIT_READY) ?
+                       STORVSC_LOGGING_WARN : STORVSC_LOGGING_ERROR;
+
+               storvsc_log(device, loglevel,
                        "tag#%d cmd 0x%x status: scsi 0x%x srb 0x%x hv 0x%x\n",
                        request->cmd->request->tag,
                        stor_pkt->vm_srb.cdb[0],
                        vstor_packet->vm_srb.scsi_status,
                        vstor_packet->vm_srb.srb_status,
                        vstor_packet->status);
+       }
 
        if (vstor_packet->vm_srb.scsi_status == SAM_STAT_CHECK_CONDITION &&
            (vstor_packet->vm_srb.srb_status & SRB_STATUS_AUTOSENSE_VALID))
index f2b5d34..e5ae262 100644 (file)
@@ -66,7 +66,7 @@ int slim_alloc_txn_tid(struct slim_controller *ctrl, struct slim_msg_txn *txn)
        int ret = 0;
 
        spin_lock_irqsave(&ctrl->txn_lock, flags);
-       ret = idr_alloc_cyclic(&ctrl->tid_idr, txn, 0,
+       ret = idr_alloc_cyclic(&ctrl->tid_idr, txn, 1,
                                SLIM_MAX_TIDS, GFP_ATOMIC);
        if (ret < 0) {
                spin_unlock_irqrestore(&ctrl->txn_lock, flags);
@@ -131,7 +131,8 @@ int slim_do_transfer(struct slim_controller *ctrl, struct slim_msg_txn *txn)
                        goto slim_xfer_err;
                }
        }
-
+       /* Initialize tid to invalid value */
+       txn->tid = 0;
        need_tid = slim_tid_txn(txn->mt, txn->mc);
 
        if (need_tid) {
@@ -163,7 +164,7 @@ int slim_do_transfer(struct slim_controller *ctrl, struct slim_msg_txn *txn)
                        txn->mt, txn->mc, txn->la, ret);
 
 slim_xfer_err:
-       if (!clk_pause_msg && (!need_tid  || ret == -ETIMEDOUT)) {
+       if (!clk_pause_msg && (txn->tid == 0  || ret == -ETIMEDOUT)) {
                /*
                 * remove runtime-pm vote if this was TX only, or
                 * if there was error during this transaction
index c054e83..7040293 100644 (file)
@@ -618,7 +618,7 @@ static void qcom_slim_ngd_rx(struct qcom_slim_ngd_ctrl *ctrl, u8 *buf)
                (mc == SLIM_USR_MC_GENERIC_ACK &&
                 mt == SLIM_MSG_MT_SRC_REFERRED_USER)) {
                slim_msg_response(&ctrl->ctrl, &buf[4], buf[3], len - 4);
-               pm_runtime_mark_last_busy(ctrl->dev);
+               pm_runtime_mark_last_busy(ctrl->ctrl.dev);
        }
 }
 
@@ -1080,7 +1080,8 @@ static void qcom_slim_ngd_setup(struct qcom_slim_ngd_ctrl *ctrl)
 {
        u32 cfg = readl_relaxed(ctrl->ngd->base);
 
-       if (ctrl->state == QCOM_SLIM_NGD_CTRL_DOWN)
+       if (ctrl->state == QCOM_SLIM_NGD_CTRL_DOWN ||
+               ctrl->state == QCOM_SLIM_NGD_CTRL_ASLEEP)
                qcom_slim_ngd_init_dma(ctrl);
 
        /* By default enable message queues */
@@ -1131,6 +1132,7 @@ static int qcom_slim_ngd_power_up(struct qcom_slim_ngd_ctrl *ctrl)
                        dev_info(ctrl->dev, "Subsys restart: ADSP active framer\n");
                        return 0;
                }
+               qcom_slim_ngd_setup(ctrl);
                return 0;
        }
 
@@ -1257,13 +1259,14 @@ static int qcom_slim_ngd_enable(struct qcom_slim_ngd_ctrl *ctrl, bool enable)
                }
                /* controller state should be in sync with framework state */
                complete(&ctrl->qmi.qmi_comp);
-               if (!pm_runtime_enabled(ctrl->dev) ||
-                               !pm_runtime_suspended(ctrl->dev))
-                       qcom_slim_ngd_runtime_resume(ctrl->dev);
+               if (!pm_runtime_enabled(ctrl->ctrl.dev) ||
+                        !pm_runtime_suspended(ctrl->ctrl.dev))
+                       qcom_slim_ngd_runtime_resume(ctrl->ctrl.dev);
                else
-                       pm_runtime_resume(ctrl->dev);
-               pm_runtime_mark_last_busy(ctrl->dev);
-               pm_runtime_put(ctrl->dev);
+                       pm_runtime_resume(ctrl->ctrl.dev);
+
+               pm_runtime_mark_last_busy(ctrl->ctrl.dev);
+               pm_runtime_put(ctrl->ctrl.dev);
 
                ret = slim_register_controller(&ctrl->ctrl);
                if (ret) {
@@ -1389,7 +1392,7 @@ static int qcom_slim_ngd_ssr_pdr_notify(struct qcom_slim_ngd_ctrl *ctrl,
                /* Make sure the last dma xfer is finished */
                mutex_lock(&ctrl->tx_lock);
                if (ctrl->state != QCOM_SLIM_NGD_CTRL_DOWN) {
-                       pm_runtime_get_noresume(ctrl->dev);
+                       pm_runtime_get_noresume(ctrl->ctrl.dev);
                        ctrl->state = QCOM_SLIM_NGD_CTRL_DOWN;
                        qcom_slim_ngd_down(ctrl);
                        qcom_slim_ngd_exit_dma(ctrl);
@@ -1617,6 +1620,7 @@ static int __maybe_unused qcom_slim_ngd_runtime_suspend(struct device *dev)
        struct qcom_slim_ngd_ctrl *ctrl = dev_get_drvdata(dev);
        int ret = 0;
 
+       qcom_slim_ngd_exit_dma(ctrl);
        if (!ctrl->qmi.handle)
                return 0;
 
index 3f711c1..bbae3d3 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/signal.h>
 #include <linux/device.h>
 #include <linux/spinlock.h>
+#include <linux/platform_device.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <soc/fsl/qe/qe.h>
@@ -53,8 +54,8 @@ struct qe_ic {
        struct irq_chip hc_irq;
 
        /* VIRQ numbers of QE high/low irqs */
-       unsigned int virq_high;
-       unsigned int virq_low;
+       int virq_high;
+       int virq_low;
 };
 
 /*
@@ -404,42 +405,40 @@ static void qe_ic_cascade_muxed_mpic(struct irq_desc *desc)
        chip->irq_eoi(&desc->irq_data);
 }
 
-static void __init qe_ic_init(struct device_node *node)
+static int qe_ic_init(struct platform_device *pdev)
 {
+       struct device *dev = &pdev->dev;
        void (*low_handler)(struct irq_desc *desc);
        void (*high_handler)(struct irq_desc *desc);
        struct qe_ic *qe_ic;
-       struct resource res;
-       u32 ret;
+       struct resource *res;
+       struct device_node *node = pdev->dev.of_node;
 
-       ret = of_address_to_resource(node, 0, &res);
-       if (ret)
-               return;
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(dev, "no memory resource defined\n");
+               return -ENODEV;
+       }
 
-       qe_ic = kzalloc(sizeof(*qe_ic), GFP_KERNEL);
+       qe_ic = devm_kzalloc(dev, sizeof(*qe_ic), GFP_KERNEL);
        if (qe_ic == NULL)
-               return;
+               return -ENOMEM;
 
-       qe_ic->irqhost = irq_domain_add_linear(node, NR_QE_IC_INTS,
-                                              &qe_ic_host_ops, qe_ic);
-       if (qe_ic->irqhost == NULL) {
-               kfree(qe_ic);
-               return;
+       qe_ic->regs = devm_ioremap(dev, res->start, resource_size(res));
+       if (qe_ic->regs == NULL) {
+               dev_err(dev, "failed to ioremap() registers\n");
+               return -ENODEV;
        }
 
-       qe_ic->regs = ioremap(res.start, resource_size(&res));
-
        qe_ic->hc_irq = qe_ic_irq_chip;
 
-       qe_ic->virq_high = irq_of_parse_and_map(node, 0);
-       qe_ic->virq_low = irq_of_parse_and_map(node, 1);
+       qe_ic->virq_high = platform_get_irq(pdev, 0);
+       qe_ic->virq_low = platform_get_irq(pdev, 1);
 
-       if (!qe_ic->virq_low) {
-               printk(KERN_ERR "Failed to map QE_IC low IRQ\n");
-               kfree(qe_ic);
-               return;
-       }
-       if (qe_ic->virq_high != qe_ic->virq_low) {
+       if (qe_ic->virq_low <= 0)
+               return -ENODEV;
+
+       if (qe_ic->virq_high > 0 && qe_ic->virq_high != qe_ic->virq_low) {
                low_handler = qe_ic_cascade_low;
                high_handler = qe_ic_cascade_high;
        } else {
@@ -447,29 +446,42 @@ static void __init qe_ic_init(struct device_node *node)
                high_handler = NULL;
        }
 
+       qe_ic->irqhost = irq_domain_add_linear(node, NR_QE_IC_INTS,
+                                              &qe_ic_host_ops, qe_ic);
+       if (qe_ic->irqhost == NULL) {
+               dev_err(dev, "failed to add irq domain\n");
+               return -ENODEV;
+       }
+
        qe_ic_write(qe_ic->regs, QEIC_CICR, 0);
 
        irq_set_handler_data(qe_ic->virq_low, qe_ic);
        irq_set_chained_handler(qe_ic->virq_low, low_handler);
 
-       if (qe_ic->virq_high && qe_ic->virq_high != qe_ic->virq_low) {
+       if (high_handler) {
                irq_set_handler_data(qe_ic->virq_high, qe_ic);
                irq_set_chained_handler(qe_ic->virq_high, high_handler);
        }
+       return 0;
 }
+static const struct of_device_id qe_ic_ids[] = {
+       { .compatible = "fsl,qe-ic"},
+       { .type = "qeic"},
+       {},
+};
 
-static int __init qe_ic_of_init(void)
+static struct platform_driver qe_ic_driver =
 {
-       struct device_node *np;
+       .driver = {
+               .name           = "qe-ic",
+               .of_match_table = qe_ic_ids,
+       },
+       .probe  = qe_ic_init,
+};
 
-       np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
-       if (!np) {
-               np = of_find_node_by_type(NULL, "qeic");
-               if (!np)
-                       return -ENODEV;
-       }
-       qe_ic_init(np);
-       of_node_put(np);
+static int __init qe_ic_of_init(void)
+{
+       platform_driver_register(&qe_ic_driver);
        return 0;
 }
 subsys_initcall(qe_ic_of_init);
index b8d4b2d..84fe57e 100644 (file)
@@ -1741,13 +1741,9 @@ static void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep)
 {
        struct dwc3_request             *req;
        struct dwc3_request             *tmp;
-       struct list_head                local;
        struct dwc3                     *dwc = dep->dwc;
 
-restart:
-       list_replace_init(&dep->cancelled_list, &local);
-
-       list_for_each_entry_safe(req, tmp, &local, list) {
+       list_for_each_entry_safe(req, tmp, &dep->cancelled_list, list) {
                dwc3_gadget_ep_skip_trbs(dep, req);
                switch (req->status) {
                case DWC3_REQUEST_STATUS_DISCONNECTED:
@@ -1765,9 +1761,6 @@ restart:
                        break;
                }
        }
-
-       if (!list_empty(&dep->cancelled_list))
-               goto restart;
 }
 
 static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
@@ -2976,12 +2969,8 @@ static void dwc3_gadget_ep_cleanup_completed_requests(struct dwc3_ep *dep,
 {
        struct dwc3_request     *req;
        struct dwc3_request     *tmp;
-       struct list_head        local;
 
-restart:
-       list_replace_init(&dep->started_list, &local);
-
-       list_for_each_entry_safe(req, tmp, &local, list) {
+       list_for_each_entry_safe(req, tmp, &dep->started_list, list) {
                int ret;
 
                ret = dwc3_gadget_ep_cleanup_completed_request(dep, event,
@@ -2989,9 +2978,6 @@ restart:
                if (ret)
                        break;
        }
-
-       if (!list_empty(&dep->started_list))
-               goto restart;
 }
 
 static bool dwc3_gadget_ep_should_continue(struct dwc3_ep *dep)
index b9bb63d..f4079b5 100644 (file)
@@ -1737,6 +1737,10 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
        return rlen;
 }
 
+static void tcpm_pd_handle_msg(struct tcpm_port *port,
+                              enum pd_msg_request message,
+                              enum tcpm_ams ams);
+
 static void tcpm_handle_vdm_request(struct tcpm_port *port,
                                    const __le32 *payload, int cnt)
 {
@@ -1764,11 +1768,11 @@ static void tcpm_handle_vdm_request(struct tcpm_port *port,
                port->vdm_state = VDM_STATE_DONE;
        }
 
-       if (PD_VDO_SVDM(p[0])) {
+       if (PD_VDO_SVDM(p[0]) && (adev || tcpm_vdm_ams(port) || port->nr_snk_vdo)) {
                rlen = tcpm_pd_svdm(port, adev, p, cnt, response, &adev_action);
        } else {
                if (port->negotiated_rev >= PD_REV30)
-                       tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP);
+                       tcpm_pd_handle_msg(port, PD_MSG_CTRL_NOT_SUPP, NONE_AMS);
        }
 
        /*
@@ -2471,10 +2475,7 @@ static void tcpm_pd_data_request(struct tcpm_port *port,
                                           NONE_AMS);
                break;
        case PD_DATA_VENDOR_DEF:
-               if (tcpm_vdm_ams(port) || port->nr_snk_vdo)
-                       tcpm_handle_vdm_request(port, msg->payload, cnt);
-               else if (port->negotiated_rev > PD_REV20)
-                       tcpm_pd_handle_msg(port, PD_MSG_CTRL_NOT_SUPP, NONE_AMS);
+               tcpm_handle_vdm_request(port, msg->payload, cnt);
                break;
        case PD_DATA_BIST:
                port->bist_request = le32_to_cpu(msg->payload[0]);
index 21b78f1..351c6cf 100644 (file)
@@ -493,9 +493,9 @@ static int ifcvf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        adapter = vdpa_alloc_device(struct ifcvf_adapter, vdpa,
                                    dev, &ifc_vdpa_ops, NULL);
-       if (adapter == NULL) {
+       if (IS_ERR(adapter)) {
                IFCVF_ERR(pdev, "Failed to allocate vDPA structure");
-               return -ENOMEM;
+               return PTR_ERR(adapter);
        }
 
        pci_set_master(pdev);
index dcee603..e59135f 100644 (file)
@@ -512,11 +512,6 @@ out:
        mutex_unlock(&mr->mkey_mtx);
 }
 
-static bool map_empty(struct vhost_iotlb *iotlb)
-{
-       return !vhost_iotlb_itree_first(iotlb, 0, U64_MAX);
-}
-
 int mlx5_vdpa_handle_set_map(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb,
                             bool *change_map)
 {
@@ -524,10 +519,6 @@ int mlx5_vdpa_handle_set_map(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *io
        int err = 0;
 
        *change_map = false;
-       if (map_empty(iotlb)) {
-               mlx5_vdpa_destroy_mr(mvdev);
-               return 0;
-       }
        mutex_lock(&mr->mkey_mtx);
        if (mr->initialized) {
                mlx5_vdpa_info(mvdev, "memory map update\n");
index 2a31467..3cc12fc 100644 (file)
@@ -526,7 +526,6 @@ static int cq_create(struct mlx5_vdpa_net *ndev, u16 idx, u32 num_ent)
        void __iomem *uar_page = ndev->mvdev.res.uar->map;
        u32 out[MLX5_ST_SZ_DW(create_cq_out)];
        struct mlx5_vdpa_cq *vcq = &mvq->cq;
-       unsigned int irqn;
        __be64 *pas;
        int inlen;
        void *cqc;
@@ -566,7 +565,7 @@ static int cq_create(struct mlx5_vdpa_net *ndev, u16 idx, u32 num_ent)
        /* Use vector 0 by default. Consider adding code to choose least used
         * vector.
         */
-       err = mlx5_vector2eqn(mdev, 0, &eqn, &irqn);
+       err = mlx5_vector2eqn(mdev, 0, &eqn);
        if (err)
                goto err_vec;
 
@@ -753,12 +752,12 @@ static int get_queue_type(struct mlx5_vdpa_net *ndev)
        type_mask = MLX5_CAP_DEV_VDPA_EMULATION(ndev->mvdev.mdev, virtio_queue_type);
 
        /* prefer split queue */
-       if (type_mask & MLX5_VIRTIO_EMULATION_CAP_VIRTIO_QUEUE_TYPE_PACKED)
-               return MLX5_VIRTIO_EMULATION_VIRTIO_QUEUE_TYPE_PACKED;
+       if (type_mask & MLX5_VIRTIO_EMULATION_CAP_VIRTIO_QUEUE_TYPE_SPLIT)
+               return MLX5_VIRTIO_EMULATION_VIRTIO_QUEUE_TYPE_SPLIT;
 
-       WARN_ON(!(type_mask & MLX5_VIRTIO_EMULATION_CAP_VIRTIO_QUEUE_TYPE_SPLIT));
+       WARN_ON(!(type_mask & MLX5_VIRTIO_EMULATION_CAP_VIRTIO_QUEUE_TYPE_PACKED));
 
-       return MLX5_VIRTIO_EMULATION_VIRTIO_QUEUE_TYPE_SPLIT;
+       return MLX5_VIRTIO_EMULATION_VIRTIO_QUEUE_TYPE_PACKED;
 }
 
 static bool vq_is_tx(u16 idx)
@@ -2030,6 +2029,12 @@ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name)
                return -ENOSPC;
 
        mdev = mgtdev->madev->mdev;
+       if (!(MLX5_CAP_DEV_VDPA_EMULATION(mdev, virtio_queue_type) &
+           MLX5_VIRTIO_EMULATION_CAP_VIRTIO_QUEUE_TYPE_SPLIT)) {
+               dev_warn(mdev->device, "missing support for split virtqueues\n");
+               return -EOPNOTSUPP;
+       }
+
        /* we save one virtqueue for control virtqueue should we require it */
        max_vqs = MLX5_CAP_DEV_VDPA_EMULATION(mdev, max_num_virtio_queues);
        max_vqs = min_t(u32, max_vqs, MLX5_MAX_SUPPORTED_VQS);
index 14e024d..c621cf7 100644 (file)
@@ -251,8 +251,10 @@ struct vdpasim *vdpasim_create(struct vdpasim_dev_attr *dev_attr)
 
        vdpasim = vdpa_alloc_device(struct vdpasim, vdpa, NULL, ops,
                                    dev_attr->name);
-       if (!vdpasim)
+       if (IS_ERR(vdpasim)) {
+               ret = PTR_ERR(vdpasim);
                goto err_alloc;
+       }
 
        vdpasim->dev_attr = *dev_attr;
        INIT_WORK(&vdpasim->work, dev_attr->work_fn);
index 7b4a639..fe05273 100644 (file)
@@ -436,9 +436,9 @@ static int vp_vdpa_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        vp_vdpa = vdpa_alloc_device(struct vp_vdpa, vdpa,
                                    dev, &vp_vdpa_ops, NULL);
-       if (vp_vdpa == NULL) {
+       if (IS_ERR(vp_vdpa)) {
                dev_err(dev, "vp_vdpa: Failed to allocate vDPA structure\n");
-               return -ENOMEM;
+               return PTR_ERR(vp_vdpa);
        }
 
        mdev = &vp_vdpa->mdev;
index 210ab35..9479f7f 100644 (file)
@@ -614,7 +614,8 @@ static int vhost_vdpa_process_iotlb_update(struct vhost_vdpa *v,
        long pinned;
        int ret = 0;
 
-       if (msg->iova < v->range.first ||
+       if (msg->iova < v->range.first || !msg->size ||
+           msg->iova > U64_MAX - msg->size + 1 ||
            msg->iova + msg->size - 1 > v->range.last)
                return -EINVAL;
 
index b9e853e..59edb5a 100644 (file)
@@ -735,10 +735,16 @@ static bool log_access_ok(void __user *log_base, u64 addr, unsigned long sz)
                         (sz + VHOST_PAGE_SIZE * 8 - 1) / VHOST_PAGE_SIZE / 8);
 }
 
+/* Make sure 64 bit math will not overflow. */
 static bool vhost_overflow(u64 uaddr, u64 size)
 {
-       /* Make sure 64 bit math will not overflow. */
-       return uaddr > ULONG_MAX || size > ULONG_MAX || uaddr > ULONG_MAX - size;
+       if (uaddr > ULONG_MAX || size > ULONG_MAX)
+               return true;
+
+       if (!size)
+               return false;
+
+       return uaddr > ULONG_MAX - size + 1;
 }
 
 /* Caller should have vq mutex and device mutex. */
index 4af8fa2..14e2043 100644 (file)
@@ -359,7 +359,7 @@ __vringh_iov(struct vringh *vrh, u16 i,
                        iov = wiov;
                else {
                        iov = riov;
-                       if (unlikely(wiov && wiov->i)) {
+                       if (unlikely(wiov && wiov->used)) {
                                vringh_bad("Readable desc %p after writable",
                                           &descs[i]);
                                err = -EINVAL;
index 4b15c00..49984d2 100644 (file)
@@ -355,6 +355,7 @@ int register_virtio_device(struct virtio_device *dev)
        virtio_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
 
        INIT_LIST_HEAD(&dev->vqs);
+       spin_lock_init(&dev->vqs_list_lock);
 
        /*
         * device_add() causes the bus infrastructure to look for a matching
index 222d630..b35bb2d 100644 (file)
@@ -576,6 +576,13 @@ static void virtio_pci_remove(struct pci_dev *pci_dev)
        struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
        struct device *dev = get_device(&vp_dev->vdev.dev);
 
+       /*
+        * Device is marked broken on surprise removal so that virtio upper
+        * layers can abort any ongoing operation.
+        */
+       if (!pci_device_is_present(pci_dev))
+               virtio_break_device(&vp_dev->vdev);
+
        pci_disable_sriov(pci_dev);
 
        unregister_virtio_device(&vp_dev->vdev);
index 89bfe46..dd95dfd 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/hrtimer.h>
 #include <linux/dma-mapping.h>
+#include <linux/spinlock.h>
 #include <xen/xen.h>
 
 #ifdef DEBUG
@@ -1755,7 +1756,9 @@ static struct virtqueue *vring_create_virtqueue_packed(
                        cpu_to_le16(vq->packed.event_flags_shadow);
        }
 
+       spin_lock(&vdev->vqs_list_lock);
        list_add_tail(&vq->vq.list, &vdev->vqs);
+       spin_unlock(&vdev->vqs_list_lock);
        return &vq->vq;
 
 err_desc_extra:
@@ -2229,7 +2232,9 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
        memset(vq->split.desc_state, 0, vring.num *
                        sizeof(struct vring_desc_state_split));
 
+       spin_lock(&vdev->vqs_list_lock);
        list_add_tail(&vq->vq.list, &vdev->vqs);
+       spin_unlock(&vdev->vqs_list_lock);
        return &vq->vq;
 
 err_extra:
@@ -2291,6 +2296,10 @@ void vring_del_virtqueue(struct virtqueue *_vq)
 {
        struct vring_virtqueue *vq = to_vvq(_vq);
 
+       spin_lock(&vq->vq.vdev->vqs_list_lock);
+       list_del(&_vq->list);
+       spin_unlock(&vq->vq.vdev->vqs_list_lock);
+
        if (vq->we_own_ring) {
                if (vq->packed_ring) {
                        vring_free_queue(vq->vq.vdev,
@@ -2321,7 +2330,6 @@ void vring_del_virtqueue(struct virtqueue *_vq)
                kfree(vq->split.desc_state);
                kfree(vq->split.desc_extra);
        }
-       list_del(&_vq->list);
        kfree(vq);
 }
 EXPORT_SYMBOL_GPL(vring_del_virtqueue);
@@ -2373,7 +2381,7 @@ bool virtqueue_is_broken(struct virtqueue *_vq)
 {
        struct vring_virtqueue *vq = to_vvq(_vq);
 
-       return vq->broken;
+       return READ_ONCE(vq->broken);
 }
 EXPORT_SYMBOL_GPL(virtqueue_is_broken);
 
@@ -2385,10 +2393,14 @@ void virtio_break_device(struct virtio_device *dev)
 {
        struct virtqueue *_vq;
 
+       spin_lock(&dev->vqs_list_lock);
        list_for_each_entry(_vq, &dev->vqs, list) {
                struct vring_virtqueue *vq = to_vvq(_vq);
-               vq->broken = true;
+
+               /* Pairs with READ_ONCE() in virtqueue_is_broken(). */
+               WRITE_ONCE(vq->broken, true);
        }
+       spin_unlock(&dev->vqs_list_lock);
 }
 EXPORT_SYMBOL_GPL(virtio_break_device);
 
index e1a1411..72eaef2 100644 (file)
@@ -151,6 +151,9 @@ virtio_vdpa_setup_vq(struct virtio_device *vdev, unsigned int index,
        if (!name)
                return NULL;
 
+       if (index >= vdpa->nvqs)
+               return ERR_PTR(-ENOENT);
+
        /* Queue shouldn't already be set up. */
        if (ops->get_vq_ready(vdpa, index))
                return ERR_PTR(-ENOENT);
index d7e361f..a78704a 100644 (file)
@@ -198,12 +198,12 @@ static void disable_dynirq(struct irq_data *data);
 
 static DEFINE_PER_CPU(unsigned int, irq_epoch);
 
-static void clear_evtchn_to_irq_row(unsigned row)
+static void clear_evtchn_to_irq_row(int *evtchn_row)
 {
        unsigned col;
 
        for (col = 0; col < EVTCHN_PER_ROW; col++)
-               WRITE_ONCE(evtchn_to_irq[row][col], -1);
+               WRITE_ONCE(evtchn_row[col], -1);
 }
 
 static void clear_evtchn_to_irq_all(void)
@@ -213,7 +213,7 @@ static void clear_evtchn_to_irq_all(void)
        for (row = 0; row < EVTCHN_ROW(xen_evtchn_max_channels()); row++) {
                if (evtchn_to_irq[row] == NULL)
                        continue;
-               clear_evtchn_to_irq_row(row);
+               clear_evtchn_to_irq_row(evtchn_to_irq[row]);
        }
 }
 
@@ -221,6 +221,7 @@ static int set_evtchn_to_irq(evtchn_port_t evtchn, unsigned int irq)
 {
        unsigned row;
        unsigned col;
+       int *evtchn_row;
 
        if (evtchn >= xen_evtchn_max_channels())
                return -EINVAL;
@@ -233,11 +234,18 @@ static int set_evtchn_to_irq(evtchn_port_t evtchn, unsigned int irq)
                if (irq == -1)
                        return 0;
 
-               evtchn_to_irq[row] = (int *)get_zeroed_page(GFP_KERNEL);
-               if (evtchn_to_irq[row] == NULL)
+               evtchn_row = (int *) __get_free_pages(GFP_KERNEL, 0);
+               if (evtchn_row == NULL)
                        return -ENOMEM;
 
-               clear_evtchn_to_irq_row(row);
+               clear_evtchn_to_irq_row(evtchn_row);
+
+               /*
+                * We've prepared an empty row for the mapping. If a different
+                * thread was faster inserting it, we can drop ours.
+                */
+               if (cmpxchg(&evtchn_to_irq[row], NULL, evtchn_row) != NULL)
+                       free_page((unsigned long) evtchn_row);
        }
 
        WRITE_ONCE(evtchn_to_irq[row][col], irq);
@@ -1009,7 +1017,7 @@ static void __unbind_from_irq(unsigned int irq)
 int xen_bind_pirq_gsi_to_irq(unsigned gsi,
                             unsigned pirq, int shareable, char *name)
 {
-       int irq = -1;
+       int irq;
        struct physdev_irq irq_op;
        int ret;
 
index 0117d86..06f9f16 100644 (file)
@@ -9226,8 +9226,14 @@ static int btrfs_rename_exchange(struct inode *old_dir,
        bool dest_log_pinned = false;
        bool need_abort = false;
 
-       /* we only allow rename subvolume link between subvolumes */
-       if (old_ino != BTRFS_FIRST_FREE_OBJECTID && root != dest)
+       /*
+        * For non-subvolumes allow exchange only within one subvolume, in the
+        * same inode namespace. Two subvolumes (represented as directory) can
+        * be exchanged as they're a logical link and have a fixed inode number.
+        */
+       if (root != dest &&
+           (old_ino != BTRFS_FIRST_FREE_OBJECTID ||
+            new_ino != BTRFS_FIRST_FREE_OBJECTID))
                return -EXDEV;
 
        /* close the race window with snapshot create/destroy ioctl */
index 7bdefd0..2a29009 100644 (file)
@@ -4150,11 +4150,19 @@ bad:
 
 /*
  * Delayed work handler to process end of delayed cap release LRU list.
+ *
+ * If new caps are added to the list while processing it, these won't get
+ * processed in this run.  In this case, the ci->i_hold_caps_max will be
+ * returned so that the work can be scheduled accordingly.
  */
-void ceph_check_delayed_caps(struct ceph_mds_client *mdsc)
+unsigned long ceph_check_delayed_caps(struct ceph_mds_client *mdsc)
 {
        struct inode *inode;
        struct ceph_inode_info *ci;
+       struct ceph_mount_options *opt = mdsc->fsc->mount_options;
+       unsigned long delay_max = opt->caps_wanted_delay_max * HZ;
+       unsigned long loop_start = jiffies;
+       unsigned long delay = 0;
 
        dout("check_delayed_caps\n");
        spin_lock(&mdsc->cap_delay_lock);
@@ -4162,6 +4170,11 @@ void ceph_check_delayed_caps(struct ceph_mds_client *mdsc)
                ci = list_first_entry(&mdsc->cap_delay_list,
                                      struct ceph_inode_info,
                                      i_cap_delay_list);
+               if (time_before(loop_start, ci->i_hold_caps_max - delay_max)) {
+                       dout("%s caps added recently.  Exiting loop", __func__);
+                       delay = ci->i_hold_caps_max;
+                       break;
+               }
                if ((ci->i_ceph_flags & CEPH_I_FLUSH) == 0 &&
                    time_before(jiffies, ci->i_hold_caps_max))
                        break;
@@ -4177,6 +4190,8 @@ void ceph_check_delayed_caps(struct ceph_mds_client *mdsc)
                }
        }
        spin_unlock(&mdsc->cap_delay_lock);
+
+       return delay;
 }
 
 /*
index 9db1b39..afdc202 100644 (file)
@@ -4490,22 +4490,29 @@ void inc_session_sequence(struct ceph_mds_session *s)
 }
 
 /*
- * delayed work -- periodically trim expired leases, renew caps with mds
+ * delayed work -- periodically trim expired leases, renew caps with mds.  If
+ * the @delay parameter is set to 0 or if it's more than 5 secs, the default
+ * workqueue delay value of 5 secs will be used.
  */
-static void schedule_delayed(struct ceph_mds_client *mdsc)
+static void schedule_delayed(struct ceph_mds_client *mdsc, unsigned long delay)
 {
-       int delay = 5;
-       unsigned hz = round_jiffies_relative(HZ * delay);
-       schedule_delayed_work(&mdsc->delayed_work, hz);
+       unsigned long max_delay = HZ * 5;
+
+       /* 5 secs default delay */
+       if (!delay || (delay > max_delay))
+               delay = max_delay;
+       schedule_delayed_work(&mdsc->delayed_work,
+                             round_jiffies_relative(delay));
 }
 
 static void delayed_work(struct work_struct *work)
 {
-       int i;
        struct ceph_mds_client *mdsc =
                container_of(work, struct ceph_mds_client, delayed_work.work);
+       unsigned long delay;
        int renew_interval;
        int renew_caps;
+       int i;
 
        dout("mdsc delayed_work\n");
 
@@ -4545,7 +4552,7 @@ static void delayed_work(struct work_struct *work)
        }
        mutex_unlock(&mdsc->mutex);
 
-       ceph_check_delayed_caps(mdsc);
+       delay = ceph_check_delayed_caps(mdsc);
 
        ceph_queue_cap_reclaim_work(mdsc);
 
@@ -4553,7 +4560,7 @@ static void delayed_work(struct work_struct *work)
 
        maybe_recover_session(mdsc);
 
-       schedule_delayed(mdsc);
+       schedule_delayed(mdsc, delay);
 }
 
 int ceph_mdsc_init(struct ceph_fs_client *fsc)
@@ -5030,7 +5037,7 @@ void ceph_mdsc_handle_mdsmap(struct ceph_mds_client *mdsc, struct ceph_msg *msg)
                          mdsc->mdsmap->m_epoch);
 
        mutex_unlock(&mdsc->mutex);
-       schedule_delayed(mdsc);
+       schedule_delayed(mdsc, 0);
        return;
 
 bad_unlock:
index 4ac0606..4c6bd10 100644 (file)
@@ -67,19 +67,19 @@ void ceph_get_snap_realm(struct ceph_mds_client *mdsc,
 {
        lockdep_assert_held(&mdsc->snap_rwsem);
 
-       dout("get_realm %p %d -> %d\n", realm,
-            atomic_read(&realm->nref), atomic_read(&realm->nref)+1);
        /*
-        * since we _only_ increment realm refs or empty the empty
-        * list with snap_rwsem held, adjusting the empty list here is
-        * safe.  we do need to protect against concurrent empty list
-        * additions, however.
+        * The 0->1 and 1->0 transitions must take the snap_empty_lock
+        * atomically with the refcount change. Go ahead and bump the
+        * nref here, unless it's 0, in which case we take the spinlock
+        * and then do the increment and remove it from the list.
         */
-       if (atomic_inc_return(&realm->nref) == 1) {
-               spin_lock(&mdsc->snap_empty_lock);
+       if (atomic_inc_not_zero(&realm->nref))
+               return;
+
+       spin_lock(&mdsc->snap_empty_lock);
+       if (atomic_inc_return(&realm->nref) == 1)
                list_del_init(&realm->empty_item);
-               spin_unlock(&mdsc->snap_empty_lock);
-       }
+       spin_unlock(&mdsc->snap_empty_lock);
 }
 
 static void __insert_snap_realm(struct rb_root *root,
@@ -208,28 +208,28 @@ static void __put_snap_realm(struct ceph_mds_client *mdsc,
 {
        lockdep_assert_held_write(&mdsc->snap_rwsem);
 
-       dout("__put_snap_realm %llx %p %d -> %d\n", realm->ino, realm,
-            atomic_read(&realm->nref), atomic_read(&realm->nref)-1);
+       /*
+        * We do not require the snap_empty_lock here, as any caller that
+        * increments the value must hold the snap_rwsem.
+        */
        if (atomic_dec_and_test(&realm->nref))
                __destroy_snap_realm(mdsc, realm);
 }
 
 /*
- * caller needn't hold any locks
+ * See comments in ceph_get_snap_realm. Caller needn't hold any locks.
  */
 void ceph_put_snap_realm(struct ceph_mds_client *mdsc,
                         struct ceph_snap_realm *realm)
 {
-       dout("put_snap_realm %llx %p %d -> %d\n", realm->ino, realm,
-            atomic_read(&realm->nref), atomic_read(&realm->nref)-1);
-       if (!atomic_dec_and_test(&realm->nref))
+       if (!atomic_dec_and_lock(&realm->nref, &mdsc->snap_empty_lock))
                return;
 
        if (down_write_trylock(&mdsc->snap_rwsem)) {
+               spin_unlock(&mdsc->snap_empty_lock);
                __destroy_snap_realm(mdsc, realm);
                up_write(&mdsc->snap_rwsem);
        } else {
-               spin_lock(&mdsc->snap_empty_lock);
                list_add(&realm->empty_item, &mdsc->snap_empty);
                spin_unlock(&mdsc->snap_empty_lock);
        }
index 6b6332a..9215a2f 100644 (file)
@@ -1167,7 +1167,7 @@ extern void ceph_flush_snaps(struct ceph_inode_info *ci,
 extern bool __ceph_should_report_size(struct ceph_inode_info *ci);
 extern void ceph_check_caps(struct ceph_inode_info *ci, int flags,
                            struct ceph_mds_session *session);
-extern void ceph_check_delayed_caps(struct ceph_mds_client *mdsc);
+extern unsigned long ceph_check_delayed_caps(struct ceph_mds_client *mdsc);
 extern void ceph_flush_dirty_caps(struct ceph_mds_client *mdsc);
 extern int  ceph_drop_caps_for_unlink(struct inode *inode);
 extern int ceph_encode_inode_release(void **p, struct inode *inode,
index c0bfc2f..c6a9542 100644 (file)
@@ -1611,6 +1611,11 @@ struct dfs_info3_param {
        int ttl;
 };
 
+struct file_list {
+       struct list_head list;
+       struct cifsFileInfo *cfile;
+};
+
 /*
  * common struct for holding inode info when searching for or updating an
  * inode with new info
index 79402ca..5f8a302 100644 (file)
@@ -100,7 +100,7 @@ build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
                pplen = cifs_sb->prepath ? strlen(cifs_sb->prepath) + 1 : 0;
 
-       s = dentry_path_raw(direntry, page, PAGE_SIZE);
+       s = dentry_path_raw(direntry, page, PATH_MAX);
        if (IS_ERR(s))
                return s;
        if (!s[1])      // for root we want "", not "/"
index 0a72840..bb98fbd 100644 (file)
@@ -4847,17 +4847,6 @@ void cifs_oplock_break(struct work_struct *work)
                cifs_dbg(VFS, "Push locks rc = %d\n", rc);
 
 oplock_break_ack:
-       /*
-        * releasing stale oplock after recent reconnect of smb session using
-        * a now incorrect file handle is not a data integrity issue but do
-        * not bother sending an oplock release if session to server still is
-        * disconnected since oplock already released by the server
-        */
-       if (!cfile->oplock_break_cancelled) {
-               rc = tcon->ses->server->ops->oplock_response(tcon, &cfile->fid,
-                                                            cinode);
-               cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
-       }
        /*
         * When oplock break is received and there are no active
         * file handles but cached, then schedule deferred close immediately.
@@ -4865,17 +4854,27 @@ oplock_break_ack:
         */
        spin_lock(&CIFS_I(inode)->deferred_lock);
        is_deferred = cifs_is_deferred_close(cfile, &dclose);
+       spin_unlock(&CIFS_I(inode)->deferred_lock);
        if (is_deferred &&
            cfile->deferred_close_scheduled &&
            delayed_work_pending(&cfile->deferred)) {
-               /*
-                * If there is no pending work, mod_delayed_work queues new work.
-                * So, Increase the ref count to avoid use-after-free.
-                */
-               if (!mod_delayed_work(deferredclose_wq, &cfile->deferred, 0))
-                       cifsFileInfo_get(cfile);
+               if (cancel_delayed_work(&cfile->deferred)) {
+                       _cifsFileInfo_put(cfile, false, false);
+                       goto oplock_break_done;
+               }
        }
-       spin_unlock(&CIFS_I(inode)->deferred_lock);
+       /*
+        * releasing stale oplock after recent reconnect of smb session using
+        * a now incorrect file handle is not a data integrity issue but do
+        * not bother sending an oplock release if session to server still is
+        * disconnected since oplock already released by the server
+        */
+       if (!cfile->oplock_break_cancelled) {
+               rc = tcon->ses->server->ops->oplock_response(tcon, &cfile->fid,
+                                                            cinode);
+               cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
+       }
+oplock_break_done:
        _cifsFileInfo_put(cfile, false /* do not wait for ourself */, false);
        cifs_done_oplock_break(cinode);
 }
index b96b253..65f8a70 100644 (file)
@@ -1625,7 +1625,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
                goto unlink_out;
        }
 
-       cifs_close_all_deferred_files(tcon);
+       cifs_close_deferred_file(CIFS_I(inode));
        if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
                                le64_to_cpu(tcon->fsUnixInfo.Capability))) {
                rc = CIFSPOSIXDelFile(xid, tcon, full_path,
@@ -2084,6 +2084,7 @@ cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir,
        FILE_UNIX_BASIC_INFO *info_buf_target;
        unsigned int xid;
        int rc, tmprc;
+       int retry_count = 0;
 
        if (flags & ~RENAME_NOREPLACE)
                return -EINVAL;
@@ -2113,10 +2114,24 @@ cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir,
                goto cifs_rename_exit;
        }
 
-       cifs_close_all_deferred_files(tcon);
+       cifs_close_deferred_file(CIFS_I(d_inode(source_dentry)));
+       if (d_inode(target_dentry) != NULL)
+               cifs_close_deferred_file(CIFS_I(d_inode(target_dentry)));
+
        rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
                            to_name);
 
+       if (rc == -EACCES) {
+               while (retry_count < 3) {
+                       cifs_close_all_deferred_files(tcon);
+                       rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
+                                           to_name);
+                       if (rc != -EACCES)
+                               break;
+                       retry_count++;
+               }
+       }
+
        /*
         * No-replace is the natural behavior for CIFS, so skip unlink hacks.
         */
index 844abeb..9469f1c 100644 (file)
@@ -723,13 +723,31 @@ void
 cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode)
 {
        struct cifsFileInfo *cfile = NULL;
-       struct cifs_deferred_close *dclose;
+       struct file_list *tmp_list, *tmp_next_list;
+       struct list_head file_head;
+
+       if (cifs_inode == NULL)
+               return;
 
+       INIT_LIST_HEAD(&file_head);
+       spin_lock(&cifs_inode->open_file_lock);
        list_for_each_entry(cfile, &cifs_inode->openFileList, flist) {
-               spin_lock(&cifs_inode->deferred_lock);
-               if (cifs_is_deferred_close(cfile, &dclose))
-                       mod_delayed_work(deferredclose_wq, &cfile->deferred, 0);
-               spin_unlock(&cifs_inode->deferred_lock);
+               if (delayed_work_pending(&cfile->deferred)) {
+                       if (cancel_delayed_work(&cfile->deferred)) {
+                               tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
+                               if (tmp_list == NULL)
+                                       continue;
+                               tmp_list->cfile = cfile;
+                               list_add_tail(&tmp_list->list, &file_head);
+                       }
+               }
+       }
+       spin_unlock(&cifs_inode->open_file_lock);
+
+       list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) {
+               _cifsFileInfo_put(tmp_list->cfile, true, false);
+               list_del(&tmp_list->list);
+               kfree(tmp_list);
        }
 }
 
@@ -738,20 +756,30 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon)
 {
        struct cifsFileInfo *cfile;
        struct list_head *tmp;
+       struct file_list *tmp_list, *tmp_next_list;
+       struct list_head file_head;
 
+       INIT_LIST_HEAD(&file_head);
        spin_lock(&tcon->open_file_lock);
        list_for_each(tmp, &tcon->openFileList) {
                cfile = list_entry(tmp, struct cifsFileInfo, tlist);
                if (delayed_work_pending(&cfile->deferred)) {
-                       /*
-                        * If there is no pending work, mod_delayed_work queues new work.
-                        * So, Increase the ref count to avoid use-after-free.
-                        */
-                       if (!mod_delayed_work(deferredclose_wq, &cfile->deferred, 0))
-                               cifsFileInfo_get(cfile);
+                       if (cancel_delayed_work(&cfile->deferred)) {
+                               tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
+                               if (tmp_list == NULL)
+                                       continue;
+                               tmp_list->cfile = cfile;
+                               list_add_tail(&tmp_list->list, &file_head);
+                       }
                }
        }
        spin_unlock(&tcon->open_file_lock);
+
+       list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) {
+               _cifsFileInfo_put(tmp_list->cfile, true, false);
+               list_del(&tmp_list->list);
+               kfree(tmp_list);
+       }
 }
 
 /* parses DFS refferal V3 structure
index 781d14e..b6d2e35 100644 (file)
@@ -2426,7 +2426,7 @@ create_sd_buf(umode_t mode, bool set_owner, unsigned int *len)
        memcpy(aclptr, &acl, sizeof(struct cifs_acl));
 
        buf->ccontext.DataLength = cpu_to_le32(ptr - (__u8 *)&buf->sd);
-       *len = ptr - (__u8 *)buf;
+       *len = roundup(ptr - (__u8 *)buf, 8);
 
        return buf;
 }
index 5a0be99..0ad3215 100644 (file)
@@ -177,28 +177,22 @@ out:
        return retval;
 }
 
-/* Fill [buffer, buffer + pos) with data coming from @from. */
-static int fill_write_buffer(struct configfs_buffer *buffer, loff_t pos,
+/* Fill @buffer with data coming from @from. */
+static int fill_write_buffer(struct configfs_buffer *buffer,
                             struct iov_iter *from)
 {
-       loff_t to_copy;
        int copied;
-       u8 *to;
 
        if (!buffer->page)
                buffer->page = (char *)__get_free_pages(GFP_KERNEL, 0);
        if (!buffer->page)
                return -ENOMEM;
 
-       to_copy = SIMPLE_ATTR_SIZE - 1 - pos;
-       if (to_copy <= 0)
-               return 0;
-       to = buffer->page + pos;
-       copied = copy_from_iter(to, to_copy, from);
+       copied = copy_from_iter(buffer->page, SIMPLE_ATTR_SIZE - 1, from);
        buffer->needs_read_fill = 1;
        /* if buf is assumed to contain a string, terminate it by \0,
         * so e.g. sscanf() can scan the string easily */
-       to[copied] = 0;
+       buffer->page[copied] = 0;
        return copied ? : -EFAULT;
 }
 
@@ -227,10 +221,10 @@ static ssize_t configfs_write_iter(struct kiocb *iocb, struct iov_iter *from)
 {
        struct file *file = iocb->ki_filp;
        struct configfs_buffer *buffer = file->private_data;
-       ssize_t len;
+       int len;
 
        mutex_lock(&buffer->mutex);
-       len = fill_write_buffer(buffer, iocb->ki_pos, from);
+       len = fill_write_buffer(buffer, from);
        if (len > 0)
                len = flush_write_buffer(file, buffer, len);
        if (len > 0)
index da41f93..99b4e78 100644 (file)
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -722,7 +722,7 @@ static int copy_cow_page_dax(struct block_device *bdev, struct dax_device *dax_d
                return rc;
 
        id = dax_read_lock();
-       rc = dax_direct_access(dax_dev, pgoff, PHYS_PFN(PAGE_SIZE), &kaddr, NULL);
+       rc = dax_direct_access(dax_dev, pgoff, 1, &kaddr, NULL);
        if (rc < 0) {
                dax_read_unlock(id);
                return rc;
index e557237..9d58371 100644 (file)
@@ -1235,8 +1235,6 @@ void fuse_dax_conn_free(struct fuse_conn *fc)
 static int fuse_dax_mem_range_init(struct fuse_conn_dax *fcd)
 {
        long nr_pages, nr_ranges;
-       void *kaddr;
-       pfn_t pfn;
        struct fuse_dax_mapping *range;
        int ret, id;
        size_t dax_size = -1;
@@ -1248,8 +1246,8 @@ static int fuse_dax_mem_range_init(struct fuse_conn_dax *fcd)
        INIT_DELAYED_WORK(&fcd->free_work, fuse_dax_free_mem_worker);
 
        id = dax_read_lock();
-       nr_pages = dax_direct_access(fcd->dev, 0, PHYS_PFN(dax_size), &kaddr,
-                                    &pfn);
+       nr_pages = dax_direct_access(fcd->dev, 0, PHYS_PFN(dax_size), NULL,
+                                    NULL);
        dax_read_unlock(id);
        if (nr_pages < 0) {
                pr_debug("dax_direct_access() returned %ld\n", nr_pages);
index 12fc193..7d2ed8c 100644 (file)
@@ -129,7 +129,7 @@ struct io_cb_cancel_data {
        bool cancel_all;
 };
 
-static void create_io_worker(struct io_wq *wq, struct io_wqe *wqe, int index);
+static void create_io_worker(struct io_wq *wq, struct io_wqe *wqe, int index, bool first);
 static void io_wqe_dec_running(struct io_worker *worker);
 
 static bool io_worker_get(struct io_worker *worker)
@@ -248,18 +248,20 @@ static void io_wqe_wake_worker(struct io_wqe *wqe, struct io_wqe_acct *acct)
        rcu_read_unlock();
 
        if (!ret) {
-               bool do_create = false;
+               bool do_create = false, first = false;
 
                raw_spin_lock_irq(&wqe->lock);
                if (acct->nr_workers < acct->max_workers) {
                        atomic_inc(&acct->nr_running);
                        atomic_inc(&wqe->wq->worker_refs);
+                       if (!acct->nr_workers)
+                               first = true;
                        acct->nr_workers++;
                        do_create = true;
                }
                raw_spin_unlock_irq(&wqe->lock);
                if (do_create)
-                       create_io_worker(wqe->wq, wqe, acct->index);
+                       create_io_worker(wqe->wq, wqe, acct->index, first);
        }
 }
 
@@ -282,16 +284,26 @@ static void create_worker_cb(struct callback_head *cb)
        struct io_wq *wq;
        struct io_wqe *wqe;
        struct io_wqe_acct *acct;
+       bool do_create = false, first = false;
 
        cwd = container_of(cb, struct create_worker_data, work);
        wqe = cwd->wqe;
        wq = wqe->wq;
        acct = &wqe->acct[cwd->index];
        raw_spin_lock_irq(&wqe->lock);
-       if (acct->nr_workers < acct->max_workers)
+       if (acct->nr_workers < acct->max_workers) {
+               if (!acct->nr_workers)
+                       first = true;
                acct->nr_workers++;
+               do_create = true;
+       }
        raw_spin_unlock_irq(&wqe->lock);
-       create_io_worker(wq, cwd->wqe, cwd->index);
+       if (do_create) {
+               create_io_worker(wq, wqe, cwd->index, first);
+       } else {
+               atomic_dec(&acct->nr_running);
+               io_worker_ref_put(wq);
+       }
        kfree(cwd);
 }
 
@@ -629,7 +641,7 @@ void io_wq_worker_sleeping(struct task_struct *tsk)
        raw_spin_unlock_irq(&worker->wqe->lock);
 }
 
-static void create_io_worker(struct io_wq *wq, struct io_wqe *wqe, int index)
+static void create_io_worker(struct io_wq *wq, struct io_wqe *wqe, int index, bool first)
 {
        struct io_wqe_acct *acct = &wqe->acct[index];
        struct io_worker *worker;
@@ -670,7 +682,7 @@ fail:
        worker->flags |= IO_WORKER_F_FREE;
        if (index == IO_WQ_ACCT_BOUND)
                worker->flags |= IO_WORKER_F_BOUND;
-       if ((acct->nr_workers == 1) && (worker->flags & IO_WORKER_F_BOUND))
+       if (first && (worker->flags & IO_WORKER_F_BOUND))
                worker->flags |= IO_WORKER_F_FIXED;
        raw_spin_unlock_irq(&wqe->lock);
        wake_up_new_task(tsk);
index bf548af..a2e20a6 100644 (file)
@@ -78,6 +78,7 @@
 #include <linux/task_work.h>
 #include <linux/pagemap.h>
 #include <linux/io_uring.h>
+#include <linux/tracehook.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/io_uring.h>
@@ -1499,7 +1500,8 @@ static bool __io_cqring_overflow_flush(struct io_ring_ctx *ctx, bool force)
        all_flushed = list_empty(&ctx->cq_overflow_list);
        if (all_flushed) {
                clear_bit(0, &ctx->check_cq_overflow);
-               ctx->rings->sq_flags &= ~IORING_SQ_CQ_OVERFLOW;
+               WRITE_ONCE(ctx->rings->sq_flags,
+                          ctx->rings->sq_flags & ~IORING_SQ_CQ_OVERFLOW);
        }
 
        if (posted)
@@ -1578,7 +1580,9 @@ static bool io_cqring_event_overflow(struct io_ring_ctx *ctx, u64 user_data,
        }
        if (list_empty(&ctx->cq_overflow_list)) {
                set_bit(0, &ctx->check_cq_overflow);
-               ctx->rings->sq_flags |= IORING_SQ_CQ_OVERFLOW;
+               WRITE_ONCE(ctx->rings->sq_flags,
+                          ctx->rings->sq_flags | IORING_SQ_CQ_OVERFLOW);
+
        }
        ocqe->cqe.user_data = user_data;
        ocqe->cqe.res = res;
@@ -2222,9 +2226,9 @@ static inline unsigned int io_put_rw_kbuf(struct io_kiocb *req)
 
 static inline bool io_run_task_work(void)
 {
-       if (current->task_works) {
+       if (test_thread_flag(TIF_NOTIFY_SIGNAL) || current->task_works) {
                __set_current_state(TASK_RUNNING);
-               task_work_run();
+               tracehook_notify_signal();
                return true;
        }
 
@@ -2473,8 +2477,10 @@ static void io_fallback_req_func(struct work_struct *work)
        struct llist_node *node = llist_del_all(&ctx->fallback_llist);
        struct io_kiocb *req, *tmp;
 
+       percpu_ref_get(&ctx->refs);
        llist_for_each_entry_safe(req, tmp, node, io_task_work.fallback_node)
                req->io_task_work.func(req);
+       percpu_ref_put(&ctx->refs);
 }
 
 static void __io_complete_rw(struct io_kiocb *req, long res, long res2,
@@ -6803,14 +6809,16 @@ static inline void io_ring_set_wakeup_flag(struct io_ring_ctx *ctx)
 {
        /* Tell userspace we may need a wakeup call */
        spin_lock_irq(&ctx->completion_lock);
-       ctx->rings->sq_flags |= IORING_SQ_NEED_WAKEUP;
+       WRITE_ONCE(ctx->rings->sq_flags,
+                  ctx->rings->sq_flags | IORING_SQ_NEED_WAKEUP);
        spin_unlock_irq(&ctx->completion_lock);
 }
 
 static inline void io_ring_clear_wakeup_flag(struct io_ring_ctx *ctx)
 {
        spin_lock_irq(&ctx->completion_lock);
-       ctx->rings->sq_flags &= ~IORING_SQ_NEED_WAKEUP;
+       WRITE_ONCE(ctx->rings->sq_flags,
+                  ctx->rings->sq_flags & ~IORING_SQ_NEED_WAKEUP);
        spin_unlock_irq(&ctx->completion_lock);
 }
 
@@ -7132,16 +7140,6 @@ static void **io_alloc_page_table(size_t size)
        return table;
 }
 
-static inline void io_rsrc_ref_lock(struct io_ring_ctx *ctx)
-{
-       spin_lock_bh(&ctx->rsrc_ref_lock);
-}
-
-static inline void io_rsrc_ref_unlock(struct io_ring_ctx *ctx)
-{
-       spin_unlock_bh(&ctx->rsrc_ref_lock);
-}
-
 static void io_rsrc_node_destroy(struct io_rsrc_node *ref_node)
 {
        percpu_ref_exit(&ref_node->refs);
@@ -7158,9 +7156,9 @@ static void io_rsrc_node_switch(struct io_ring_ctx *ctx,
                struct io_rsrc_node *rsrc_node = ctx->rsrc_node;
 
                rsrc_node->rsrc_data = data_to_kill;
-               io_rsrc_ref_lock(ctx);
+               spin_lock_irq(&ctx->rsrc_ref_lock);
                list_add_tail(&rsrc_node->node, &ctx->rsrc_ref_list);
-               io_rsrc_ref_unlock(ctx);
+               spin_unlock_irq(&ctx->rsrc_ref_lock);
 
                atomic_inc(&data_to_kill->refs);
                percpu_ref_kill(&rsrc_node->refs);
@@ -7199,17 +7197,19 @@ static int io_rsrc_ref_quiesce(struct io_rsrc_data *data, struct io_ring_ctx *ct
                /* kill initial ref, already quiesced if zero */
                if (atomic_dec_and_test(&data->refs))
                        break;
+               mutex_unlock(&ctx->uring_lock);
                flush_delayed_work(&ctx->rsrc_put_work);
                ret = wait_for_completion_interruptible(&data->done);
-               if (!ret)
+               if (!ret) {
+                       mutex_lock(&ctx->uring_lock);
                        break;
+               }
 
                atomic_inc(&data->refs);
                /* wait for all works potentially completing data->done */
                flush_delayed_work(&ctx->rsrc_put_work);
                reinit_completion(&data->done);
 
-               mutex_unlock(&ctx->uring_lock);
                ret = io_run_task_work_sig();
                mutex_lock(&ctx->uring_lock);
        } while (ret >= 0);
@@ -7668,9 +7668,10 @@ static void io_rsrc_node_ref_zero(struct percpu_ref *ref)
 {
        struct io_rsrc_node *node = container_of(ref, struct io_rsrc_node, refs);
        struct io_ring_ctx *ctx = node->rsrc_data->ctx;
+       unsigned long flags;
        bool first_add = false;
 
-       io_rsrc_ref_lock(ctx);
+       spin_lock_irqsave(&ctx->rsrc_ref_lock, flags);
        node->done = true;
 
        while (!list_empty(&ctx->rsrc_ref_list)) {
@@ -7682,7 +7683,7 @@ static void io_rsrc_node_ref_zero(struct percpu_ref *ref)
                list_del(&node->node);
                first_add |= llist_add(&node->llist, &ctx->rsrc_put_llist);
        }
-       io_rsrc_ref_unlock(ctx);
+       spin_unlock_irqrestore(&ctx->rsrc_ref_lock, flags);
 
        if (first_add)
                mod_delayed_work(system_wq, &ctx->rsrc_put_work, HZ);
@@ -8653,13 +8654,10 @@ static void io_req_caches_free(struct io_ring_ctx *ctx)
        mutex_unlock(&ctx->uring_lock);
 }
 
-static bool io_wait_rsrc_data(struct io_rsrc_data *data)
+static void io_wait_rsrc_data(struct io_rsrc_data *data)
 {
-       if (!data)
-               return false;
-       if (!atomic_dec_and_test(&data->refs))
+       if (data && !atomic_dec_and_test(&data->refs))
                wait_for_completion(&data->done);
-       return true;
 }
 
 static void io_ring_ctx_free(struct io_ring_ctx *ctx)
@@ -8671,10 +8669,14 @@ static void io_ring_ctx_free(struct io_ring_ctx *ctx)
                ctx->mm_account = NULL;
        }
 
+       /* __io_rsrc_put_work() may need uring_lock to progress, wait w/o it */
+       io_wait_rsrc_data(ctx->buf_data);
+       io_wait_rsrc_data(ctx->file_data);
+
        mutex_lock(&ctx->uring_lock);
-       if (io_wait_rsrc_data(ctx->buf_data))
+       if (ctx->buf_data)
                __io_sqe_buffers_unregister(ctx);
-       if (io_wait_rsrc_data(ctx->file_data))
+       if (ctx->file_data)
                __io_sqe_files_unregister(ctx);
        if (ctx->rings)
                __io_cqring_overflow_flush(ctx, true);
@@ -9370,9 +9372,10 @@ SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit,
        if (ctx->flags & IORING_SETUP_SQPOLL) {
                io_cqring_overflow_flush(ctx, false);
 
-               ret = -EOWNERDEAD;
-               if (unlikely(ctx->sq_data->thread == NULL))
+               if (unlikely(ctx->sq_data->thread == NULL)) {
+                       ret = -EOWNERDEAD;
                        goto out;
+               }
                if (flags & IORING_ENTER_SQ_WAKEUP)
                        wake_up(&ctx->sq_data->wait);
                if (flags & IORING_ENTER_SQ_WAIT) {
@@ -9840,10 +9843,11 @@ static int io_register_personality(struct io_ring_ctx *ctx)
 
        ret = xa_alloc_cyclic(&ctx->personalities, &id, (void *)creds,
                        XA_LIMIT(0, USHRT_MAX), &ctx->pers_next, GFP_KERNEL);
-       if (!ret)
-               return id;
-       put_cred(creds);
-       return ret;
+       if (ret < 0) {
+               put_cred(creds);
+               return ret;
+       }
+       return id;
 }
 
 static int io_register_restrictions(struct io_ring_ctx *ctx, void __user *arg,
index ab4174a..97adcb5 100644 (file)
@@ -1716,8 +1716,12 @@ static inline bool may_mount(void)
 }
 
 #ifdef CONFIG_MANDATORY_FILE_LOCKING
-static inline bool may_mandlock(void)
+static bool may_mandlock(void)
 {
+       pr_warn_once("======================================================\n"
+                    "WARNING: the mand mount option is being deprecated and\n"
+                    "         will be removed in v5.15!\n"
+                    "======================================================\n");
        return capable(CAP_SYS_ADMIN);
 }
 #else
@@ -1938,6 +1942,20 @@ void drop_collected_mounts(struct vfsmount *mnt)
        namespace_unlock();
 }
 
+static bool has_locked_children(struct mount *mnt, struct dentry *dentry)
+{
+       struct mount *child;
+
+       list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) {
+               if (!is_subdir(child->mnt_mountpoint, dentry))
+                       continue;
+
+               if (child->mnt.mnt_flags & MNT_LOCKED)
+                       return true;
+       }
+       return false;
+}
+
 /**
  * clone_private_mount - create a private clone of a path
  * @path: path to clone
@@ -1953,10 +1971,19 @@ struct vfsmount *clone_private_mount(const struct path *path)
        struct mount *old_mnt = real_mount(path->mnt);
        struct mount *new_mnt;
 
+       down_read(&namespace_sem);
        if (IS_MNT_UNBINDABLE(old_mnt))
-               return ERR_PTR(-EINVAL);
+               goto invalid;
+
+       if (!check_mnt(old_mnt))
+               goto invalid;
+
+       if (has_locked_children(old_mnt, path->dentry))
+               goto invalid;
 
        new_mnt = clone_mnt(old_mnt, path->dentry, CL_PRIVATE);
+       up_read(&namespace_sem);
+
        if (IS_ERR(new_mnt))
                return ERR_CAST(new_mnt);
 
@@ -1964,6 +1991,10 @@ struct vfsmount *clone_private_mount(const struct path *path)
        new_mnt->mnt_ns = MNT_NS_INTERNAL;
 
        return &new_mnt->mnt;
+
+invalid:
+       up_read(&namespace_sem);
+       return ERR_PTR(-EINVAL);
 }
 EXPORT_SYMBOL_GPL(clone_private_mount);
 
@@ -2315,19 +2346,6 @@ static int do_change_type(struct path *path, int ms_flags)
        return err;
 }
 
-static bool has_locked_children(struct mount *mnt, struct dentry *dentry)
-{
-       struct mount *child;
-       list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) {
-               if (!is_subdir(child->mnt_mountpoint, dentry))
-                       continue;
-
-               if (child->mnt.mnt_flags & MNT_LOCKED)
-                       return true;
-       }
-       return false;
-}
-
 static struct mount *__do_loopback(struct path *old_path, int recurse)
 {
        struct mount *mnt = ERR_PTR(-EINVAL), *old = real_mount(old_path->mnt);
index 64864fb..28b67cb 100644 (file)
@@ -54,22 +54,27 @@ static int fanotify_max_queued_events __read_mostly;
 
 #include <linux/sysctl.h>
 
+static long ft_zero = 0;
+static long ft_int_max = INT_MAX;
+
 struct ctl_table fanotify_table[] = {
        {
                .procname       = "max_user_groups",
                .data   = &init_user_ns.ucount_max[UCOUNT_FANOTIFY_GROUPS],
-               .maxlen         = sizeof(int),
+               .maxlen         = sizeof(long),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec_minmax,
-               .extra1         = SYSCTL_ZERO,
+               .proc_handler   = proc_doulongvec_minmax,
+               .extra1         = &ft_zero,
+               .extra2         = &ft_int_max,
        },
        {
                .procname       = "max_user_marks",
                .data   = &init_user_ns.ucount_max[UCOUNT_FANOTIFY_MARKS],
-               .maxlen         = sizeof(int),
+               .maxlen         = sizeof(long),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec_minmax,
-               .extra1         = SYSCTL_ZERO,
+               .proc_handler   = proc_doulongvec_minmax,
+               .extra1         = &ft_zero,
+               .extra2         = &ft_int_max,
        },
        {
                .procname       = "max_queued_events",
index 98f61b3..6205124 100644 (file)
@@ -55,22 +55,27 @@ struct kmem_cache *inotify_inode_mark_cachep __read_mostly;
 
 #include <linux/sysctl.h>
 
+static long it_zero = 0;
+static long it_int_max = INT_MAX;
+
 struct ctl_table inotify_table[] = {
        {
                .procname       = "max_user_instances",
                .data           = &init_user_ns.ucount_max[UCOUNT_INOTIFY_INSTANCES],
-               .maxlen         = sizeof(int),
+               .maxlen         = sizeof(long),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec_minmax,
-               .extra1         = SYSCTL_ZERO,
+               .proc_handler   = proc_doulongvec_minmax,
+               .extra1         = &it_zero,
+               .extra2         = &it_int_max,
        },
        {
                .procname       = "max_user_watches",
                .data           = &init_user_ns.ucount_max[UCOUNT_INOTIFY_WATCHES],
-               .maxlen         = sizeof(int),
+               .maxlen         = sizeof(long),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec_minmax,
-               .extra1         = SYSCTL_ZERO,
+               .proc_handler   = proc_doulongvec_minmax,
+               .extra1         = &it_zero,
+               .extra2         = &it_int_max,
        },
        {
                .procname       = "max_queued_events",
index 41ebf52..ebde05c 100644 (file)
@@ -392,6 +392,7 @@ static struct dentry *ovl_lookup_real_one(struct dentry *connected,
         */
        take_dentry_name_snapshot(&name, real);
        this = lookup_one_len(name.name.name, connected, name.name.len);
+       release_dentry_name_snapshot(&name);
        err = PTR_ERR(this);
        if (IS_ERR(this)) {
                goto fail;
@@ -406,7 +407,6 @@ static struct dentry *ovl_lookup_real_one(struct dentry *connected,
        }
 
 out:
-       release_dentry_name_snapshot(&name);
        dput(parent);
        inode_unlock(dir);
        return this;
index 4d53d3b..d081faa 100644 (file)
@@ -392,6 +392,51 @@ out_unlock:
        return ret;
 }
 
+/*
+ * Calling iter_file_splice_write() directly from overlay's f_op may deadlock
+ * due to lock order inversion between pipe->mutex in iter_file_splice_write()
+ * and file_start_write(real.file) in ovl_write_iter().
+ *
+ * So do everything ovl_write_iter() does and call iter_file_splice_write() on
+ * the real file.
+ */
+static ssize_t ovl_splice_write(struct pipe_inode_info *pipe, struct file *out,
+                               loff_t *ppos, size_t len, unsigned int flags)
+{
+       struct fd real;
+       const struct cred *old_cred;
+       struct inode *inode = file_inode(out);
+       struct inode *realinode = ovl_inode_real(inode);
+       ssize_t ret;
+
+       inode_lock(inode);
+       /* Update mode */
+       ovl_copyattr(realinode, inode);
+       ret = file_remove_privs(out);
+       if (ret)
+               goto out_unlock;
+
+       ret = ovl_real_fdget(out, &real);
+       if (ret)
+               goto out_unlock;
+
+       old_cred = ovl_override_creds(inode->i_sb);
+       file_start_write(real.file);
+
+       ret = iter_file_splice_write(pipe, real.file, ppos, len, flags);
+
+       file_end_write(real.file);
+       /* Update size */
+       ovl_copyattr(realinode, inode);
+       revert_creds(old_cred);
+       fdput(real);
+
+out_unlock:
+       inode_unlock(inode);
+
+       return ret;
+}
+
 static int ovl_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
        struct fd real;
@@ -603,7 +648,7 @@ const struct file_operations ovl_file_operations = {
        .fadvise        = ovl_fadvise,
        .flush          = ovl_flush,
        .splice_read    = generic_file_splice_read,
-       .splice_write   = iter_file_splice_write,
+       .splice_write   = ovl_splice_write,
 
        .copy_file_range        = ovl_copy_file_range,
        .remap_file_range       = ovl_remap_file_range,
index e8ad2c2..150fdf3 100644 (file)
@@ -481,6 +481,8 @@ static int ovl_cache_update_ino(struct path *path, struct ovl_cache_entry *p)
        }
        this = lookup_one_len(p->name, dir, p->len);
        if (IS_ERR_OR_NULL(this) || !this->d_inode) {
+               /* Mark a stale entry */
+               p->is_whiteout = true;
                if (IS_ERR(this)) {
                        err = PTR_ERR(this);
                        this = NULL;
@@ -776,6 +778,9 @@ static int ovl_iterate(struct file *file, struct dir_context *ctx)
                                if (err)
                                        goto out;
                        }
+               }
+               /* ovl_cache_update_ino() sets is_whiteout on stale entry */
+               if (!p->is_whiteout) {
                        if (!dir_emit(ctx, p->name, p->len, p->ino, p->type))
                                break;
                }
index 8e6ef62..678dee2 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -444,9 +444,6 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from)
 #endif
 
        /*
-        * Epoll nonsensically wants a wakeup whether the pipe
-        * was already empty or not.
-        *
         * If it wasn't empty we try to merge new data into
         * the last buffer.
         *
@@ -455,9 +452,9 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from)
         * spanning multiple pages.
         */
        head = pipe->head;
-       was_empty = true;
+       was_empty = pipe_empty(head, pipe->tail);
        chars = total_len & (PAGE_SIZE-1);
-       if (chars && !pipe_empty(head, pipe->tail)) {
+       if (chars && !was_empty) {
                unsigned int mask = pipe->ring_size - 1;
                struct pipe_buffer *buf = &pipe->bufs[(head - 1) & mask];
                int offset = buf->offset + buf->len;
@@ -590,8 +587,11 @@ out:
         * This is particularly important for small writes, because of
         * how (for example) the GNU make jobserver uses small writes to
         * wake up pending jobs
+        *
+        * Epoll nonsensically wants a wakeup whether the pipe
+        * was already empty or not.
         */
-       if (was_empty) {
+       if (was_empty || pipe->poll_usage) {
                wake_up_interruptible_sync_poll(&pipe->rd_wait, EPOLLIN | EPOLLRDNORM);
                kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
        }
@@ -654,6 +654,9 @@ pipe_poll(struct file *filp, poll_table *wait)
        struct pipe_inode_info *pipe = filp->private_data;
        unsigned int head, tail;
 
+       /* Epoll has some historical nasty semantics, this enables them */
+       pipe->poll_usage = 1;
+
        /*
         * Reading pipe state only -- no need for acquiring the semaphore.
         *
index 1732541..62669b3 100644 (file)
                NOINSTR_TEXT                                            \
                *(.text..refcount)                                      \
                *(.ref.text)                                            \
+               *(.text.asan.* .text.tsan.*)                            \
                TEXT_CFI_JT                                             \
        MEM_KEEP(init.text*)                                            \
        MEM_KEEP(exit.text*)                                            \
index 8b77d08..6c9b10d 100644 (file)
@@ -201,8 +201,8 @@ static inline void bpf_cgroup_storage_unset(void)
 {
        int i;
 
-       for (i = 0; i < BPF_CGROUP_STORAGE_NEST_MAX; i++) {
-               if (unlikely(this_cpu_read(bpf_cgroup_storage_info[i].task) != current))
+       for (i = BPF_CGROUP_STORAGE_NEST_MAX - 1; i >= 0; i--) {
+               if (likely(this_cpu_read(bpf_cgroup_storage_info[i].task) != current))
                        continue;
 
                this_cpu_write(bpf_cgroup_storage_info[i].task, NULL);
index 59940f1..65d84b6 100644 (file)
@@ -407,6 +407,7 @@ struct dev_links_info {
  * @em_pd:     device's energy model performance domain
  * @pins:      For device pin management.
  *             See Documentation/driver-api/pin-control.rst for details.
+ * @msi_lock:  Lock to protect MSI mask cache and mask register
  * @msi_list:  Hosts MSI descriptors
  * @msi_domain: The generic MSI domain this device is using.
  * @numa_node: NUMA node this device is close to.
@@ -506,6 +507,7 @@ struct device {
        struct dev_pin_info     *pins;
 #endif
 #ifdef CONFIG_GENERIC_MSI_IRQ
+       raw_spinlock_t          msi_lock;
        struct list_head        msi_list;
 #endif
 #ifdef CONFIG_DMA_OPS
index 53aa034..aaf4f1b 100644 (file)
@@ -41,7 +41,7 @@ struct in_device {
        unsigned long           mr_qri;         /* Query Response Interval */
        unsigned char           mr_qrv;         /* Query Robustness Variable */
        unsigned char           mr_gq_running;
-       unsigned char           mr_ifc_count;
+       u32                     mr_ifc_count;
        struct timer_list       mr_gq_timer;    /* general query timer */
        struct timer_list       mr_ifc_timer;   /* interface change timer */
 
index 8e9a9ae..c8293c8 100644 (file)
@@ -569,6 +569,7 @@ struct irq_chip {
  * IRQCHIP_SUPPORTS_NMI:              Chip can deliver NMIs, only for root irqchips
  * IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND:  Invokes __enable_irq()/__disable_irq() for wake irqs
  *                                    in the suspend path if they are in disabled state
+ * IRQCHIP_AFFINITY_PRE_STARTUP:      Default affinity update before startup
  */
 enum {
        IRQCHIP_SET_TYPE_MASKED                 = (1 <<  0),
@@ -581,6 +582,7 @@ enum {
        IRQCHIP_SUPPORTS_LEVEL_MSI              = (1 <<  7),
        IRQCHIP_SUPPORTS_NMI                    = (1 <<  8),
        IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND        = (1 <<  9),
+       IRQCHIP_AFFINITY_PRE_STARTUP            = (1 << 10),
 };
 
 #include <linux/irqdesc.h>
index a70d1ea..3fe6dd8 100644 (file)
@@ -51,10 +51,11 @@ extern atomic_t kfence_allocation_gate;
 static __always_inline bool is_kfence_address(const void *addr)
 {
        /*
-        * The non-NULL check is required in case the __kfence_pool pointer was
-        * never initialized; keep it in the slow-path after the range-check.
+        * The __kfence_pool != NULL check is required to deal with the case
+        * where __kfence_pool == NULL && addr < KFENCE_POOL_SIZE. Keep it in
+        * the slow-path after the range-check!
         */
-       return unlikely((unsigned long)((char *)addr - __kfence_pool) < KFENCE_POOL_SIZE && addr);
+       return unlikely((unsigned long)((char *)addr - __kfence_pool) < KFENCE_POOL_SIZE && __kfence_pool);
 }
 
 /**
index bfe5c48..2479792 100644 (file)
@@ -612,12 +612,15 @@ static inline bool mem_cgroup_disabled(void)
        return !cgroup_subsys_enabled(memory_cgrp_subsys);
 }
 
-static inline unsigned long mem_cgroup_protection(struct mem_cgroup *root,
-                                                 struct mem_cgroup *memcg,
-                                                 bool in_low_reclaim)
+static inline void mem_cgroup_protection(struct mem_cgroup *root,
+                                        struct mem_cgroup *memcg,
+                                        unsigned long *min,
+                                        unsigned long *low)
 {
+       *min = *low = 0;
+
        if (mem_cgroup_disabled())
-               return 0;
+               return;
 
        /*
         * There is no reclaim protection applied to a targeted reclaim.
@@ -653,13 +656,10 @@ static inline unsigned long mem_cgroup_protection(struct mem_cgroup *root,
         *
         */
        if (root == memcg)
-               return 0;
-
-       if (in_low_reclaim)
-               return READ_ONCE(memcg->memory.emin);
+               return;
 
-       return max(READ_ONCE(memcg->memory.emin),
-                  READ_ONCE(memcg->memory.elow));
+       *min = READ_ONCE(memcg->memory.emin);
+       *low = READ_ONCE(memcg->memory.elow);
 }
 
 void mem_cgroup_calculate_protection(struct mem_cgroup *root,
@@ -1147,11 +1147,12 @@ static inline void memcg_memory_event_mm(struct mm_struct *mm,
 {
 }
 
-static inline unsigned long mem_cgroup_protection(struct mem_cgroup *root,
-                                                 struct mem_cgroup *memcg,
-                                                 bool in_low_reclaim)
+static inline void mem_cgroup_protection(struct mem_cgroup *root,
+                                        struct mem_cgroup *memcg,
+                                        unsigned long *min,
+                                        unsigned long *low)
 {
-       return 0;
+       *min = *low = 0;
 }
 
 static inline void mem_cgroup_calculate_protection(struct mem_cgroup *root,
index 1efe374..25a8be5 100644 (file)
@@ -1044,8 +1044,7 @@ void mlx5_unregister_debugfs(void);
 void mlx5_fill_page_array(struct mlx5_frag_buf *buf, __be64 *pas);
 void mlx5_fill_page_frag_array_perm(struct mlx5_frag_buf *buf, __be64 *pas, u8 perm);
 void mlx5_fill_page_frag_array(struct mlx5_frag_buf *frag_buf, __be64 *pas);
-int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn,
-                   unsigned int *irqn);
+int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn);
 int mlx5_core_attach_mcg(struct mlx5_core_dev *dev, union ib_gid *mgid, u32 qpn);
 int mlx5_core_detach_mcg(struct mlx5_core_dev *dev, union ib_gid *mgid, u32 qpn);
 
index 98b56b7..1a9c9d9 100644 (file)
@@ -11,13 +11,15 @@ enum {
 };
 
 enum {
-       MLX5_VIRTIO_EMULATION_CAP_VIRTIO_QUEUE_TYPE_SPLIT   = 0x1, // do I check this caps?
-       MLX5_VIRTIO_EMULATION_CAP_VIRTIO_QUEUE_TYPE_PACKED  = 0x2,
+       MLX5_VIRTIO_EMULATION_VIRTIO_QUEUE_TYPE_SPLIT   = 0,
+       MLX5_VIRTIO_EMULATION_VIRTIO_QUEUE_TYPE_PACKED  = 1,
 };
 
 enum {
-       MLX5_VIRTIO_EMULATION_VIRTIO_QUEUE_TYPE_SPLIT   = 0,
-       MLX5_VIRTIO_EMULATION_VIRTIO_QUEUE_TYPE_PACKED  = 1,
+       MLX5_VIRTIO_EMULATION_CAP_VIRTIO_QUEUE_TYPE_SPLIT =
+               BIT(MLX5_VIRTIO_EMULATION_VIRTIO_QUEUE_TYPE_SPLIT),
+       MLX5_VIRTIO_EMULATION_CAP_VIRTIO_QUEUE_TYPE_PACKED =
+               BIT(MLX5_VIRTIO_EMULATION_VIRTIO_QUEUE_TYPE_PACKED),
 };
 
 struct mlx5_ifc_virtio_q_bits {
index 6aff469..e8bdcb8 100644 (file)
@@ -233,7 +233,7 @@ void __pci_read_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
 void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
 
 u32 __pci_msix_desc_mask_irq(struct msi_desc *desc, u32 flag);
-u32 __pci_msi_desc_mask_irq(struct msi_desc *desc, u32 mask, u32 flag);
+void __pci_msi_desc_mask_irq(struct msi_desc *desc, u32 mask, u32 flag);
 void pci_msi_mask_irq(struct irq_data *data);
 void pci_msi_unmask_irq(struct irq_data *data);
 
index 10279c4..ada1296 100644 (file)
@@ -196,6 +196,9 @@ struct ip_set_region {
        u32 elements;           /* Number of elements vs timeout */
 };
 
+/* Max range where every element is added/deleted in one step */
+#define IPSET_MAX_RANGE                (1<<20)
+
 /* The max revision number supported by any set type + 1 */
 #define IPSET_REVISION_MAX     9
 
index 9225ee6..ae6f4eb 100644 (file)
@@ -7,7 +7,7 @@
 
 bool __do_once_start(bool *done, unsigned long *flags);
 void __do_once_done(bool *done, struct static_key_true *once_key,
-                   unsigned long *flags);
+                   unsigned long *flags, struct module *mod);
 
 /* Call a function exactly once. The idea of DO_ONCE() is to perform
  * a function call such as initialization of random seeds, etc, only
@@ -46,7 +46,7 @@ void __do_once_done(bool *done, struct static_key_true *once_key,
                        if (unlikely(___ret)) {                              \
                                func(__VA_ARGS__);                           \
                                __do_once_done(&___done, &___once_key,       \
-                                              &___flags);                   \
+                                              &___flags, THIS_MODULE);      \
                        }                                                    \
                }                                                            \
                ___ret;                                                      \
index 5d2705f..fc56424 100644 (file)
@@ -48,6 +48,7 @@ struct pipe_buffer {
  *     @files: number of struct file referring this pipe (protected by ->i_lock)
  *     @r_counter: reader counter
  *     @w_counter: writer counter
+ *     @poll_usage: is this pipe used for epoll, which has crazy wakeups?
  *     @fasync_readers: reader side fasync
  *     @fasync_writers: writer side fasync
  *     @bufs: the circular array of pipe buffers
@@ -70,6 +71,7 @@ struct pipe_inode_info {
        unsigned int files;
        unsigned int r_counter;
        unsigned int w_counter;
+       unsigned int poll_usage;
        struct page *tmp_page;
        struct fasync_struct *fasync_readers;
        struct fasync_struct *fasync_writers;
index 24eda04..5b72885 100644 (file)
@@ -120,10 +120,11 @@ enum lockdown_reason {
        LOCKDOWN_MMIOTRACE,
        LOCKDOWN_DEBUGFS,
        LOCKDOWN_XMON_WR,
+       LOCKDOWN_BPF_WRITE_USER,
        LOCKDOWN_INTEGRITY_MAX,
        LOCKDOWN_KCORE,
        LOCKDOWN_KPROBES,
-       LOCKDOWN_BPF_READ,
+       LOCKDOWN_BPF_READ_KERNEL,
        LOCKDOWN_PERF,
        LOCKDOWN_TRACEFS,
        LOCKDOWN_XMON_RW,
index 3357ac9..8cfe49d 100644 (file)
@@ -277,6 +277,17 @@ struct vdpa_device *__vdpa_alloc_device(struct device *parent,
                                        const struct vdpa_config_ops *config,
                                        size_t size, const char *name);
 
+/**
+ * vdpa_alloc_device - allocate and initilaize a vDPA device
+ *
+ * @dev_struct: the type of the parent structure
+ * @member: the name of struct vdpa_device within the @dev_struct
+ * @parent: the parent device
+ * @config: the bus operations that is supported by this device
+ * @name: name of the vdpa device
+ *
+ * Return allocated data structure or ERR_PTR upon error
+ */
 #define vdpa_alloc_device(dev_struct, member, parent, config, name)   \
                          container_of(__vdpa_alloc_device( \
                                       parent, config, \
index b1894e0..41edbc0 100644 (file)
@@ -110,6 +110,7 @@ struct virtio_device {
        bool config_enabled;
        bool config_change_pending;
        spinlock_t config_lock;
+       spinlock_t vqs_list_lock; /* Protects VQs list access */
        struct device dev;
        struct virtio_device_id id;
        const struct virtio_config_ops *config;
index 84db7b8..212892c 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/virtio_byteorder.h>
 #include <linux/uio.h>
 #include <linux/slab.h>
+#include <linux/spinlock.h>
 #if IS_REACHABLE(CONFIG_VHOST_IOTLB)
 #include <linux/dma-direction.h>
 #include <linux/vhost_iotlb.h>
index f3c2841..1b9d75a 100644 (file)
@@ -319,14 +319,12 @@ flow_action_mixed_hw_stats_check(const struct flow_action *action,
        if (flow_offload_has_one_action(action))
                return true;
 
-       if (action) {
-               flow_action_for_each(i, action_entry, action) {
-                       if (i && action_entry->hw_stats != last_hw_stats) {
-                               NL_SET_ERR_MSG_MOD(extack, "Mixing HW stats types for actions is not supported");
-                               return false;
-                       }
-                       last_hw_stats = action_entry->hw_stats;
+       flow_action_for_each(i, action_entry, action) {
+               if (i && action_entry->hw_stats != last_hw_stats) {
+                       NL_SET_ERR_MSG_MOD(extack, "Mixing HW stats types for actions is not supported");
+                       return false;
                }
+               last_hw_stats = action_entry->hw_stats;
        }
        return true;
 }
index 37e5300..fefd38d 100644 (file)
@@ -30,7 +30,6 @@ struct nf_tcp_net {
        u8 tcp_ignore_invalid_rst;
 #if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
        unsigned int offload_timeout;
-       unsigned int offload_pickup;
 #endif
 };
 
@@ -44,7 +43,6 @@ struct nf_udp_net {
        unsigned int timeouts[UDP_CT_MAX];
 #if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
        unsigned int offload_timeout;
-       unsigned int offload_pickup;
 #endif
 };
 
index e328c51..0509d2d 100644 (file)
@@ -31,6 +31,8 @@ struct psample_group *psample_group_get(struct net *net, u32 group_num);
 void psample_group_take(struct psample_group *group);
 void psample_group_put(struct psample_group *group);
 
+struct sk_buff;
+
 #if IS_ENABLED(CONFIG_PSAMPLE)
 
 void psample_sample_packet(struct psample_group *group, struct sk_buff *skb,
index 390270e..f160484 100644 (file)
@@ -48,7 +48,9 @@
        {(unsigned long)__GFP_WRITE,            "__GFP_WRITE"},         \
        {(unsigned long)__GFP_RECLAIM,          "__GFP_RECLAIM"},       \
        {(unsigned long)__GFP_DIRECT_RECLAIM,   "__GFP_DIRECT_RECLAIM"},\
-       {(unsigned long)__GFP_KSWAPD_RECLAIM,   "__GFP_KSWAPD_RECLAIM"}\
+       {(unsigned long)__GFP_KSWAPD_RECLAIM,   "__GFP_KSWAPD_RECLAIM"},\
+       {(unsigned long)__GFP_ZEROTAGS,         "__GFP_ZEROTAGS"},      \
+       {(unsigned long)__GFP_SKIP_KASAN_POISON,"__GFP_SKIP_KASAN_POISON"}\
 
 #define show_gfp_flags(flags)                                          \
        (flags) ? __print_flags(flags, "|",                             \
index dc8b722..00a6069 100644 (file)
@@ -66,8 +66,11 @@ enum {
 #define NUD_NONE       0x00
 
 /* NUD_NOARP & NUD_PERMANENT are pseudostates, they never change
-   and make no address resolution or NUD.
-   NUD_PERMANENT also cannot be deleted by garbage collectors.
+ * and make no address resolution or NUD.
+ * NUD_PERMANENT also cannot be deleted by garbage collectors.
+ * When NTF_EXT_LEARNED is set for a bridge fdb entry the different cache entry
+ * states don't make sense and thus are ignored. Such entries don't age and
+ * can roam.
  */
 
 struct nda_cacheinfo {
index 912ec60..bbcd285 100644 (file)
@@ -43,6 +43,15 @@ enum nfnl_hook_chain_info_attributes {
 };
 #define NFNLA_HOOK_INFO_MAX (__NFNLA_HOOK_INFO_MAX - 1)
 
+enum nfnl_hook_chain_desc_attributes {
+       NFNLA_CHAIN_UNSPEC,
+       NFNLA_CHAIN_TABLE,
+       NFNLA_CHAIN_FAMILY,
+       NFNLA_CHAIN_NAME,
+       __NFNLA_CHAIN_MAX,
+};
+#define NFNLA_CHAIN_MAX (__NFNLA_CHAIN_MAX - 1)
+
 /**
  * enum nfnl_hook_chaintype - chain type
  *
index f5b8246..8d97aba 100644 (file)
@@ -397,6 +397,12 @@ static int __init bootconfig_params(char *param, char *val,
        return 0;
 }
 
+static int __init warn_bootconfig(char *str)
+{
+       /* The 'bootconfig' has been handled by bootconfig_params(). */
+       return 0;
+}
+
 static void __init setup_boot_config(void)
 {
        static char tmp_cmdline[COMMAND_LINE_SIZE] __initdata;
@@ -475,9 +481,8 @@ static int __init warn_bootconfig(char *str)
        pr_warn("WARNING: 'bootconfig' found on the kernel command line but CONFIG_BOOT_CONFIG is not set.\n");
        return 0;
 }
-early_param("bootconfig", warn_bootconfig);
-
 #endif
+early_param("bootconfig", warn_bootconfig);
 
 /* Change NUL term back to "=", to make "param" the whole string. */
 static void __init repair_env_string(char *param, char *val)
index b1a5fc0..0a28a80 100644 (file)
@@ -1362,11 +1362,13 @@ u64 __weak bpf_probe_read_kernel(void *dst, u32 size, const void *unsafe_ptr)
 }
 
 /**
- *     __bpf_prog_run - run eBPF program on a given context
+ *     ___bpf_prog_run - run eBPF program on a given context
  *     @regs: is the array of MAX_BPF_EXT_REG eBPF pseudo-registers
  *     @insn: is the array of eBPF instructions
  *
  * Decode and execute eBPF instructions.
+ *
+ * Return: whatever value is in %BPF_R0 at program exit
  */
 static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn)
 {
@@ -1878,6 +1880,9 @@ static void bpf_prog_select_func(struct bpf_prog *fp)
  *
  * Try to JIT eBPF program, if JIT is not available, use interpreter.
  * The BPF program will be executed via BPF_PROG_RUN() macro.
+ *
+ * Return: the &fp argument along with &err set to 0 for success or
+ * a negative errno code on failure
  */
 struct bpf_prog *bpf_prog_select_runtime(struct bpf_prog *fp, int *err)
 {
index 72c58cc..9c011f3 100644 (file)
@@ -1565,8 +1565,8 @@ alloc:
        /* We cannot do copy_from_user or copy_to_user inside
         * the rcu_read_lock. Allocate enough space here.
         */
-       keys = kvmalloc(key_size * bucket_size, GFP_USER | __GFP_NOWARN);
-       values = kvmalloc(value_size * bucket_size, GFP_USER | __GFP_NOWARN);
+       keys = kvmalloc_array(key_size, bucket_size, GFP_USER | __GFP_NOWARN);
+       values = kvmalloc_array(value_size, bucket_size, GFP_USER | __GFP_NOWARN);
        if (!keys || !values) {
                ret = -ENOMEM;
                goto after_loop;
index 62cf003..55f83ea 100644 (file)
@@ -353,9 +353,15 @@ const struct bpf_func_proto bpf_jiffies64_proto = {
 #ifdef CONFIG_CGROUPS
 BPF_CALL_0(bpf_get_current_cgroup_id)
 {
-       struct cgroup *cgrp = task_dfl_cgroup(current);
+       struct cgroup *cgrp;
+       u64 cgrp_id;
 
-       return cgroup_id(cgrp);
+       rcu_read_lock();
+       cgrp = task_dfl_cgroup(current);
+       cgrp_id = cgroup_id(cgrp);
+       rcu_read_unlock();
+
+       return cgrp_id;
 }
 
 const struct bpf_func_proto bpf_get_current_cgroup_id_proto = {
@@ -366,13 +372,17 @@ const struct bpf_func_proto bpf_get_current_cgroup_id_proto = {
 
 BPF_CALL_1(bpf_get_current_ancestor_cgroup_id, int, ancestor_level)
 {
-       struct cgroup *cgrp = task_dfl_cgroup(current);
+       struct cgroup *cgrp;
        struct cgroup *ancestor;
+       u64 cgrp_id;
 
+       rcu_read_lock();
+       cgrp = task_dfl_cgroup(current);
        ancestor = cgroup_ancestor(cgrp, ancestor_level);
-       if (!ancestor)
-               return 0;
-       return cgroup_id(ancestor);
+       cgrp_id = ancestor ? cgroup_id(ancestor) : 0;
+       rcu_read_unlock();
+
+       return cgrp_id;
 }
 
 const struct bpf_func_proto bpf_get_current_ancestor_cgroup_id_proto = {
@@ -397,8 +407,8 @@ BPF_CALL_2(bpf_get_local_storage, struct bpf_map *, map, u64, flags)
        void *ptr;
        int i;
 
-       for (i = 0; i < BPF_CGROUP_STORAGE_NEST_MAX; i++) {
-               if (unlikely(this_cpu_read(bpf_cgroup_storage_info[i].task) != current))
+       for (i = BPF_CGROUP_STORAGE_NEST_MAX - 1; i >= 0; i--) {
+               if (likely(this_cpu_read(bpf_cgroup_storage_info[i].task) != current))
                        continue;
 
                storage = this_cpu_read(bpf_cgroup_storage_info[i].storage[stype]);
@@ -1070,12 +1080,12 @@ bpf_base_func_proto(enum bpf_func_id func_id)
        case BPF_FUNC_probe_read_user:
                return &bpf_probe_read_user_proto;
        case BPF_FUNC_probe_read_kernel:
-               return security_locked_down(LOCKDOWN_BPF_READ) < 0 ?
+               return security_locked_down(LOCKDOWN_BPF_READ_KERNEL) < 0 ?
                       NULL : &bpf_probe_read_kernel_proto;
        case BPF_FUNC_probe_read_user_str:
                return &bpf_probe_read_user_str_proto;
        case BPF_FUNC_probe_read_kernel_str:
-               return security_locked_down(LOCKDOWN_BPF_READ) < 0 ?
+               return security_locked_down(LOCKDOWN_BPF_READ_KERNEL) < 0 ?
                       NULL : &bpf_probe_read_kernel_str_proto;
        case BPF_FUNC_snprintf_btf:
                return &bpf_snprintf_btf_proto;
index f9bda54..381d3d6 100644 (file)
@@ -11663,6 +11663,7 @@ static void sanitize_dead_code(struct bpf_verifier_env *env)
                if (aux_data[i].seen)
                        continue;
                memcpy(insn + i, &trap, sizeof(trap));
+               aux_data[i].zext_dst = false;
        }
 }
 
index e17a566..9594cfd 100644 (file)
@@ -248,9 +248,9 @@ static inline cfi_check_fn find_shadow_check_fn(unsigned long ptr)
 {
        cfi_check_fn fn;
 
-       rcu_read_lock_sched();
+       rcu_read_lock_sched_notrace();
        fn = ptr_to_check_fn(rcu_dereference_sched(cfi_shadow), ptr);
-       rcu_read_unlock_sched();
+       rcu_read_unlock_sched_notrace();
 
        return fn;
 }
@@ -269,11 +269,11 @@ static inline cfi_check_fn find_module_check_fn(unsigned long ptr)
        cfi_check_fn fn = NULL;
        struct module *mod;
 
-       rcu_read_lock_sched();
+       rcu_read_lock_sched_notrace();
        mod = __module_address(ptr);
        if (mod)
                fn = mod->cfi_check;
-       rcu_read_unlock_sched();
+       rcu_read_unlock_sched_notrace();
 
        return fn;
 }
index 7f0e589..b264ab5 100644 (file)
@@ -347,19 +347,20 @@ static void cgroup_base_stat_flush(struct cgroup *cgrp, int cpu)
 }
 
 static struct cgroup_rstat_cpu *
-cgroup_base_stat_cputime_account_begin(struct cgroup *cgrp)
+cgroup_base_stat_cputime_account_begin(struct cgroup *cgrp, unsigned long *flags)
 {
        struct cgroup_rstat_cpu *rstatc;
 
        rstatc = get_cpu_ptr(cgrp->rstat_cpu);
-       u64_stats_update_begin(&rstatc->bsync);
+       *flags = u64_stats_update_begin_irqsave(&rstatc->bsync);
        return rstatc;
 }
 
 static void cgroup_base_stat_cputime_account_end(struct cgroup *cgrp,
-                                                struct cgroup_rstat_cpu *rstatc)
+                                                struct cgroup_rstat_cpu *rstatc,
+                                                unsigned long flags)
 {
-       u64_stats_update_end(&rstatc->bsync);
+       u64_stats_update_end_irqrestore(&rstatc->bsync, flags);
        cgroup_rstat_updated(cgrp, smp_processor_id());
        put_cpu_ptr(rstatc);
 }
@@ -367,18 +368,20 @@ static void cgroup_base_stat_cputime_account_end(struct cgroup *cgrp,
 void __cgroup_account_cputime(struct cgroup *cgrp, u64 delta_exec)
 {
        struct cgroup_rstat_cpu *rstatc;
+       unsigned long flags;
 
-       rstatc = cgroup_base_stat_cputime_account_begin(cgrp);
+       rstatc = cgroup_base_stat_cputime_account_begin(cgrp, &flags);
        rstatc->bstat.cputime.sum_exec_runtime += delta_exec;
-       cgroup_base_stat_cputime_account_end(cgrp, rstatc);
+       cgroup_base_stat_cputime_account_end(cgrp, rstatc, flags);
 }
 
 void __cgroup_account_cputime_field(struct cgroup *cgrp,
                                    enum cpu_usage_stat index, u64 delta_exec)
 {
        struct cgroup_rstat_cpu *rstatc;
+       unsigned long flags;
 
-       rstatc = cgroup_base_stat_cputime_account_begin(cgrp);
+       rstatc = cgroup_base_stat_cputime_account_begin(cgrp, &flags);
 
        switch (index) {
        case CPUTIME_USER:
@@ -394,7 +397,7 @@ void __cgroup_account_cputime_field(struct cgroup *cgrp,
                break;
        }
 
-       cgroup_base_stat_cputime_account_end(cgrp, rstatc);
+       cgroup_base_stat_cputime_account_end(cgrp, rstatc, flags);
 }
 
 /*
index 7f04c7d..a98bcfc 100644 (file)
@@ -265,8 +265,11 @@ int irq_startup(struct irq_desc *desc, bool resend, bool force)
        } else {
                switch (__irq_startup_managed(desc, aff, force)) {
                case IRQ_STARTUP_NORMAL:
+                       if (d->chip->flags & IRQCHIP_AFFINITY_PRE_STARTUP)
+                               irq_setup_affinity(desc);
                        ret = __irq_startup(desc);
-                       irq_setup_affinity(desc);
+                       if (!(d->chip->flags & IRQCHIP_AFFINITY_PRE_STARTUP))
+                               irq_setup_affinity(desc);
                        break;
                case IRQ_STARTUP_MANAGED:
                        irq_do_set_affinity(d, aff, false);
index c41965e..85df3ca 100644 (file)
@@ -476,11 +476,6 @@ skip_activate:
        return 0;
 
 cleanup:
-       for_each_msi_vector(desc, i, dev) {
-               irq_data = irq_domain_get_irq_data(domain, i);
-               if (irqd_is_activated(irq_data))
-                       irq_domain_deactivate_irq(irq_data);
-       }
        msi_domain_free_irqs(domain, dev);
        return ret;
 }
@@ -505,7 +500,15 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
 
 void __msi_domain_free_irqs(struct irq_domain *domain, struct device *dev)
 {
+       struct irq_data *irq_data;
        struct msi_desc *desc;
+       int i;
+
+       for_each_msi_vector(desc, i, dev) {
+               irq_data = irq_domain_get_irq_data(domain, i);
+               if (irqd_is_activated(irq_data))
+                       irq_domain_deactivate_irq(irq_data);
+       }
 
        for_each_msi_entry(desc, dev) {
                /*
index d309d6f..4d2a702 100644 (file)
@@ -453,6 +453,11 @@ static __always_inline void __irq_timings_store(int irq, struct irqt_stat *irqs,
         */
        index = irq_timings_interval_index(interval);
 
+       if (index > PREDICTION_BUFFER_SIZE - 1) {
+               irqs->count = 0;
+               return;
+       }
+
        /*
         * Store the index as an element of the pattern in another
         * circular array.
index b5d9bb5..ad0db32 100644 (file)
@@ -343,7 +343,7 @@ static __always_inline bool
 rt_mutex_cond_detect_deadlock(struct rt_mutex_waiter *waiter,
                              enum rtmutex_chainwalk chwalk)
 {
-       if (IS_ENABLED(CONFIG_DEBUG_RT_MUTEX))
+       if (IS_ENABLED(CONFIG_DEBUG_RT_MUTEXES))
                return waiter != NULL;
        return chwalk == RT_MUTEX_FULL_CHAINWALK;
 }
index 057e17f..6469eca 100644 (file)
@@ -602,7 +602,7 @@ static inline void seccomp_sync_threads(unsigned long flags)
                smp_store_release(&thread->seccomp.filter,
                                  caller->seccomp.filter);
                atomic_set(&thread->seccomp.filter_count,
-                          atomic_read(&thread->seccomp.filter_count));
+                          atomic_read(&caller->seccomp.filter_count));
 
                /*
                 * Don't let an unprivileged task work around
index d567b17..3ee23f4 100644 (file)
@@ -219,6 +219,11 @@ config DYNAMIC_FTRACE_WITH_DIRECT_CALLS
        depends on DYNAMIC_FTRACE_WITH_REGS
        depends on HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
 
+config DYNAMIC_FTRACE_WITH_ARGS
+       def_bool y
+       depends on DYNAMIC_FTRACE
+       depends on HAVE_DYNAMIC_FTRACE_WITH_ARGS
+
 config FUNCTION_PROFILER
        bool "Kernel function profiler"
        depends on FUNCTION_TRACER
index b4916ef..fdd1407 100644 (file)
@@ -990,28 +990,29 @@ bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
                return &bpf_get_numa_node_id_proto;
        case BPF_FUNC_perf_event_read:
                return &bpf_perf_event_read_proto;
-       case BPF_FUNC_probe_write_user:
-               return bpf_get_probe_write_proto();
        case BPF_FUNC_current_task_under_cgroup:
                return &bpf_current_task_under_cgroup_proto;
        case BPF_FUNC_get_prandom_u32:
                return &bpf_get_prandom_u32_proto;
+       case BPF_FUNC_probe_write_user:
+               return security_locked_down(LOCKDOWN_BPF_WRITE_USER) < 0 ?
+                      NULL : bpf_get_probe_write_proto();
        case BPF_FUNC_probe_read_user:
                return &bpf_probe_read_user_proto;
        case BPF_FUNC_probe_read_kernel:
-               return security_locked_down(LOCKDOWN_BPF_READ) < 0 ?
+               return security_locked_down(LOCKDOWN_BPF_READ_KERNEL) < 0 ?
                       NULL : &bpf_probe_read_kernel_proto;
        case BPF_FUNC_probe_read_user_str:
                return &bpf_probe_read_user_str_proto;
        case BPF_FUNC_probe_read_kernel_str:
-               return security_locked_down(LOCKDOWN_BPF_READ) < 0 ?
+               return security_locked_down(LOCKDOWN_BPF_READ_KERNEL) < 0 ?
                       NULL : &bpf_probe_read_kernel_str_proto;
 #ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
        case BPF_FUNC_probe_read:
-               return security_locked_down(LOCKDOWN_BPF_READ) < 0 ?
+               return security_locked_down(LOCKDOWN_BPF_READ_KERNEL) < 0 ?
                       NULL : &bpf_probe_read_compat_proto;
        case BPF_FUNC_probe_read_str:
-               return security_locked_down(LOCKDOWN_BPF_READ) < 0 ?
+               return security_locked_down(LOCKDOWN_BPF_READ_KERNEL) < 0 ?
                       NULL : &bpf_probe_read_compat_str_proto;
 #endif
 #ifdef CONFIG_CGROUPS
index 33899a7..a1adb29 100644 (file)
@@ -2897,14 +2897,26 @@ int tracepoint_printk_sysctl(struct ctl_table *table, int write,
 
 void trace_event_buffer_commit(struct trace_event_buffer *fbuffer)
 {
+       enum event_trigger_type tt = ETT_NONE;
+       struct trace_event_file *file = fbuffer->trace_file;
+
+       if (__event_trigger_test_discard(file, fbuffer->buffer, fbuffer->event,
+                       fbuffer->entry, &tt))
+               goto discard;
+
        if (static_key_false(&tracepoint_printk_key.key))
                output_printk(fbuffer);
 
        if (static_branch_unlikely(&trace_event_exports_enabled))
                ftrace_exports(fbuffer->event, TRACE_EXPORT_EVENT);
-       event_trigger_unlock_commit_regs(fbuffer->trace_file, fbuffer->buffer,
-                                   fbuffer->event, fbuffer->entry,
-                                   fbuffer->trace_ctx, fbuffer->regs);
+
+       trace_buffer_unlock_commit_regs(file->tr, fbuffer->buffer,
+                       fbuffer->event, fbuffer->trace_ctx, fbuffer->regs);
+
+discard:
+       if (tt)
+               event_triggers_post_call(file, tt);
+
 }
 EXPORT_SYMBOL_GPL(trace_event_buffer_commit);
 
index a180abf..4a0e693 100644 (file)
@@ -1389,38 +1389,6 @@ event_trigger_unlock_commit(struct trace_event_file *file,
                event_triggers_post_call(file, tt);
 }
 
-/**
- * event_trigger_unlock_commit_regs - handle triggers and finish event commit
- * @file: The file pointer associated with the event
- * @buffer: The ring buffer that the event is being written to
- * @event: The event meta data in the ring buffer
- * @entry: The event itself
- * @trace_ctx: The tracing context flags.
- *
- * This is a helper function to handle triggers that require data
- * from the event itself. It also tests the event against filters and
- * if the event is soft disabled and should be discarded.
- *
- * Same as event_trigger_unlock_commit() but calls
- * trace_buffer_unlock_commit_regs() instead of trace_buffer_unlock_commit().
- */
-static inline void
-event_trigger_unlock_commit_regs(struct trace_event_file *file,
-                                struct trace_buffer *buffer,
-                                struct ring_buffer_event *event,
-                                void *entry, unsigned int trace_ctx,
-                                struct pt_regs *regs)
-{
-       enum event_trigger_type tt = ETT_NONE;
-
-       if (!__event_trigger_test_discard(file, buffer, event, entry, &tt))
-               trace_buffer_unlock_commit_regs(file->tr, buffer, event,
-                                               trace_ctx, regs);
-
-       if (tt)
-               event_triggers_post_call(file, tt);
-}
-
 #define FILTER_PRED_INVALID    ((unsigned short)-1)
 #define FILTER_PRED_IS_RIGHT   (1 << 15)
 #define FILTER_PRED_FOLD       (1 << 15)
index 949ef09..a48aa2a 100644 (file)
@@ -3430,6 +3430,8 @@ trace_action_create_field_var(struct hist_trigger_data *hist_data,
                        event = data->match_data.event;
                }
 
+               if (!event)
+                       goto free;
                /*
                 * At this point, we're looking at a field on another
                 * event.  Because we can't modify a hist trigger on
index a7e3c24..b61eefe 100644 (file)
@@ -253,10 +253,40 @@ static struct osnoise_data {
  */
 static bool osnoise_busy;
 
+#ifdef CONFIG_PREEMPT_RT
 /*
  * Print the osnoise header info.
  */
 static void print_osnoise_headers(struct seq_file *s)
+{
+       if (osnoise_data.tainted)
+               seq_puts(s, "# osnoise is tainted!\n");
+
+       seq_puts(s, "#                                _-------=> irqs-off\n");
+       seq_puts(s, "#                               / _------=> need-resched\n");
+       seq_puts(s, "#                              | / _-----=> need-resched-lazy\n");
+       seq_puts(s, "#                              || / _----=> hardirq/softirq\n");
+       seq_puts(s, "#                              ||| / _---=> preempt-depth\n");
+       seq_puts(s, "#                              |||| / _--=> preempt-lazy-depth\n");
+       seq_puts(s, "#                              ||||| / _-=> migrate-disable\n");
+
+       seq_puts(s, "#                              |||||| /          ");
+       seq_puts(s, "                                     MAX\n");
+
+       seq_puts(s, "#                              ||||| /                         ");
+       seq_puts(s, "                    SINGLE      Interference counters:\n");
+
+       seq_puts(s, "#                              |||||||               RUNTIME   ");
+       seq_puts(s, "   NOISE  %% OF CPU  NOISE    +-----------------------------+\n");
+
+       seq_puts(s, "#           TASK-PID      CPU# |||||||   TIMESTAMP    IN US    ");
+       seq_puts(s, "   IN US  AVAILABLE  IN US     HW    NMI    IRQ   SIRQ THREAD\n");
+
+       seq_puts(s, "#              | |         |   |||||||      |           |      ");
+       seq_puts(s, "       |    |            |      |      |      |      |      |\n");
+}
+#else /* CONFIG_PREEMPT_RT */
+static void print_osnoise_headers(struct seq_file *s)
 {
        if (osnoise_data.tainted)
                seq_puts(s, "# osnoise is tainted!\n");
@@ -279,6 +309,7 @@ static void print_osnoise_headers(struct seq_file *s)
        seq_puts(s, "#              | |         |   ||||      |           |      ");
        seq_puts(s, "       |    |            |      |      |      |      |      |\n");
 }
+#endif /* CONFIG_PREEMPT_RT */
 
 /*
  * osnoise_taint - report an osnoise error.
@@ -323,6 +354,24 @@ static void trace_osnoise_sample(struct osnoise_sample *sample)
 /*
  * Print the timerlat header info.
  */
+#ifdef CONFIG_PREEMPT_RT
+static void print_timerlat_headers(struct seq_file *s)
+{
+       seq_puts(s, "#                                _-------=> irqs-off\n");
+       seq_puts(s, "#                               / _------=> need-resched\n");
+       seq_puts(s, "#                              | / _-----=> need-resched-lazy\n");
+       seq_puts(s, "#                              || / _----=> hardirq/softirq\n");
+       seq_puts(s, "#                              ||| / _---=> preempt-depth\n");
+       seq_puts(s, "#                              |||| / _--=> preempt-lazy-depth\n");
+       seq_puts(s, "#                              ||||| / _-=> migrate-disable\n");
+       seq_puts(s, "#                              |||||| /\n");
+       seq_puts(s, "#                              |||||||             ACTIVATION\n");
+       seq_puts(s, "#           TASK-PID      CPU# |||||||   TIMESTAMP    ID     ");
+       seq_puts(s, "       CONTEXT                LATENCY\n");
+       seq_puts(s, "#              | |         |   |||||||      |         |      ");
+       seq_puts(s, "            |                       |\n");
+}
+#else /* CONFIG_PREEMPT_RT */
 static void print_timerlat_headers(struct seq_file *s)
 {
        seq_puts(s, "#                                _-----=> irqs-off\n");
@@ -336,6 +385,7 @@ static void print_timerlat_headers(struct seq_file *s)
        seq_puts(s, "#              | |         |   ||||      |         |      ");
        seq_puts(s, "            |                       |\n");
 }
+#endif /* CONFIG_PREEMPT_RT */
 
 /*
  * Record an timerlat_sample into the tracer buffer.
@@ -1025,9 +1075,13 @@ diff_osn_sample_stats(struct osnoise_variables *osn_var, struct osnoise_sample *
 /*
  * osnoise_stop_tracing - Stop tracing and the tracer.
  */
-static void osnoise_stop_tracing(void)
+static __always_inline void osnoise_stop_tracing(void)
 {
        struct trace_array *tr = osnoise_trace;
+
+       trace_array_printk_buf(tr->array_buffer.buffer, _THIS_IP_,
+                       "stop tracing hit on cpu %d\n", smp_processor_id());
+
        tracer_tracing_off(tr);
 }
 
index 77be3bb..bb51849 100644 (file)
@@ -58,14 +58,17 @@ static struct ctl_table_root set_root = {
        .permissions = set_permissions,
 };
 
-#define UCOUNT_ENTRY(name)                             \
-       {                                               \
-               .procname       = name,                 \
-               .maxlen         = sizeof(int),          \
-               .mode           = 0644,                 \
-               .proc_handler   = proc_dointvec_minmax, \
-               .extra1         = SYSCTL_ZERO,          \
-               .extra2         = SYSCTL_INT_MAX,       \
+static long ue_zero = 0;
+static long ue_int_max = INT_MAX;
+
+#define UCOUNT_ENTRY(name)                                     \
+       {                                                       \
+               .procname       = name,                         \
+               .maxlen         = sizeof(long),                 \
+               .mode           = 0644,                         \
+               .proc_handler   = proc_doulongvec_minmax,       \
+               .extra1         = &ue_zero,                     \
+               .extra2         = &ue_int_max,                  \
        }
 static struct ctl_table user_table[] = {
        UCOUNT_ENTRY("max_user_namespaces"),
index c0d67c5..60be9e2 100644 (file)
@@ -19,7 +19,7 @@
  */
 int devmem_is_allowed(unsigned long pfn)
 {
-       if (iomem_is_exclusive(pfn << PAGE_SHIFT))
+       if (iomem_is_exclusive(PFN_PHYS(pfn)))
                return 0;
        if (!page_is_ram(pfn))
                return 1;
index 8b7d623..59149bf 100644 (file)
@@ -3,10 +3,12 @@
 #include <linux/spinlock.h>
 #include <linux/once.h>
 #include <linux/random.h>
+#include <linux/module.h>
 
 struct once_work {
        struct work_struct work;
        struct static_key_true *key;
+       struct module *module;
 };
 
 static void once_deferred(struct work_struct *w)
@@ -16,10 +18,11 @@ static void once_deferred(struct work_struct *w)
        work = container_of(w, struct once_work, work);
        BUG_ON(!static_key_enabled(work->key));
        static_branch_disable(work->key);
+       module_put(work->module);
        kfree(work);
 }
 
-static void once_disable_jump(struct static_key_true *key)
+static void once_disable_jump(struct static_key_true *key, struct module *mod)
 {
        struct once_work *w;
 
@@ -29,6 +32,8 @@ static void once_disable_jump(struct static_key_true *key)
 
        INIT_WORK(&w->work, once_deferred);
        w->key = key;
+       w->module = mod;
+       __module_get(mod);
        schedule_work(&w->work);
 }
 
@@ -53,11 +58,11 @@ bool __do_once_start(bool *done, unsigned long *flags)
 EXPORT_SYMBOL(__do_once_start);
 
 void __do_once_done(bool *done, struct static_key_true *once_key,
-                   unsigned long *flags)
+                   unsigned long *flags, struct module *mod)
        __releases(once_lock)
 {
        *done = true;
        spin_unlock_irqrestore(&once_lock, *flags);
-       once_disable_jump(once_key);
+       once_disable_jump(once_key, mod);
 }
 EXPORT_SYMBOL(__do_once_done);
index 42b8b1f..b947179 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -1558,9 +1558,12 @@ long faultin_vma_page_range(struct vm_area_struct *vma, unsigned long start,
                gup_flags |= FOLL_WRITE;
 
        /*
-        * See check_vma_flags(): Will return -EFAULT on incompatible mappings
-        * or with insufficient permissions.
+        * We want to report -EINVAL instead of -EFAULT for any permission
+        * problems or incompatible mappings.
         */
+       if (check_vma_flags(vma, gup_flags))
+               return -EINVAL;
+
        return __get_user_pages(mm, start, nr_pages, gup_flags,
                                NULL, NULL, locked);
 }
index dfc940d..8ea35ba 100644 (file)
@@ -2476,7 +2476,7 @@ void restore_reserve_on_error(struct hstate *h, struct vm_area_struct *vma,
                if (!rc) {
                        /*
                         * This indicates there is an entry in the reserve map
-                        * added by alloc_huge_page.  We know it was added
+                        * not added by alloc_huge_page.  We know it was added
                         * before the alloc_huge_page call, otherwise
                         * HPageRestoreReserve would be set on the page.
                         * Remove the entry so that a subsequent allocation
@@ -4660,7 +4660,9 @@ retry_avoidcopy:
        spin_unlock(ptl);
        mmu_notifier_invalidate_range_end(&range);
 out_release_all:
-       restore_reserve_on_error(h, vma, haddr, new_page);
+       /* No restore in case of successful pagetable update (Break COW) */
+       if (new_page != old_page)
+               restore_reserve_on_error(h, vma, haddr, new_page);
        put_page(new_page);
 out_release_old:
        put_page(old_page);
@@ -4776,7 +4778,7 @@ static vm_fault_t hugetlb_no_page(struct mm_struct *mm,
        pte_t new_pte;
        spinlock_t *ptl;
        unsigned long haddr = address & huge_page_mask(h);
-       bool new_page = false;
+       bool new_page, new_pagecache_page = false;
 
        /*
         * Currently, we are forced to kill the process in the event the
@@ -4799,6 +4801,7 @@ static vm_fault_t hugetlb_no_page(struct mm_struct *mm,
                goto out;
 
 retry:
+       new_page = false;
        page = find_lock_page(mapping, idx);
        if (!page) {
                /* Check for page in userfault range */
@@ -4842,6 +4845,7 @@ retry:
                                        goto retry;
                                goto out;
                        }
+                       new_pagecache_page = true;
                } else {
                        lock_page(page);
                        if (unlikely(anon_vma_prepare(vma))) {
@@ -4926,7 +4930,9 @@ backout:
        spin_unlock(ptl);
 backout_unlocked:
        unlock_page(page);
-       restore_reserve_on_error(h, vma, haddr, page);
+       /* restore reserve for newly allocated pages not in page cache */
+       if (new_page && !new_pagecache_page)
+               restore_reserve_on_error(h, vma, haddr, page);
        put_page(page);
        goto out;
 }
@@ -5135,6 +5141,7 @@ int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm,
        int ret = -ENOMEM;
        struct page *page;
        int writable;
+       bool new_pagecache_page = false;
 
        if (is_continue) {
                ret = -EFAULT;
@@ -5228,6 +5235,7 @@ int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm,
                ret = huge_add_to_page_cache(page, mapping, idx);
                if (ret)
                        goto out_release_nounlock;
+               new_pagecache_page = true;
        }
 
        ptl = huge_pte_lockptr(h, dst_mm, dst_pte);
@@ -5291,7 +5299,8 @@ out_release_unlock:
        if (vm_shared || is_continue)
                unlock_page(page);
 out_release_nounlock:
-       restore_reserve_on_error(h, dst_vma, dst_addr, page);
+       if (!new_pagecache_page)
+               restore_reserve_on_error(h, dst_vma, dst_addr, page);
        put_page(page);
        goto out;
 }
index 228a2fb..73d46d1 100644 (file)
@@ -290,7 +290,7 @@ static void hex_dump_object(struct seq_file *seq,
        warn_or_seq_printf(seq, "  hex dump (first %zu bytes):\n", len);
        kasan_disable_current();
        warn_or_seq_hex_dump(seq, DUMP_PREFIX_NONE, HEX_ROW_SIZE,
-                            HEX_GROUP_SIZE, ptr, len, HEX_ASCII);
+                            HEX_GROUP_SIZE, kasan_reset_tag((void *)ptr), len, HEX_ASCII);
        kasan_enable_current();
 }
 
@@ -1171,7 +1171,7 @@ static bool update_checksum(struct kmemleak_object *object)
 
        kasan_disable_current();
        kcsan_disable_current();
-       object->checksum = crc32(0, (void *)object->pointer, object->size);
+       object->checksum = crc32(0, kasan_reset_tag((void *)object->pointer), object->size);
        kasan_enable_current();
        kcsan_enable_current();
 
@@ -1246,7 +1246,7 @@ static void scan_block(void *_start, void *_end,
                        break;
 
                kasan_disable_current();
-               pointer = *ptr;
+               pointer = *(unsigned long *)kasan_reset_tag((void *)ptr);
                kasan_enable_current();
 
                untagged_ptr = (unsigned long)kasan_reset_tag((void *)pointer);
index 6d3d348..5c065bc 100644 (file)
@@ -862,10 +862,12 @@ static long madvise_populate(struct vm_area_struct *vma,
                        switch (pages) {
                        case -EINTR:
                                return -EINTR;
-                       case -EFAULT: /* Incompatible mappings / permissions. */
+                       case -EINVAL: /* Incompatible mappings / permissions. */
                                return -EINVAL;
                        case -EHWPOISON:
                                return -EHWPOISON;
+                       case -EFAULT: /* VM_FAULT_SIGBUS or VM_FAULT_SIGSEGV */
+                               return -EFAULT;
                        default:
                                pr_warn_once("%s: unhandled return value: %ld\n",
                                             __func__, pages);
index eb8e87c..702a81d 100644 (file)
@@ -3106,13 +3106,15 @@ void mod_objcg_state(struct obj_cgroup *objcg, struct pglist_data *pgdat,
                stock->cached_pgdat = pgdat;
        } else if (stock->cached_pgdat != pgdat) {
                /* Flush the existing cached vmstat data */
+               struct pglist_data *oldpg = stock->cached_pgdat;
+
                if (stock->nr_slab_reclaimable_b) {
-                       mod_objcg_mlstate(objcg, pgdat, NR_SLAB_RECLAIMABLE_B,
+                       mod_objcg_mlstate(objcg, oldpg, NR_SLAB_RECLAIMABLE_B,
                                          stock->nr_slab_reclaimable_b);
                        stock->nr_slab_reclaimable_b = 0;
                }
                if (stock->nr_slab_unreclaimable_b) {
-                       mod_objcg_mlstate(objcg, pgdat, NR_SLAB_UNRECLAIMABLE_B,
+                       mod_objcg_mlstate(objcg, oldpg, NR_SLAB_UNRECLAIMABLE_B,
                                          stock->nr_slab_unreclaimable_b);
                        stock->nr_slab_unreclaimable_b = 0;
                }
index eefd823..470400c 100644 (file)
@@ -1146,7 +1146,7 @@ static int __get_hwpoison_page(struct page *page)
         * unexpected races caused by taking a page refcount.
         */
        if (!HWPoisonHandlable(head))
-               return 0;
+               return -EBUSY;
 
        if (PageTransHuge(head)) {
                /*
@@ -1199,9 +1199,15 @@ try_again:
                        }
                        goto out;
                } else if (ret == -EBUSY) {
-                       /* We raced with freeing huge page to buddy, retry. */
-                       if (pass++ < 3)
+                       /*
+                        * We raced with (possibly temporary) unhandlable
+                        * page, retry.
+                        */
+                       if (pass++ < 3) {
+                               shake_page(p, 1);
                                goto try_again;
+                       }
+                       ret = -EIO;
                        goto out;
                }
        }
index 856b175..eeb3a9c 100644 (file)
@@ -3453,19 +3453,10 @@ void free_unref_page_list(struct list_head *list)
                 * comment in free_unref_page.
                 */
                migratetype = get_pcppage_migratetype(page);
-               if (unlikely(migratetype >= MIGRATE_PCPTYPES)) {
-                       if (unlikely(is_migrate_isolate(migratetype))) {
-                               list_del(&page->lru);
-                               free_one_page(page_zone(page), page, pfn, 0,
-                                                       migratetype, FPI_NONE);
-                               continue;
-                       }
-
-                       /*
-                        * Non-isolated types over MIGRATE_PCPTYPES get added
-                        * to the MIGRATE_MOVABLE pcp list.
-                        */
-                       set_pcppage_migratetype(page, MIGRATE_MOVABLE);
+               if (unlikely(is_migrate_isolate(migratetype))) {
+                       list_del(&page->lru);
+                       free_one_page(page_zone(page), page, pfn, 0, migratetype, FPI_NONE);
+                       continue;
                }
 
                set_page_private(page, pfn);
@@ -3475,7 +3466,15 @@ void free_unref_page_list(struct list_head *list)
        list_for_each_entry_safe(page, next, list, lru) {
                pfn = page_private(page);
                set_page_private(page, 0);
+
+               /*
+                * Non-isolated types over MIGRATE_PCPTYPES get added
+                * to the MIGRATE_MOVABLE pcp list.
+                */
                migratetype = get_pcppage_migratetype(page);
+               if (unlikely(migratetype >= MIGRATE_PCPTYPES))
+                       migratetype = MIGRATE_MOVABLE;
+
                trace_mm_page_free_batched(page);
                free_unref_page_commit(page, pfn, migratetype, 0);
 
index 70d9ce2..dacda74 100644 (file)
@@ -1696,8 +1696,7 @@ static int shmem_swapin_page(struct inode *inode, pgoff_t index,
        struct address_space *mapping = inode->i_mapping;
        struct shmem_inode_info *info = SHMEM_I(inode);
        struct mm_struct *charge_mm = vma ? vma->vm_mm : NULL;
-       struct swap_info_struct *si;
-       struct page *page = NULL;
+       struct page *page;
        swp_entry_t swap;
        int error;
 
@@ -1705,12 +1704,6 @@ static int shmem_swapin_page(struct inode *inode, pgoff_t index,
        swap = radix_to_swp_entry(*pagep);
        *pagep = NULL;
 
-       /* Prevent swapoff from happening to us. */
-       si = get_swap_device(swap);
-       if (!si) {
-               error = EINVAL;
-               goto failed;
-       }
        /* Look it up and read it in.. */
        page = lookup_swap_cache(swap, NULL, 0);
        if (!page) {
@@ -1772,8 +1765,6 @@ static int shmem_swapin_page(struct inode *inode, pgoff_t index,
        swap_free(swap);
 
        *pagep = page;
-       if (si)
-               put_swap_device(si);
        return 0;
 failed:
        if (!shmem_confirm_swap(mapping, index, swap))
@@ -1784,9 +1775,6 @@ unlock:
                put_page(page);
        }
 
-       if (si)
-               put_swap_device(si);
-
        return error;
 }
 
index af984e4..f77d8cd 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -576,8 +576,8 @@ static void print_section(char *level, char *text, u8 *addr,
                          unsigned int length)
 {
        metadata_access_enable();
-       print_hex_dump(level, kasan_reset_tag(text), DUMP_PREFIX_ADDRESS,
-                       16, 1, addr, length, 1);
+       print_hex_dump(level, text, DUMP_PREFIX_ADDRESS,
+                       16, 1, kasan_reset_tag((void *)addr), length, 1);
        metadata_access_disable();
 }
 
@@ -1400,12 +1400,13 @@ check_slabs:
 static int __init setup_slub_debug(char *str)
 {
        slab_flags_t flags;
+       slab_flags_t global_flags;
        char *saved_str;
        char *slab_list;
        bool global_slub_debug_changed = false;
        bool slab_list_specified = false;
 
-       slub_debug = DEBUG_DEFAULT_FLAGS;
+       global_flags = DEBUG_DEFAULT_FLAGS;
        if (*str++ != '=' || !*str)
                /*
                 * No options specified. Switch on full debugging.
@@ -1417,7 +1418,7 @@ static int __init setup_slub_debug(char *str)
                str = parse_slub_debug_flags(str, &flags, &slab_list, true);
 
                if (!slab_list) {
-                       slub_debug = flags;
+                       global_flags = flags;
                        global_slub_debug_changed = true;
                } else {
                        slab_list_specified = true;
@@ -1426,16 +1427,18 @@ static int __init setup_slub_debug(char *str)
 
        /*
         * For backwards compatibility, a single list of flags with list of
-        * slabs means debugging is only enabled for those slabs, so the global
-        * slub_debug should be 0. We can extended that to multiple lists as
+        * slabs means debugging is only changed for those slabs, so the global
+        * slub_debug should be unchanged (0 or DEBUG_DEFAULT_FLAGS, depending
+        * on CONFIG_SLUB_DEBUG_ON). We can extended that to multiple lists as
         * long as there is no option specifying flags without a slab list.
         */
        if (slab_list_specified) {
                if (!global_slub_debug_changed)
-                       slub_debug = 0;
+                       global_flags = slub_debug;
                slub_debug_string = saved_str;
        }
 out:
+       slub_debug = global_flags;
        if (slub_debug != 0 || slub_debug_string)
                static_branch_enable(&slub_debug_enabled);
        else
@@ -3236,12 +3239,12 @@ struct detached_freelist {
        struct kmem_cache *s;
 };
 
-static inline void free_nonslab_page(struct page *page)
+static inline void free_nonslab_page(struct page *page, void *object)
 {
        unsigned int order = compound_order(page);
 
        VM_BUG_ON_PAGE(!PageCompound(page), page);
-       kfree_hook(page_address(page));
+       kfree_hook(object);
        mod_lruvec_page_state(page, NR_SLAB_UNRECLAIMABLE_B, -(PAGE_SIZE << order));
        __free_pages(page, order);
 }
@@ -3282,7 +3285,7 @@ int build_detached_freelist(struct kmem_cache *s, size_t size,
        if (!s) {
                /* Handle kalloc'ed objects */
                if (unlikely(!PageSlab(page))) {
-                       free_nonslab_page(page);
+                       free_nonslab_page(page, object);
                        p[size] = NULL; /* mark object processed */
                        return size;
                }
@@ -4258,7 +4261,7 @@ void kfree(const void *x)
 
        page = virt_to_head_page(x);
        if (unlikely(!PageSlab(page))) {
-               free_nonslab_page(page);
+               free_nonslab_page(page, object);
                return;
        }
        slab_free(page->slab_cache, page, object, NULL, 1, _RET_IP_);
index c56aa9a..bc7cee6 100644 (file)
@@ -628,13 +628,6 @@ struct page *swap_cluster_readahead(swp_entry_t entry, gfp_t gfp_mask,
        if (!mask)
                goto skip;
 
-       /* Test swap type to make sure the dereference is safe */
-       if (likely(si->flags & (SWP_BLKDEV | SWP_FS_OPS))) {
-               struct inode *inode = si->swap_file->f_mapping->host;
-               if (inode_read_congested(inode))
-                       goto skip;
-       }
-
        do_poll = false;
        /* Read a page_cluster sized and aligned cluster around offset. */
        start_offset = offset & ~mask;
index 4620df6..eeae2f6 100644 (file)
@@ -100,9 +100,12 @@ struct scan_control {
        unsigned int may_swap:1;
 
        /*
-        * Cgroups are not reclaimed below their configured memory.low,
-        * unless we threaten to OOM. If any cgroups are skipped due to
-        * memory.low and nothing was reclaimed, go back for memory.low.
+        * Cgroup memory below memory.low is protected as long as we
+        * don't threaten to OOM. If any cgroup is reclaimed at
+        * reduced force or passed over entirely due to its memory.low
+        * setting (memcg_low_skipped), and nothing is reclaimed as a
+        * result, then go back for one more cycle that reclaims the protected
+        * memory (memcg_low_reclaim) to avert OOM.
         */
        unsigned int memcg_low_reclaim:1;
        unsigned int memcg_low_skipped:1;
@@ -2537,15 +2540,14 @@ out:
        for_each_evictable_lru(lru) {
                int file = is_file_lru(lru);
                unsigned long lruvec_size;
+               unsigned long low, min;
                unsigned long scan;
-               unsigned long protection;
 
                lruvec_size = lruvec_lru_size(lruvec, lru, sc->reclaim_idx);
-               protection = mem_cgroup_protection(sc->target_mem_cgroup,
-                                                  memcg,
-                                                  sc->memcg_low_reclaim);
+               mem_cgroup_protection(sc->target_mem_cgroup, memcg,
+                                     &min, &low);
 
-               if (protection) {
+               if (min || low) {
                        /*
                         * Scale a cgroup's reclaim pressure by proportioning
                         * its current usage to its memory.low or memory.min
@@ -2576,6 +2578,15 @@ out:
                         * hard protection.
                         */
                        unsigned long cgroup_size = mem_cgroup_size(memcg);
+                       unsigned long protection;
+
+                       /* memory.low scaling, make sure we retry before OOM */
+                       if (!sc->memcg_low_reclaim && low > min) {
+                               protection = low;
+                               sc->memcg_low_skipped = 1;
+                       } else {
+                               protection = min;
+                       }
 
                        /* Avoid TOCTOU with earlier protection check */
                        cgroup_size = max(cgroup_size, protection);
@@ -4413,11 +4424,13 @@ static int __node_reclaim(struct pglist_data *pgdat, gfp_t gfp_mask, unsigned in
                .may_swap = 1,
                .reclaim_idx = gfp_zone(gfp_mask),
        };
+       unsigned long pflags;
 
        trace_mm_vmscan_node_reclaim_begin(pgdat->node_id, order,
                                           sc.gfp_mask);
 
        cond_resched();
+       psi_memstall_enter(&pflags);
        fs_reclaim_acquire(sc.gfp_mask);
        /*
         * We need to be able to allocate from the reserves for RECLAIM_UNMAP
@@ -4442,6 +4455,7 @@ static int __node_reclaim(struct pglist_data *pgdat, gfp_t gfp_mask, unsigned in
        current->flags &= ~PF_SWAPWRITE;
        memalloc_noreclaim_restore(noreclaim_flag);
        fs_reclaim_release(sc.gfp_mask);
+       psi_memstall_leave(&pflags);
 
        trace_mm_vmscan_node_reclaim_end(sc.nr_reclaimed);
 
index 1cc75c8..caa16bf 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/vmalloc.h>
 #include <linux/etherdevice.h>
 #include <linux/filter.h>
+#include <linux/rcupdate_trace.h>
 #include <linux/sched/signal.h>
 #include <net/bpf_sk_storage.h>
 #include <net/sock.h>
@@ -951,7 +952,10 @@ int bpf_prog_test_run_syscall(struct bpf_prog *prog,
                        goto out;
                }
        }
+
+       rcu_read_lock_trace();
        retval = bpf_prog_run_pin_on_cpu(prog, ctx);
+       rcu_read_unlock_trace();
 
        if (copy_to_user(&uattr->test.retval, &retval, sizeof(u32))) {
                err = -EFAULT;
index bbab998..ef743f9 100644 (file)
@@ -166,8 +166,7 @@ static int br_switchdev_event(struct notifier_block *unused,
        case SWITCHDEV_FDB_ADD_TO_BRIDGE:
                fdb_info = ptr;
                err = br_fdb_external_learn_add(br, p, fdb_info->addr,
-                                               fdb_info->vid,
-                                               fdb_info->is_local, false);
+                                               fdb_info->vid, false);
                if (err) {
                        err = notifier_from_errno(err);
                        break;
index 835cec1..5dee309 100644 (file)
@@ -1044,10 +1044,7 @@ static int __br_fdb_add(struct ndmsg *ndm, struct net_bridge *br,
                                           "FDB entry towards bridge must be permanent");
                        return -EINVAL;
                }
-
-               err = br_fdb_external_learn_add(br, p, addr, vid,
-                                               ndm->ndm_state & NUD_PERMANENT,
-                                               true);
+               err = br_fdb_external_learn_add(br, p, addr, vid, true);
        } else {
                spin_lock_bh(&br->hash_lock);
                err = fdb_add_entry(br, p, addr, ndm, nlh_flags, vid, nfea_tb);
@@ -1275,7 +1272,7 @@ void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p)
 }
 
 int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
-                             const unsigned char *addr, u16 vid, bool is_local,
+                             const unsigned char *addr, u16 vid,
                              bool swdev_notify)
 {
        struct net_bridge_fdb_entry *fdb;
@@ -1293,7 +1290,7 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
                if (swdev_notify)
                        flags |= BIT(BR_FDB_ADDED_BY_USER);
 
-               if (is_local)
+               if (!p)
                        flags |= BIT(BR_FDB_LOCAL);
 
                fdb = fdb_create(br, p, addr, vid, flags);
@@ -1322,7 +1319,7 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
                if (swdev_notify)
                        set_bit(BR_FDB_ADDED_BY_USER, &fdb->flags);
 
-               if (is_local)
+               if (!p)
                        set_bit(BR_FDB_LOCAL, &fdb->flags);
 
                if (modified)
index 6e4a323..14cd6ef 100644 (file)
@@ -616,6 +616,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev,
 
        err = dev_set_allmulti(dev, 1);
        if (err) {
+               br_multicast_del_port(p);
                kfree(p);       /* kobject not yet init'd, manually free */
                goto err1;
        }
@@ -729,6 +730,7 @@ err4:
 err3:
        sysfs_remove_link(br->ifobj, p->dev->name);
 err2:
+       br_multicast_del_port(p);
        kobject_put(&p->kobj);
        dev_set_allmulti(dev, -1);
 err1:
index aa64d8d..2b48b20 100644 (file)
@@ -711,7 +711,7 @@ int br_fdb_get(struct sk_buff *skb, struct nlattr *tb[], struct net_device *dev,
 int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p);
 void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p);
 int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
-                             const unsigned char *addr, u16 vid, bool is_local,
+                             const unsigned char *addr, u16 vid,
                              bool swdev_notify);
 int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
                              const unsigned char *addr, u16 vid,
index 8d033a7..fdbed31 100644 (file)
@@ -88,6 +88,12 @@ static int nf_br_ip_fragment(struct net *net, struct sock *sk,
 
                        skb = ip_fraglist_next(&iter);
                }
+
+               if (!err)
+                       return 0;
+
+               kfree_skb_list(iter.frag);
+
                return err;
        }
 slow_path:
index 75431ca..1a45584 100644 (file)
@@ -158,7 +158,7 @@ static void linkwatch_do_dev(struct net_device *dev)
        clear_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state);
 
        rfc2863_policy(dev);
-       if (dev->flags & IFF_UP && netif_device_present(dev)) {
+       if (dev->flags & IFF_UP) {
                if (netif_carrier_ok(dev))
                        dev_activate(dev);
                else
@@ -204,7 +204,8 @@ static void __linkwatch_run_queue(int urgent_only)
                dev = list_first_entry(&wrk, struct net_device, link_watch_list);
                list_del_init(&dev->link_watch_list);
 
-               if (urgent_only && !linkwatch_urgent_event(dev)) {
+               if (!netif_device_present(dev) ||
+                   (urgent_only && !linkwatch_urgent_event(dev))) {
                        list_add_tail(&dev->link_watch_list, &lweventlist);
                        continue;
                }
index 5e4eb45..8ab7b40 100644 (file)
@@ -634,7 +634,15 @@ bool page_pool_return_skb_page(struct page *page)
        struct page_pool *pp;
 
        page = compound_head(page);
-       if (unlikely(page->pp_magic != PP_SIGNATURE))
+
+       /* page->pp_magic is OR'ed with PP_SIGNATURE after the allocation
+        * in order to preserve any existing bits, such as bit 0 for the
+        * head page of compound page and bit 1 for pfmemalloc page, so
+        * mask those bits for freeing side when doing below checking,
+        * and page_is_pfmemalloc() is checked in __page_pool_put_page()
+        * to avoid recycling the pfmemalloc page.
+        */
+       if (unlikely((page->pp_magic & ~0x3UL) != PP_SIGNATURE))
                return false;
 
        pp = page->pp;
index 9cc9d1e..c5c1d2b 100644 (file)
@@ -41,9 +41,9 @@ extern bool dccp_debug;
 #define dccp_pr_debug_cat(format, a...)   DCCP_PRINTK(dccp_debug, format, ##a)
 #define dccp_debug(fmt, a...)            dccp_pr_debug_cat(KERN_DEBUG fmt, ##a)
 #else
-#define dccp_pr_debug(format, a...)
-#define dccp_pr_debug_cat(format, a...)
-#define dccp_debug(format, a...)
+#define dccp_pr_debug(format, a...)      do {} while (0)
+#define dccp_pr_debug_cat(format, a...)          do {} while (0)
+#define dccp_debug(format, a...)         do {} while (0)
 #endif
 
 extern struct inet_hashinfo dccp_hashinfo;
index 532085d..23be8e0 100644 (file)
@@ -2291,8 +2291,8 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb,
 static void
 dsa_fdb_offload_notify(struct dsa_switchdev_event_work *switchdev_work)
 {
+       struct switchdev_notifier_fdb_info info = {};
        struct dsa_switch *ds = switchdev_work->ds;
-       struct switchdev_notifier_fdb_info info;
        struct dsa_port *dp;
 
        if (!dsa_is_user_port(ds, switchdev_work->port))
index a45a040..c25f761 100644 (file)
@@ -984,6 +984,11 @@ static const struct proto_ops ieee802154_dgram_ops = {
        .sendpage          = sock_no_sendpage,
 };
 
+static void ieee802154_sock_destruct(struct sock *sk)
+{
+       skb_queue_purge(&sk->sk_receive_queue);
+}
+
 /* Create a socket. Initialise the socket, blank the addresses
  * set the state.
  */
@@ -1024,7 +1029,7 @@ static int ieee802154_create(struct net *net, struct socket *sock,
        sock->ops = ops;
 
        sock_init_data(sock, sk);
-       /* FIXME: sk->sk_destruct */
+       sk->sk_destruct = ieee802154_sock_destruct;
        sk->sk_family = PF_IEEE802154;
 
        /* Checksums on by default */
index 6b3c558..00576ba 100644 (file)
@@ -803,10 +803,17 @@ static void igmp_gq_timer_expire(struct timer_list *t)
 static void igmp_ifc_timer_expire(struct timer_list *t)
 {
        struct in_device *in_dev = from_timer(in_dev, t, mr_ifc_timer);
+       u32 mr_ifc_count;
 
        igmpv3_send_cr(in_dev);
-       if (in_dev->mr_ifc_count) {
-               in_dev->mr_ifc_count--;
+restart:
+       mr_ifc_count = READ_ONCE(in_dev->mr_ifc_count);
+
+       if (mr_ifc_count) {
+               if (cmpxchg(&in_dev->mr_ifc_count,
+                           mr_ifc_count,
+                           mr_ifc_count - 1) != mr_ifc_count)
+                       goto restart;
                igmp_ifc_start_timer(in_dev,
                                     unsolicited_report_interval(in_dev));
        }
@@ -818,7 +825,7 @@ static void igmp_ifc_event(struct in_device *in_dev)
        struct net *net = dev_net(in_dev->dev);
        if (IGMP_V1_SEEN(in_dev) || IGMP_V2_SEEN(in_dev))
                return;
-       in_dev->mr_ifc_count = in_dev->mr_qrv ?: net->ipv4.sysctl_igmp_qrv;
+       WRITE_ONCE(in_dev->mr_ifc_count, in_dev->mr_qrv ?: net->ipv4.sysctl_igmp_qrv);
        igmp_ifc_start_timer(in_dev, 1);
 }
 
@@ -957,7 +964,7 @@ static bool igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
                                in_dev->mr_qri;
                }
                /* cancel the interface change timer */
-               in_dev->mr_ifc_count = 0;
+               WRITE_ONCE(in_dev->mr_ifc_count, 0);
                if (del_timer(&in_dev->mr_ifc_timer))
                        __in_dev_put(in_dev);
                /* clear deleted report items */
@@ -1724,7 +1731,7 @@ void ip_mc_down(struct in_device *in_dev)
                igmp_group_dropped(pmc);
 
 #ifdef CONFIG_IP_MULTICAST
-       in_dev->mr_ifc_count = 0;
+       WRITE_ONCE(in_dev->mr_ifc_count, 0);
        if (del_timer(&in_dev->mr_ifc_timer))
                __in_dev_put(in_dev);
        in_dev->mr_gq_running = 0;
@@ -1941,7 +1948,7 @@ static int ip_mc_del_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
                pmc->sfmode = MCAST_INCLUDE;
 #ifdef CONFIG_IP_MULTICAST
                pmc->crcount = in_dev->mr_qrv ?: net->ipv4.sysctl_igmp_qrv;
-               in_dev->mr_ifc_count = pmc->crcount;
+               WRITE_ONCE(in_dev->mr_ifc_count, pmc->crcount);
                for (psf = pmc->sources; psf; psf = psf->sf_next)
                        psf->sf_crcount = 0;
                igmp_ifc_event(pmc->interface);
@@ -2120,7 +2127,7 @@ static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
                /* else no filters; keep old mode for reports */
 
                pmc->crcount = in_dev->mr_qrv ?: net->ipv4.sysctl_igmp_qrv;
-               in_dev->mr_ifc_count = pmc->crcount;
+               WRITE_ONCE(in_dev->mr_ifc_count, pmc->crcount);
                for (psf = pmc->sources; psf; psf = psf->sf_next)
                        psf->sf_crcount = 0;
                igmp_ifc_event(in_dev);
index 6ea3dc2..6274462 100644 (file)
@@ -1041,7 +1041,7 @@ static void bbr_init(struct sock *sk)
        bbr->prior_cwnd = 0;
        tp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
        bbr->rtt_cnt = 0;
-       bbr->next_rtt_delivered = 0;
+       bbr->next_rtt_delivered = tp->delivered;
        bbr->prev_ca_state = TCP_CA_Open;
        bbr->packet_conservation = 0;
 
index 05f4c3c..fcae76d 100644 (file)
@@ -260,6 +260,8 @@ static void ieee80211_restart_work(struct work_struct *work)
        flush_work(&local->radar_detected_work);
 
        rtnl_lock();
+       /* we might do interface manipulations, so need both */
+       wiphy_lock(local->hw.wiphy);
 
        WARN(test_bit(SCAN_HW_SCANNING, &local->scanning),
             "%s called with hardware scan in progress\n", __func__);
index 4452455..7adcbc1 100644 (file)
@@ -885,20 +885,16 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk,
                return subflow->mp_capable;
        }
 
-       if (mp_opt->dss && mp_opt->use_ack) {
+       if ((mp_opt->dss && mp_opt->use_ack) ||
+           (mp_opt->add_addr && !mp_opt->echo)) {
                /* subflows are fully established as soon as we get any
-                * additional ack.
+                * additional ack, including ADD_ADDR.
                 */
                subflow->fully_established = 1;
                WRITE_ONCE(msk->fully_established, true);
                goto fully_established;
        }
 
-       if (mp_opt->add_addr) {
-               WRITE_ONCE(msk->fully_established, true);
-               return true;
-       }
-
        /* If the first established packet does not contain MP_CAPABLE + data
         * then fallback to TCP. Fallback scenarios requires a reset for
         * MP_JOIN subflows.
index 56263c2..7b37944 100644 (file)
@@ -1135,36 +1135,12 @@ next:
        return 0;
 }
 
-struct addr_entry_release_work {
-       struct rcu_work rwork;
-       struct mptcp_pm_addr_entry *entry;
-};
-
-static void mptcp_pm_release_addr_entry(struct work_struct *work)
+/* caller must ensure the RCU grace period is already elapsed */
+static void __mptcp_pm_release_addr_entry(struct mptcp_pm_addr_entry *entry)
 {
-       struct addr_entry_release_work *w;
-       struct mptcp_pm_addr_entry *entry;
-
-       w = container_of(to_rcu_work(work), struct addr_entry_release_work, rwork);
-       entry = w->entry;
-       if (entry) {
-               if (entry->lsk)
-                       sock_release(entry->lsk);
-               kfree(entry);
-       }
-       kfree(w);
-}
-
-static void mptcp_pm_free_addr_entry(struct mptcp_pm_addr_entry *entry)
-{
-       struct addr_entry_release_work *w;
-
-       w = kmalloc(sizeof(*w), GFP_ATOMIC);
-       if (w) {
-               INIT_RCU_WORK(&w->rwork, mptcp_pm_release_addr_entry);
-               w->entry = entry;
-               queue_rcu_work(system_wq, &w->rwork);
-       }
+       if (entry->lsk)
+               sock_release(entry->lsk);
+       kfree(entry);
 }
 
 static int mptcp_nl_remove_id_zero_address(struct net *net,
@@ -1244,7 +1220,8 @@ static int mptcp_nl_cmd_del_addr(struct sk_buff *skb, struct genl_info *info)
        spin_unlock_bh(&pernet->lock);
 
        mptcp_nl_remove_subflow_and_signal_addr(sock_net(skb->sk), &entry->addr);
-       mptcp_pm_free_addr_entry(entry);
+       synchronize_rcu();
+       __mptcp_pm_release_addr_entry(entry);
 
        return ret;
 }
@@ -1297,6 +1274,7 @@ static void mptcp_nl_remove_addrs_list(struct net *net,
        }
 }
 
+/* caller must ensure the RCU grace period is already elapsed */
 static void __flush_addrs(struct list_head *list)
 {
        while (!list_empty(list)) {
@@ -1305,7 +1283,7 @@ static void __flush_addrs(struct list_head *list)
                cur = list_entry(list->next,
                                 struct mptcp_pm_addr_entry, list);
                list_del_rcu(&cur->list);
-               mptcp_pm_free_addr_entry(cur);
+               __mptcp_pm_release_addr_entry(cur);
        }
 }
 
@@ -1329,6 +1307,7 @@ static int mptcp_nl_cmd_flush_addrs(struct sk_buff *skb, struct genl_info *info)
        bitmap_zero(pernet->id_bitmap, MAX_ADDR_ID + 1);
        spin_unlock_bh(&pernet->lock);
        mptcp_nl_remove_addrs_list(sock_net(skb->sk), &free_list);
+       synchronize_rcu();
        __flush_addrs(&free_list);
        return 0;
 }
@@ -1939,7 +1918,8 @@ static void __net_exit pm_nl_exit_net(struct list_head *net_list)
                struct pm_nl_pernet *pernet = net_generic(net, pm_nl_pernet_id);
 
                /* net is removed from namespace list, can't race with
-                * other modifiers
+                * other modifiers, also netns core already waited for a
+                * RCU grace period.
                 */
                __flush_addrs(&pernet->local_addr_list);
        }
index d1bef23..dd30c03 100644 (file)
@@ -132,8 +132,11 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
                if (ret)
                        return ret;
-               if (ip > ip_to)
+               if (ip > ip_to) {
+                       if (ip_to == 0)
+                               return -IPSET_ERR_HASH_ELEM;
                        swap(ip, ip_to);
+               }
        } else if (tb[IPSET_ATTR_CIDR]) {
                u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
 
@@ -144,6 +147,10 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
 
        hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);
 
+       /* 64bit division is not allowed on 32bit */
+       if (((u64)ip_to - ip + 1) >> (32 - h->netmask) > IPSET_MAX_RANGE)
+               return -ERANGE;
+
        if (retried) {
                ip = ntohl(h->next.ip);
                e.ip = htonl(ip);
index 18346d1..153de34 100644 (file)
@@ -121,6 +121,8 @@ hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[],
 
        e.mark = ntohl(nla_get_be32(tb[IPSET_ATTR_MARK]));
        e.mark &= h->markmask;
+       if (e.mark == 0 && e.ip == 0)
+               return -IPSET_ERR_HASH_ELEM;
 
        if (adt == IPSET_TEST ||
            !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR])) {
@@ -133,8 +135,11 @@ hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[],
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
                if (ret)
                        return ret;
-               if (ip > ip_to)
+               if (ip > ip_to) {
+                       if (e.mark == 0 && ip_to == 0)
+                               return -IPSET_ERR_HASH_ELEM;
                        swap(ip, ip_to);
+               }
        } else if (tb[IPSET_ATTR_CIDR]) {
                u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
 
@@ -143,6 +148,9 @@ hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[],
                ip_set_mask_from_to(ip, ip_to, cidr);
        }
 
+       if (((u64)ip_to - ip + 1) > IPSET_MAX_RANGE)
+               return -ERANGE;
+
        if (retried)
                ip = ntohl(h->next.ip);
        for (; ip <= ip_to; ip++) {
index e1ca111..7303138 100644 (file)
@@ -173,6 +173,9 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
                        swap(port, port_to);
        }
 
+       if (((u64)ip_to - ip + 1)*(port_to - port + 1) > IPSET_MAX_RANGE)
+               return -ERANGE;
+
        if (retried)
                ip = ntohl(h->next.ip);
        for (; ip <= ip_to; ip++) {
index ab179e0..334fb1a 100644 (file)
@@ -180,6 +180,9 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
                        swap(port, port_to);
        }
 
+       if (((u64)ip_to - ip + 1)*(port_to - port + 1) > IPSET_MAX_RANGE)
+               return -ERANGE;
+
        if (retried)
                ip = ntohl(h->next.ip);
        for (; ip <= ip_to; ip++) {
index 8f075b4..7df94f4 100644 (file)
@@ -253,6 +253,9 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
                        swap(port, port_to);
        }
 
+       if (((u64)ip_to - ip + 1)*(port_to - port + 1) > IPSET_MAX_RANGE)
+               return -ERANGE;
+
        ip2_to = ip2_from;
        if (tb[IPSET_ATTR_IP2_TO]) {
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to);
index c1a11f0..1422739 100644 (file)
@@ -140,7 +140,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_net4_elem e = { .cidr = HOST_MASK };
        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
-       u32 ip = 0, ip_to = 0;
+       u32 ip = 0, ip_to = 0, ipn, n = 0;
        int ret;
 
        if (tb[IPSET_ATTR_LINENO])
@@ -188,6 +188,15 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
                if (ip + UINT_MAX == ip_to)
                        return -IPSET_ERR_HASH_RANGE;
        }
+       ipn = ip;
+       do {
+               ipn = ip_set_range_to_cidr(ipn, ip_to, &e.cidr);
+               n++;
+       } while (ipn++ < ip_to);
+
+       if (n > IPSET_MAX_RANGE)
+               return -ERANGE;
+
        if (retried)
                ip = ntohl(h->next.ip);
        do {
index ddd51c2..9810f5b 100644 (file)
@@ -202,7 +202,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_netiface4_elem e = { .cidr = HOST_MASK, .elem = 1 };
        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
-       u32 ip = 0, ip_to = 0;
+       u32 ip = 0, ip_to = 0, ipn, n = 0;
        int ret;
 
        if (tb[IPSET_ATTR_LINENO])
@@ -256,6 +256,14 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
        } else {
                ip_set_mask_from_to(ip, ip_to, e.cidr);
        }
+       ipn = ip;
+       do {
+               ipn = ip_set_range_to_cidr(ipn, ip_to, &e.cidr);
+               n++;
+       } while (ipn++ < ip_to);
+
+       if (n > IPSET_MAX_RANGE)
+               return -ERANGE;
 
        if (retried)
                ip = ntohl(h->next.ip);
index 6532f05..3d09eef 100644 (file)
@@ -168,7 +168,8 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
        struct hash_netnet4_elem e = { };
        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
        u32 ip = 0, ip_to = 0;
-       u32 ip2 = 0, ip2_from = 0, ip2_to = 0;
+       u32 ip2 = 0, ip2_from = 0, ip2_to = 0, ipn;
+       u64 n = 0, m = 0;
        int ret;
 
        if (tb[IPSET_ATTR_LINENO])
@@ -244,6 +245,19 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
        } else {
                ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]);
        }
+       ipn = ip;
+       do {
+               ipn = ip_set_range_to_cidr(ipn, ip_to, &e.cidr[0]);
+               n++;
+       } while (ipn++ < ip_to);
+       ipn = ip2_from;
+       do {
+               ipn = ip_set_range_to_cidr(ipn, ip2_to, &e.cidr[1]);
+               m++;
+       } while (ipn++ < ip2_to);
+
+       if (n*m > IPSET_MAX_RANGE)
+               return -ERANGE;
 
        if (retried) {
                ip = ntohl(h->next.ip[0]);
index ec1564a..09cf72e 100644 (file)
@@ -158,7 +158,8 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_netport4_elem e = { .cidr = HOST_MASK - 1 };
        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
-       u32 port, port_to, p = 0, ip = 0, ip_to = 0;
+       u32 port, port_to, p = 0, ip = 0, ip_to = 0, ipn;
+       u64 n = 0;
        bool with_ports = false;
        u8 cidr;
        int ret;
@@ -235,6 +236,14 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
        } else {
                ip_set_mask_from_to(ip, ip_to, e.cidr + 1);
        }
+       ipn = ip;
+       do {
+               ipn = ip_set_range_to_cidr(ipn, ip_to, &cidr);
+               n++;
+       } while (ipn++ < ip_to);
+
+       if (n*(port_to - port + 1) > IPSET_MAX_RANGE)
+               return -ERANGE;
 
        if (retried) {
                ip = ntohl(h->next.ip);
index 0e91d1e..19bcdb3 100644 (file)
@@ -182,7 +182,8 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
        struct hash_netportnet4_elem e = { };
        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
        u32 ip = 0, ip_to = 0, p = 0, port, port_to;
-       u32 ip2_from = 0, ip2_to = 0, ip2;
+       u32 ip2_from = 0, ip2_to = 0, ip2, ipn;
+       u64 n = 0, m = 0;
        bool with_ports = false;
        int ret;
 
@@ -284,6 +285,19 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
        } else {
                ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]);
        }
+       ipn = ip;
+       do {
+               ipn = ip_set_range_to_cidr(ipn, ip_to, &e.cidr[0]);
+               n++;
+       } while (ipn++ < ip_to);
+       ipn = ip2_from;
+       do {
+               ipn = ip_set_range_to_cidr(ipn, ip2_to, &e.cidr[1]);
+               m++;
+       } while (ipn++ < ip2_to);
+
+       if (n*m*(port_to - port + 1) > IPSET_MAX_RANGE)
+               return -ERANGE;
 
        if (retried) {
                ip = ntohl(h->next.ip[0]);
index 5c03e51..d31dbcc 100644 (file)
@@ -66,22 +66,17 @@ EXPORT_SYMBOL_GPL(nf_conntrack_hash);
 
 struct conntrack_gc_work {
        struct delayed_work     dwork;
-       u32                     last_bucket;
+       u32                     next_bucket;
        bool                    exiting;
        bool                    early_drop;
-       long                    next_gc_run;
 };
 
 static __read_mostly struct kmem_cache *nf_conntrack_cachep;
 static DEFINE_SPINLOCK(nf_conntrack_locks_all_lock);
 static __read_mostly bool nf_conntrack_locks_all;
 
-/* every gc cycle scans at most 1/GC_MAX_BUCKETS_DIV part of table */
-#define GC_MAX_BUCKETS_DIV     128u
-/* upper bound of full table scan */
-#define GC_MAX_SCAN_JIFFIES    (16u * HZ)
-/* desired ratio of entries found to be expired */
-#define GC_EVICT_RATIO 50u
+#define GC_SCAN_INTERVAL       (120u * HZ)
+#define GC_SCAN_MAX_DURATION   msecs_to_jiffies(10)
 
 static struct conntrack_gc_work conntrack_gc_work;
 
@@ -1363,17 +1358,13 @@ static bool gc_worker_can_early_drop(const struct nf_conn *ct)
 
 static void gc_worker(struct work_struct *work)
 {
-       unsigned int min_interval = max(HZ / GC_MAX_BUCKETS_DIV, 1u);
-       unsigned int i, goal, buckets = 0, expired_count = 0;
-       unsigned int nf_conntrack_max95 = 0;
+       unsigned long end_time = jiffies + GC_SCAN_MAX_DURATION;
+       unsigned int i, hashsz, nf_conntrack_max95 = 0;
+       unsigned long next_run = GC_SCAN_INTERVAL;
        struct conntrack_gc_work *gc_work;
-       unsigned int ratio, scanned = 0;
-       unsigned long next_run;
-
        gc_work = container_of(work, struct conntrack_gc_work, dwork.work);
 
-       goal = nf_conntrack_htable_size / GC_MAX_BUCKETS_DIV;
-       i = gc_work->last_bucket;
+       i = gc_work->next_bucket;
        if (gc_work->early_drop)
                nf_conntrack_max95 = nf_conntrack_max / 100u * 95u;
 
@@ -1381,15 +1372,15 @@ static void gc_worker(struct work_struct *work)
                struct nf_conntrack_tuple_hash *h;
                struct hlist_nulls_head *ct_hash;
                struct hlist_nulls_node *n;
-               unsigned int hashsz;
                struct nf_conn *tmp;
 
-               i++;
                rcu_read_lock();
 
                nf_conntrack_get_ht(&ct_hash, &hashsz);
-               if (i >= hashsz)
-                       i = 0;
+               if (i >= hashsz) {
+                       rcu_read_unlock();
+                       break;
+               }
 
                hlist_nulls_for_each_entry_rcu(h, n, &ct_hash[i], hnnode) {
                        struct nf_conntrack_net *cnet;
@@ -1397,7 +1388,6 @@ static void gc_worker(struct work_struct *work)
 
                        tmp = nf_ct_tuplehash_to_ctrack(h);
 
-                       scanned++;
                        if (test_bit(IPS_OFFLOAD_BIT, &tmp->status)) {
                                nf_ct_offload_timeout(tmp);
                                continue;
@@ -1405,7 +1395,6 @@ static void gc_worker(struct work_struct *work)
 
                        if (nf_ct_is_expired(tmp)) {
                                nf_ct_gc_expired(tmp);
-                               expired_count++;
                                continue;
                        }
 
@@ -1438,7 +1427,14 @@ static void gc_worker(struct work_struct *work)
                 */
                rcu_read_unlock();
                cond_resched();
-       } while (++buckets < goal);
+               i++;
+
+               if (time_after(jiffies, end_time) && i < hashsz) {
+                       gc_work->next_bucket = i;
+                       next_run = 0;
+                       break;
+               }
+       } while (i < hashsz);
 
        if (gc_work->exiting)
                return;
@@ -1449,40 +1445,17 @@ static void gc_worker(struct work_struct *work)
         *
         * This worker is only here to reap expired entries when system went
         * idle after a busy period.
-        *
-        * The heuristics below are supposed to balance conflicting goals:
-        *
-        * 1. Minimize time until we notice a stale entry
-        * 2. Maximize scan intervals to not waste cycles
-        *
-        * Normally, expire ratio will be close to 0.
-        *
-        * As soon as a sizeable fraction of the entries have expired
-        * increase scan frequency.
         */
-       ratio = scanned ? expired_count * 100 / scanned : 0;
-       if (ratio > GC_EVICT_RATIO) {
-               gc_work->next_gc_run = min_interval;
-       } else {
-               unsigned int max = GC_MAX_SCAN_JIFFIES / GC_MAX_BUCKETS_DIV;
-
-               BUILD_BUG_ON((GC_MAX_SCAN_JIFFIES / GC_MAX_BUCKETS_DIV) == 0);
-
-               gc_work->next_gc_run += min_interval;
-               if (gc_work->next_gc_run > max)
-                       gc_work->next_gc_run = max;
+       if (next_run) {
+               gc_work->early_drop = false;
+               gc_work->next_bucket = 0;
        }
-
-       next_run = gc_work->next_gc_run;
-       gc_work->last_bucket = i;
-       gc_work->early_drop = false;
        queue_delayed_work(system_power_efficient_wq, &gc_work->dwork, next_run);
 }
 
 static void conntrack_gc_work_init(struct conntrack_gc_work *gc_work)
 {
        INIT_DEFERRABLE_WORK(&gc_work->dwork, gc_worker);
-       gc_work->next_gc_run = HZ;
        gc_work->exiting = false;
 }
 
index 3259416..af5115e 100644 (file)
@@ -1478,7 +1478,6 @@ void nf_conntrack_tcp_init_net(struct net *net)
 
 #if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
        tn->offload_timeout = 30 * HZ;
-       tn->offload_pickup = 120 * HZ;
 #endif
 }
 
index 698fee4..f8e3c0d 100644 (file)
@@ -271,7 +271,6 @@ void nf_conntrack_udp_init_net(struct net *net)
 
 #if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
        un->offload_timeout = 30 * HZ;
-       un->offload_pickup = 30 * HZ;
 #endif
 }
 
index 214d9f9..e84b499 100644 (file)
@@ -575,7 +575,6 @@ enum nf_ct_sysctl_index {
        NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_UNACK,
 #if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
        NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD,
-       NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD_PICKUP,
 #endif
        NF_SYSCTL_CT_PROTO_TCP_LOOSE,
        NF_SYSCTL_CT_PROTO_TCP_LIBERAL,
@@ -585,7 +584,6 @@ enum nf_ct_sysctl_index {
        NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_STREAM,
 #if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
        NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD,
-       NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD_PICKUP,
 #endif
        NF_SYSCTL_CT_PROTO_TIMEOUT_ICMP,
        NF_SYSCTL_CT_PROTO_TIMEOUT_ICMPV6,
@@ -776,12 +774,6 @@ static struct ctl_table nf_ct_sysctl_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec_jiffies,
        },
-       [NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD_PICKUP] = {
-               .procname       = "nf_flowtable_tcp_pickup",
-               .maxlen         = sizeof(unsigned int),
-               .mode           = 0644,
-               .proc_handler   = proc_dointvec_jiffies,
-       },
 #endif
        [NF_SYSCTL_CT_PROTO_TCP_LOOSE] = {
                .procname       = "nf_conntrack_tcp_loose",
@@ -832,12 +824,6 @@ static struct ctl_table nf_ct_sysctl_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec_jiffies,
        },
-       [NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD_PICKUP] = {
-               .procname       = "nf_flowtable_udp_pickup",
-               .maxlen         = sizeof(unsigned int),
-               .mode           = 0644,
-               .proc_handler   = proc_dointvec_jiffies,
-       },
 #endif
        [NF_SYSCTL_CT_PROTO_TIMEOUT_ICMP] = {
                .procname       = "nf_conntrack_icmp_timeout",
@@ -1018,7 +1004,6 @@ static void nf_conntrack_standalone_init_tcp_sysctl(struct net *net,
 
 #if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
        table[NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD].data = &tn->offload_timeout;
-       table[NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD_PICKUP].data = &tn->offload_pickup;
 #endif
 
 }
@@ -1111,7 +1096,6 @@ static int nf_conntrack_standalone_init_sysctl(struct net *net)
        table[NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_STREAM].data = &un->timeouts[UDP_CT_REPLIED];
 #if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
        table[NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD].data = &un->offload_timeout;
-       table[NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD_PICKUP].data = &un->offload_pickup;
 #endif
 
        nf_conntrack_standalone_init_tcp_sysctl(net, table);
index 551976e..8788b51 100644 (file)
@@ -183,7 +183,7 @@ static void flow_offload_fixup_ct_timeout(struct nf_conn *ct)
        const struct nf_conntrack_l4proto *l4proto;
        struct net *net = nf_ct_net(ct);
        int l4num = nf_ct_protonum(ct);
-       unsigned int timeout;
+       s32 timeout;
 
        l4proto = nf_ct_l4proto_find(l4num);
        if (!l4proto)
@@ -192,15 +192,20 @@ static void flow_offload_fixup_ct_timeout(struct nf_conn *ct)
        if (l4num == IPPROTO_TCP) {
                struct nf_tcp_net *tn = nf_tcp_pernet(net);
 
-               timeout = tn->offload_pickup;
+               timeout = tn->timeouts[TCP_CONNTRACK_ESTABLISHED];
+               timeout -= tn->offload_timeout;
        } else if (l4num == IPPROTO_UDP) {
                struct nf_udp_net *tn = nf_udp_pernet(net);
 
-               timeout = tn->offload_pickup;
+               timeout = tn->timeouts[UDP_CT_REPLIED];
+               timeout -= tn->offload_timeout;
        } else {
                return;
        }
 
+       if (timeout < 0)
+               timeout = 0;
+
        if (nf_flow_timeout_delta(ct->timeout) > (__s32)timeout)
                ct->timeout = nfct_time_stamp + timeout;
 }
index 202f57d..f554e2e 100644 (file)
@@ -89,11 +89,15 @@ static int nfnl_hook_put_nft_chain_info(struct sk_buff *nlskb,
        if (!nest2)
                goto cancel_nest;
 
-       ret = nla_put_string(nlskb, NFTA_CHAIN_TABLE, chain->table->name);
+       ret = nla_put_string(nlskb, NFNLA_CHAIN_TABLE, chain->table->name);
        if (ret)
                goto cancel_nest;
 
-       ret = nla_put_string(nlskb, NFTA_CHAIN_NAME, chain->name);
+       ret = nla_put_string(nlskb, NFNLA_CHAIN_NAME, chain->name);
+       if (ret)
+               goto cancel_nest;
+
+       ret = nla_put_u8(nlskb, NFNLA_CHAIN_FAMILY, chain->table->family);
        if (ret)
                goto cancel_nest;
 
@@ -109,18 +113,19 @@ cancel_nest:
 static int nfnl_hook_dump_one(struct sk_buff *nlskb,
                              const struct nfnl_dump_hook_data *ctx,
                              const struct nf_hook_ops *ops,
-                             unsigned int seq)
+                             int family, unsigned int seq)
 {
        u16 event = nfnl_msg_type(NFNL_SUBSYS_HOOK, NFNL_MSG_HOOK_GET);
        unsigned int portid = NETLINK_CB(nlskb).portid;
        struct nlmsghdr *nlh;
        int ret = -EMSGSIZE;
+       u32 hooknum;
 #ifdef CONFIG_KALLSYMS
        char sym[KSYM_SYMBOL_LEN];
        char *module_name;
 #endif
        nlh = nfnl_msg_put(nlskb, portid, seq, event,
-                          NLM_F_MULTI, ops->pf, NFNETLINK_V0, 0);
+                          NLM_F_MULTI, family, NFNETLINK_V0, 0);
        if (!nlh)
                goto nla_put_failure;
 
@@ -135,6 +140,7 @@ static int nfnl_hook_dump_one(struct sk_buff *nlskb,
        if (module_name) {
                char *end;
 
+               *module_name = '\0';
                module_name += 2;
                end = strchr(module_name, ']');
                if (end) {
@@ -151,7 +157,12 @@ static int nfnl_hook_dump_one(struct sk_buff *nlskb,
                goto nla_put_failure;
 #endif
 
-       ret = nla_put_be32(nlskb, NFNLA_HOOK_HOOKNUM, htonl(ops->hooknum));
+       if (ops->pf == NFPROTO_INET && ops->hooknum == NF_INET_INGRESS)
+               hooknum = NF_NETDEV_INGRESS;
+       else
+               hooknum = ops->hooknum;
+
+       ret = nla_put_be32(nlskb, NFNLA_HOOK_HOOKNUM, htonl(hooknum));
        if (ret)
                goto nla_put_failure;
 
@@ -259,7 +270,8 @@ static int nfnl_hook_dump(struct sk_buff *nlskb,
        ops = nf_hook_entries_get_hook_ops(e);
 
        for (; i < e->num_hook_entries; i++) {
-               err = nfnl_hook_dump_one(nlskb, ctx, ops[i], cb->seq);
+               err = nfnl_hook_dump_one(nlskb, ctx, ops[i], family,
+                                        cb->nlh->nlmsg_seq);
                if (err)
                        break;
        }
index e586424..9713035 100644 (file)
@@ -293,14 +293,14 @@ static bool icmp6hdr_ok(struct sk_buff *skb)
 }
 
 /**
- * Parse vlan tag from vlan header.
+ * parse_vlan_tag - Parse vlan tag from vlan header.
  * @skb: skb containing frame to parse
  * @key_vh: pointer to parsed vlan tag
  * @untag_vlan: should the vlan header be removed from the frame
  *
- * Returns ERROR on memory error.
- * Returns 0 if it encounters a non-vlan or incomplete packet.
- * Returns 1 after successfully parsing vlan tag.
+ * Return: ERROR on memory error.
+ * %0 if it encounters a non-vlan or incomplete packet.
+ * %1 after successfully parsing vlan tag.
  */
 static int parse_vlan_tag(struct sk_buff *skb, struct vlan_head *key_vh,
                          bool untag_vlan)
@@ -532,6 +532,7 @@ static int parse_nsh(struct sk_buff *skb, struct sw_flow_key *key)
  *       L3 header
  * @key: output flow key
  *
+ * Return: %0 if successful, otherwise a negative errno value.
  */
 static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
 {
@@ -748,8 +749,6 @@ static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
  *
  * The caller must ensure that skb->len >= ETH_HLEN.
  *
- * Returns 0 if successful, otherwise a negative errno value.
- *
  * Initializes @skb header fields as follows:
  *
  *    - skb->mac_header: the L2 header.
@@ -764,6 +763,8 @@ static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
  *
  *    - skb->protocol: the type of the data starting at skb->network_header.
  *      Equals to key->eth.type.
+ *
+ * Return: %0 if successful, otherwise a negative errno value.
  */
 static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
 {
index 88deb5b..cf2ce58 100644 (file)
@@ -507,6 +507,7 @@ void ovs_vport_send(struct vport *vport, struct sk_buff *skb, u8 mac_proto)
        }
 
        skb->dev = vport->dev;
+       skb->tstamp = 0;
        vport->ops->send(skb);
        return;
 
index 9b6ffff..28c1b00 100644 (file)
@@ -131,9 +131,9 @@ static int rds_ib_post_reg_frmr(struct rds_ib_mr *ibmr)
                cpu_relax();
        }
 
-       ret = ib_map_mr_sg_zbva(frmr->mr, ibmr->sg, ibmr->sg_len,
+       ret = ib_map_mr_sg_zbva(frmr->mr, ibmr->sg, ibmr->sg_dma_len,
                                &off, PAGE_SIZE);
-       if (unlikely(ret != ibmr->sg_len))
+       if (unlikely(ret != ibmr->sg_dma_len))
                return ret < 0 ? ret : -EINVAL;
 
        if (cmpxchg(&frmr->fr_state,
index 7153c67..2ef4cd2 100644 (file)
@@ -273,6 +273,9 @@ static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a,
                        goto out;
        }
 
+       /* All mirred/redirected skbs should clear previous ct info */
+       nf_reset_ct(skb2);
+
        want_ingress = tcf_mirred_act_wants_ingress(m_eaction);
 
        expects_nh = want_ingress || !m_mac_header_xmit;
index 9515428..28af8b1 100644 (file)
@@ -720,7 +720,7 @@ static u32 cake_hash(struct cake_tin_data *q, const struct sk_buff *skb,
 skip_hash:
        if (flow_override)
                flow_hash = flow_override - 1;
-       else if (use_skbhash)
+       else if (use_skbhash && (flow_mode & CAKE_FLOW_FLOWS))
                flow_hash = skb->hash;
        if (host_override) {
                dsthost_hash = host_override - 1;
index 8983896..c038efc 100644 (file)
@@ -795,7 +795,7 @@ static int smc_connect_rdma(struct smc_sock *smc,
                        reason_code = SMC_CLC_DECL_NOSRVLINK;
                        goto connect_abort;
                }
-               smc->conn.lnk = link;
+               smc_switch_link_and_count(&smc->conn, link);
        }
 
        /* create send buffer and rmb */
index cd0d7c9..c160ff5 100644 (file)
@@ -917,8 +917,8 @@ static int smc_switch_cursor(struct smc_sock *smc, struct smc_cdc_tx_pend *pend,
        return rc;
 }
 
-static void smc_switch_link_and_count(struct smc_connection *conn,
-                                     struct smc_link *to_lnk)
+void smc_switch_link_and_count(struct smc_connection *conn,
+                              struct smc_link *to_lnk)
 {
        atomic_dec(&conn->lnk->conn_cnt);
        conn->lnk = to_lnk;
index 6d6fd13..c043ecd 100644 (file)
@@ -97,6 +97,7 @@ struct smc_link {
        unsigned long           *wr_tx_mask;    /* bit mask of used indexes */
        u32                     wr_tx_cnt;      /* number of WR send buffers */
        wait_queue_head_t       wr_tx_wait;     /* wait for free WR send buf */
+       atomic_t                wr_tx_refcnt;   /* tx refs to link */
 
        struct smc_wr_buf       *wr_rx_bufs;    /* WR recv payload buffers */
        struct ib_recv_wr       *wr_rx_ibs;     /* WR recv meta data */
@@ -109,6 +110,7 @@ struct smc_link {
 
        struct ib_reg_wr        wr_reg;         /* WR register memory region */
        wait_queue_head_t       wr_reg_wait;    /* wait for wr_reg result */
+       atomic_t                wr_reg_refcnt;  /* reg refs to link */
        enum smc_wr_reg_state   wr_reg_state;   /* state of wr_reg request */
 
        u8                      gid[SMC_GID_SIZE];/* gid matching used vlan id*/
@@ -444,6 +446,8 @@ void smc_core_exit(void);
 int smcr_link_init(struct smc_link_group *lgr, struct smc_link *lnk,
                   u8 link_idx, struct smc_init_info *ini);
 void smcr_link_clear(struct smc_link *lnk, bool log);
+void smc_switch_link_and_count(struct smc_connection *conn,
+                              struct smc_link *to_lnk);
 int smcr_buf_map_lgr(struct smc_link *lnk);
 int smcr_buf_reg_lgr(struct smc_link *lnk);
 void smcr_lgr_set_type(struct smc_link_group *lgr, enum smc_lgr_type new_type);
index 273eaf1..2e7560e 100644 (file)
@@ -888,6 +888,7 @@ int smc_llc_cli_add_link(struct smc_link *link, struct smc_llc_qentry *qentry)
        if (!rc)
                goto out;
 out_clear_lnk:
+       lnk_new->state = SMC_LNK_INACTIVE;
        smcr_link_clear(lnk_new, false);
 out_reject:
        smc_llc_cli_add_link_reject(qentry);
@@ -1184,6 +1185,7 @@ int smc_llc_srv_add_link(struct smc_link *link)
                goto out_err;
        return 0;
 out_err:
+       link_new->state = SMC_LNK_INACTIVE;
        smcr_link_clear(link_new, false);
        return rc;
 }
@@ -1286,10 +1288,8 @@ static void smc_llc_process_cli_delete_link(struct smc_link_group *lgr)
        del_llc->reason = 0;
        smc_llc_send_message(lnk, &qentry->msg); /* response */
 
-       if (smc_link_downing(&lnk_del->state)) {
-               if (smc_switch_conns(lgr, lnk_del, false))
-                       smc_wr_tx_wait_no_pending_sends(lnk_del);
-       }
+       if (smc_link_downing(&lnk_del->state))
+               smc_switch_conns(lgr, lnk_del, false);
        smcr_link_clear(lnk_del, true);
 
        active_links = smc_llc_active_link_count(lgr);
@@ -1805,8 +1805,6 @@ void smc_llc_link_clear(struct smc_link *link, bool log)
                                    link->smcibdev->ibdev->name, link->ibport);
        complete(&link->llc_testlink_resp);
        cancel_delayed_work_sync(&link->llc_testlink_wrk);
-       smc_wr_wakeup_reg_wait(link);
-       smc_wr_wakeup_tx_wait(link);
 }
 
 /* register a new rtoken at the remote peer (for all links) */
index 289025c..c79361d 100644 (file)
@@ -496,7 +496,7 @@ static int smc_tx_rdma_writes(struct smc_connection *conn,
 /* Wakeup sndbuf consumers from any context (IRQ or process)
  * since there is more data to transmit; usable snd_wnd as max transmit
  */
-static int smcr_tx_sndbuf_nonempty(struct smc_connection *conn)
+static int _smcr_tx_sndbuf_nonempty(struct smc_connection *conn)
 {
        struct smc_cdc_producer_flags *pflags = &conn->local_tx_ctrl.prod_flags;
        struct smc_link *link = conn->lnk;
@@ -550,6 +550,22 @@ out_unlock:
        return rc;
 }
 
+static int smcr_tx_sndbuf_nonempty(struct smc_connection *conn)
+{
+       struct smc_link *link = conn->lnk;
+       int rc = -ENOLINK;
+
+       if (!link)
+               return rc;
+
+       atomic_inc(&link->wr_tx_refcnt);
+       if (smc_link_usable(link))
+               rc = _smcr_tx_sndbuf_nonempty(conn);
+       if (atomic_dec_and_test(&link->wr_tx_refcnt))
+               wake_up_all(&link->wr_tx_wait);
+       return rc;
+}
+
 static int smcd_tx_sndbuf_nonempty(struct smc_connection *conn)
 {
        struct smc_cdc_producer_flags *pflags = &conn->local_tx_ctrl.prod_flags;
index cbc73a7..a419e9a 100644 (file)
@@ -322,9 +322,12 @@ int smc_wr_reg_send(struct smc_link *link, struct ib_mr *mr)
        if (rc)
                return rc;
 
+       atomic_inc(&link->wr_reg_refcnt);
        rc = wait_event_interruptible_timeout(link->wr_reg_wait,
                                              (link->wr_reg_state != POSTED),
                                              SMC_WR_REG_MR_WAIT_TIME);
+       if (atomic_dec_and_test(&link->wr_reg_refcnt))
+               wake_up_all(&link->wr_reg_wait);
        if (!rc) {
                /* timeout - terminate link */
                smcr_link_down_cond_sched(link);
@@ -566,10 +569,15 @@ void smc_wr_free_link(struct smc_link *lnk)
                return;
        ibdev = lnk->smcibdev->ibdev;
 
+       smc_wr_wakeup_reg_wait(lnk);
+       smc_wr_wakeup_tx_wait(lnk);
+
        if (smc_wr_tx_wait_no_pending_sends(lnk))
                memset(lnk->wr_tx_mask, 0,
                       BITS_TO_LONGS(SMC_WR_BUF_CNT) *
                                                sizeof(*lnk->wr_tx_mask));
+       wait_event(lnk->wr_reg_wait, (!atomic_read(&lnk->wr_reg_refcnt)));
+       wait_event(lnk->wr_tx_wait, (!atomic_read(&lnk->wr_tx_refcnt)));
 
        if (lnk->wr_rx_dma_addr) {
                ib_dma_unmap_single(ibdev, lnk->wr_rx_dma_addr,
@@ -728,7 +736,9 @@ int smc_wr_create_link(struct smc_link *lnk)
        memset(lnk->wr_tx_mask, 0,
               BITS_TO_LONGS(SMC_WR_BUF_CNT) * sizeof(*lnk->wr_tx_mask));
        init_waitqueue_head(&lnk->wr_tx_wait);
+       atomic_set(&lnk->wr_tx_refcnt, 0);
        init_waitqueue_head(&lnk->wr_reg_wait);
+       atomic_set(&lnk->wr_reg_refcnt, 0);
        return rc;
 
 dma_unmap:
index cf58684..1b7a487 100644 (file)
@@ -913,7 +913,7 @@ static int link_schedule_user(struct tipc_link *l, struct tipc_msg *hdr)
        skb = tipc_msg_create(SOCK_WAKEUP, 0, INT_H_SIZE, 0,
                              dnode, l->addr, dport, 0, 0);
        if (!skb)
-               return -ENOMEM;
+               return -ENOBUFS;
        msg_set_dest_droppable(buf_msg(skb), true);
        TIPC_SKB_CB(skb)->chain_imp = msg_importance(hdr);
        skb_queue_tail(&l->wakeupq, skb);
@@ -1031,7 +1031,7 @@ void tipc_link_reset(struct tipc_link *l)
  *
  * Consumes the buffer chain.
  * Messages at TIPC_SYSTEM_IMPORTANCE are always accepted
- * Return: 0 if success, or errno: -ELINKCONG, -EMSGSIZE or -ENOBUFS or -ENOMEM
+ * Return: 0 if success, or errno: -ELINKCONG, -EMSGSIZE or -ENOBUFS
  */
 int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list,
                   struct sk_buff_head *xmitq)
@@ -1089,7 +1089,7 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list,
                        if (!_skb) {
                                kfree_skb(skb);
                                __skb_queue_purge(list);
-                               return -ENOMEM;
+                               return -ENOBUFS;
                        }
                        __skb_queue_tail(transmq, skb);
                        tipc_link_set_skb_retransmit_time(skb, l);
index 75b99b7..8754bd8 100644 (file)
@@ -1518,7 +1518,7 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dlen)
 
        if (unlikely(syn && !rc)) {
                tipc_set_sk_state(sk, TIPC_CONNECTING);
-               if (timeout) {
+               if (dlen && timeout) {
                        timeout = msecs_to_jiffies(timeout);
                        tipc_wait_for_connect(sock, &timeout);
                }
index e0c2c99..4f7c99d 100644 (file)
@@ -357,11 +357,14 @@ static void virtio_vsock_event_fill(struct virtio_vsock *vsock)
 
 static void virtio_vsock_reset_sock(struct sock *sk)
 {
-       lock_sock(sk);
+       /* vmci_transport.c doesn't take sk_lock here either.  At least we're
+        * under vsock_table_lock so the sock cannot disappear while we're
+        * executing.
+        */
+
        sk->sk_state = TCP_CLOSE;
        sk->sk_err = ECONNRESET;
        sk_error_report(sk);
-       release_sock(sk);
 }
 
 static void virtio_vsock_update_guest_cid(struct virtio_vsock *vsock)
index 09533cb..9ffa9e9 100644 (file)
@@ -58,10 +58,11 @@ const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {
        [LOCKDOWN_MMIOTRACE] = "unsafe mmio",
        [LOCKDOWN_DEBUGFS] = "debugfs access",
        [LOCKDOWN_XMON_WR] = "xmon write access",
+       [LOCKDOWN_BPF_WRITE_USER] = "use of bpf to write user RAM",
        [LOCKDOWN_INTEGRITY_MAX] = "integrity",
        [LOCKDOWN_KCORE] = "/proc/kcore access",
        [LOCKDOWN_KPROBES] = "use of kprobes",
-       [LOCKDOWN_BPF_READ] = "use of bpf to read kernel RAM",
+       [LOCKDOWN_BPF_READ_KERNEL] = "use of bpf to read kernel RAM",
        [LOCKDOWN_PERF] = "unsafe use of perf",
        [LOCKDOWN_TRACEFS] = "use of tracefs",
        [LOCKDOWN_XMON_RW] = "xmon read and write access",
index 09c0e2a..71323d8 100644 (file)
@@ -251,7 +251,10 @@ static bool hw_support_mmap(struct snd_pcm_substream *substream)
 
        switch (substream->dma_buffer.dev.type) {
        case SNDRV_DMA_TYPE_UNKNOWN:
-               return false;
+               /* we can't know the device, so just assume that the driver does
+                * everything right
+                */
+               return true;
        case SNDRV_DMA_TYPE_CONTINUOUS:
        case SNDRV_DMA_TYPE_VMALLOC:
                return true;
index 0ef242f..fff18b5 100644 (file)
@@ -153,7 +153,7 @@ static int init_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream)
        struct cmp_connection *conn;
        enum cmp_direction c_dir;
        enum amdtp_stream_direction s_dir;
-       unsigned int flags = CIP_UNAWARE_SYT;
+       unsigned int flags = 0;
        int err;
 
        if (!(oxfw->quirks & SND_OXFW_QUIRK_BLOCKING_TRANSMISSION))
@@ -161,6 +161,13 @@ static int init_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream)
        else
                flags |= CIP_BLOCKING;
 
+       // OXFW 970/971 has no function to generate playback timing according to the sequence
+       // of value in syt field, thus the packet should include NO_INFO value in the field.
+       // However, some models just ignore data blocks in packet with NO_INFO for audio data
+       // processing.
+       if (!(oxfw->quirks & SND_OXFW_QUIRK_IGNORE_NO_INFO_PACKET))
+               flags |= CIP_UNAWARE_SYT;
+
        if (stream == &oxfw->tx_stream) {
                conn = &oxfw->out_conn;
                c_dir = CMP_OUTPUT;
index 84971d7..cb5b5e3 100644 (file)
@@ -159,8 +159,10 @@ static int detect_quirks(struct snd_oxfw *oxfw, const struct ieee1394_device_id
                return snd_oxfw_scs1x_add(oxfw);
        }
 
-       if (entry->vendor_id == OUI_APOGEE && entry->model_id == MODEL_DUET_FW)
-               oxfw->quirks |= SND_OXFW_QUIRK_BLOCKING_TRANSMISSION;
+       if (entry->vendor_id == OUI_APOGEE && entry->model_id == MODEL_DUET_FW) {
+               oxfw->quirks |= SND_OXFW_QUIRK_BLOCKING_TRANSMISSION |
+                               SND_OXFW_QUIRK_IGNORE_NO_INFO_PACKET;
+       }
 
        /*
         * TASCAM FireOne has physical control and requires a pair of additional
index ee47abc..c13034f 100644 (file)
@@ -42,6 +42,11 @@ enum snd_oxfw_quirk {
        SND_OXFW_QUIRK_BLOCKING_TRANSMISSION = 0x04,
        // Stanton SCS1.d and SCS1.m support unique transaction.
        SND_OXFW_QUIRK_SCS_TRANSACTION = 0x08,
+       // Apogee Duet FireWire ignores data blocks in packet with NO_INFO for audio data
+       // processing, while output level meter moves. Any value in syt field of packet takes
+       // the device to process audio data even if the value is invalid in a point of
+       // IEC 61883-1/6.
+       SND_OXFW_QUIRK_IGNORE_NO_INFO_PACKET = 0x10,
 };
 
 /* This is an arbitrary number for convinience. */
index e97d005..481d8f8 100644 (file)
@@ -3460,7 +3460,7 @@ static int cap_put_caller(struct snd_kcontrol *kcontrol,
        struct hda_gen_spec *spec = codec->spec;
        const struct hda_input_mux *imux;
        struct nid_path *path;
-       int i, adc_idx, err = 0;
+       int i, adc_idx, ret, err = 0;
 
        imux = &spec->input_mux;
        adc_idx = kcontrol->id.index;
@@ -3470,9 +3470,13 @@ static int cap_put_caller(struct snd_kcontrol *kcontrol,
                if (!path || !path->ctls[type])
                        continue;
                kcontrol->private_value = path->ctls[type];
-               err = func(kcontrol, ucontrol);
-               if (err < 0)
+               ret = func(kcontrol, ucontrol);
+               if (ret < 0) {
+                       err = ret;
                        break;
+               }
+               if (ret > 0)
+                       err = 1;
        }
        mutex_unlock(&codec->control_mutex);
        if (err >= 0 && spec->cap_sync_hook)
index 0322b28..0062c18 100644 (file)
@@ -883,10 +883,11 @@ static unsigned int azx_get_pos_skl(struct azx *chip, struct azx_dev *azx_dev)
        return azx_get_pos_posbuf(chip, azx_dev);
 }
 
-static void azx_shutdown_chip(struct azx *chip)
+static void __azx_shutdown_chip(struct azx *chip, bool skip_link_reset)
 {
        azx_stop_chip(chip);
-       azx_enter_link_reset(chip);
+       if (!skip_link_reset)
+               azx_enter_link_reset(chip);
        azx_clear_irq_pending(chip);
        display_power(chip, false);
 }
@@ -895,6 +896,11 @@ static void azx_shutdown_chip(struct azx *chip)
 static DEFINE_MUTEX(card_list_lock);
 static LIST_HEAD(card_list);
 
+static void azx_shutdown_chip(struct azx *chip)
+{
+       __azx_shutdown_chip(chip, false);
+}
+
 static void azx_add_card_list(struct azx *chip)
 {
        struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
@@ -2385,7 +2391,7 @@ static void azx_shutdown(struct pci_dev *pci)
                return;
        chip = card->private_data;
        if (chip && chip->running)
-               azx_shutdown_chip(chip);
+               __azx_shutdown_chip(chip, true);
 }
 
 /* PCI IDs */
index 21c5215..7ad689f 100644 (file)
@@ -6658,6 +6658,7 @@ enum {
        ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP,
        ALC623_FIXUP_LENOVO_THINKSTATION_P340,
        ALC255_FIXUP_ACER_HEADPHONE_AND_MIC,
+       ALC236_FIXUP_HP_LIMIT_INT_MIC_BOOST,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -8242,6 +8243,12 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC255_FIXUP_XIAOMI_HEADSET_MIC
        },
+       [ALC236_FIXUP_HP_LIMIT_INT_MIC_BOOST] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc269_fixup_limit_int_mic_boost,
+               .chained = true,
+               .chain_id = ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF,
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -8332,6 +8339,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0a2e, "Dell", ALC236_FIXUP_DELL_AIO_HEADSET_MIC),
        SND_PCI_QUIRK(0x1028, 0x0a30, "Dell", ALC236_FIXUP_DELL_AIO_HEADSET_MIC),
        SND_PCI_QUIRK(0x1028, 0x0a58, "Dell", ALC255_FIXUP_DELL_HEADSET_MIC),
+       SND_PCI_QUIRK(0x1028, 0x0a61, "Dell XPS 15 9510", ALC289_FIXUP_DUAL_SPK),
        SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
@@ -8431,13 +8439,14 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x87f4, "HP", ALC287_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x87f5, "HP", ALC287_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x87f7, "HP Spectre x360 14", ALC245_FIXUP_HP_X360_AMP),
+       SND_PCI_QUIRK(0x103c, 0x8805, "HP ProBook 650 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x880d, "HP EliteBook 830 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8846, "HP EliteBook 850 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8847, "HP EliteBook x360 830 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x884b, "HP EliteBook 840 Aero G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x884c, "HP EliteBook 840 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
-       SND_PCI_QUIRK(0x103c, 0x8862, "HP ProBook 445 G8 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
-       SND_PCI_QUIRK(0x103c, 0x8863, "HP ProBook 445 G8 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
+       SND_PCI_QUIRK(0x103c, 0x8862, "HP ProBook 445 G8 Notebook PC", ALC236_FIXUP_HP_LIMIT_INT_MIC_BOOST),
+       SND_PCI_QUIRK(0x103c, 0x8863, "HP ProBook 445 G8 Notebook PC", ALC236_FIXUP_HP_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x103c, 0x886d, "HP ZBook Fury 17.3 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
        SND_PCI_QUIRK(0x103c, 0x8870, "HP ZBook Fury 15.6 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
        SND_PCI_QUIRK(0x103c, 0x8873, "HP ZBook Studio 15.6 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
@@ -8465,6 +8474,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x1043, 0x1740, "ASUS UX430UA", ALC295_FIXUP_ASUS_DACS),
        SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK),
+       SND_PCI_QUIRK(0x1043, 0x1662, "ASUS GV301QH", ALC294_FIXUP_ASUS_DUAL_SPK),
        SND_PCI_QUIRK(0x1043, 0x1881, "ASUS Zephyrus S/M", ALC294_FIXUP_ASUS_GX502_PINS),
        SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC),
        SND_PCI_QUIRK(0x1043, 0x18f1, "Asus FX505DT", ALC256_FIXUP_ASUS_HEADSET_MIC),
index a5c1a2c..773a136 100644 (file)
@@ -1041,6 +1041,7 @@ static const struct hda_fixup via_fixups[] = {
 };
 
 static const struct snd_pci_quirk vt2002p_fixups[] = {
+       SND_PCI_QUIRK(0x1043, 0x13f7, "Asus B23E", VIA_FIXUP_POWER_SAVE),
        SND_PCI_QUIRK(0x1043, 0x1487, "Asus G75", VIA_FIXUP_ASUS_G75),
        SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST),
        SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", VIA_FIXUP_POWER_SAVE),
index 8a13462..5dcf77a 100644 (file)
@@ -36,6 +36,7 @@ config SND_SOC_COMPRESS
 
 config SND_SOC_TOPOLOGY
        bool
+       select SND_DYNAMIC_MINORS
 
 config SND_SOC_TOPOLOGY_KUNIT_TEST
        tristate "KUnit tests for SoC topology"
index 9449fb4..3c60c5f 100644 (file)
@@ -525,6 +525,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
                                | SND_SOC_DAIFMT_CBM_CFM,
                .init = cz_da7219_init,
                .dpcm_playback = 1,
+               .stop_dma_first = 1,
                .ops = &cz_da7219_play_ops,
                SND_SOC_DAILINK_REG(designware1, dlgs, platform),
        },
@@ -534,6 +535,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
                                | SND_SOC_DAIFMT_CBM_CFM,
                .dpcm_capture = 1,
+               .stop_dma_first = 1,
                .ops = &cz_da7219_cap_ops,
                SND_SOC_DAILINK_REG(designware2, dlgs, platform),
        },
@@ -543,6 +545,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
                                | SND_SOC_DAIFMT_CBM_CFM,
                .dpcm_playback = 1,
+               .stop_dma_first = 1,
                .ops = &cz_max_play_ops,
                SND_SOC_DAILINK_REG(designware3, mx, platform),
        },
@@ -553,6 +556,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
                                | SND_SOC_DAIFMT_CBM_CFM,
                .dpcm_capture = 1,
+               .stop_dma_first = 1,
                .ops = &cz_dmic0_cap_ops,
                SND_SOC_DAILINK_REG(designware3, adau, platform),
        },
@@ -563,6 +567,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
                                | SND_SOC_DAIFMT_CBM_CFM,
                .dpcm_capture = 1,
+               .stop_dma_first = 1,
                .ops = &cz_dmic1_cap_ops,
                SND_SOC_DAILINK_REG(designware2, adau, platform),
        },
index 143155a..cc1ce6f 100644 (file)
@@ -969,7 +969,7 @@ static int acp_dma_hw_params(struct snd_soc_component *component,
 
        acp_set_sram_bank_state(rtd->acp_mmio, 0, true);
        /* Save for runtime private data */
-       rtd->dma_addr = substream->dma_buffer.addr;
+       rtd->dma_addr = runtime->dma_addr;
        rtd->order = get_order(size);
 
        /* Fill the page table entries in ACP SRAM */
index 8148b0d..597d7c4 100644 (file)
@@ -286,7 +286,7 @@ static int acp3x_dma_hw_params(struct snd_soc_component *component,
                pr_err("pinfo failed\n");
        }
        size = params_buffer_bytes(params);
-       rtd->dma_addr = substream->dma_buffer.addr;
+       rtd->dma_addr = substream->runtime->dma_addr;
        rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
        config_acp3x_dma(rtd, substream->stream);
        return 0;
index bd20622..0391c28 100644 (file)
@@ -242,7 +242,7 @@ static int acp_pdm_dma_hw_params(struct snd_soc_component *component,
                return -EINVAL;
        size = params_buffer_bytes(params);
        period_bytes = params_period_bytes(params);
-       rtd->dma_addr = substream->dma_buffer.addr;
+       rtd->dma_addr = substream->runtime->dma_addr;
        rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
        config_acp_dma(rtd, substream->stream);
        init_pdm_ring_buffer(MEM_WINDOW_START, size, period_bytes,
index 19438da..7b8040e 100644 (file)
@@ -382,6 +382,8 @@ static const struct dev_pm_ops rn_acp_pm = {
        .runtime_resume =  snd_rn_acp_resume,
        .suspend = snd_rn_acp_suspend,
        .resume =       snd_rn_acp_resume,
+       .restore =      snd_rn_acp_resume,
+       .poweroff =     snd_rn_acp_suspend,
 };
 
 static void snd_rn_acp_remove(struct pci_dev *pci)
index a3b784e..db16071 100644 (file)
@@ -1559,6 +1559,7 @@ config SND_SOC_WCD934X
 config SND_SOC_WCD938X
        depends on SND_SOC_WCD938X_SDW
        tristate
+       depends on SOUNDWIRE || !SOUNDWIRE
 
 config SND_SOC_WCD938X_SDW
        tristate "WCD9380/WCD9385 Codec - SDW"
index de8b83d..7bb38c3 100644 (file)
@@ -583,7 +583,10 @@ obj-$(CONFIG_SND_SOC_WCD_MBHC)     += snd-soc-wcd-mbhc.o
 obj-$(CONFIG_SND_SOC_WCD9335)  += snd-soc-wcd9335.o
 obj-$(CONFIG_SND_SOC_WCD934X)  += snd-soc-wcd934x.o
 obj-$(CONFIG_SND_SOC_WCD938X)  += snd-soc-wcd938x.o
-obj-$(CONFIG_SND_SOC_WCD938X_SDW) += snd-soc-wcd938x-sdw.o
+ifdef CONFIG_SND_SOC_WCD938X_SDW
+# avoid link failure by forcing sdw code built-in when needed
+obj-$(CONFIG_SND_SOC_WCD938X) += snd-soc-wcd938x-sdw.o
+endif
 obj-$(CONFIG_SND_SOC_WL1273)   += snd-soc-wl1273.o
 obj-$(CONFIG_SND_SOC_WM0010)   += snd-soc-wm0010.o
 obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o
index eff013f..99c022b 100644 (file)
@@ -405,7 +405,7 @@ static const struct regmap_config cs42l42_regmap = {
        .use_single_write = true,
 };
 
-static DECLARE_TLV_DB_SCALE(adc_tlv, -9600, 100, false);
+static DECLARE_TLV_DB_SCALE(adc_tlv, -9700, 100, true);
 static DECLARE_TLV_DB_SCALE(mixer_tlv, -6300, 100, true);
 
 static const char * const cs42l42_hpf_freq_text[] = {
@@ -425,34 +425,23 @@ static SOC_ENUM_SINGLE_DECL(cs42l42_wnf3_freq_enum, CS42L42_ADC_WNF_HPF_CTL,
                            CS42L42_ADC_WNF_CF_SHIFT,
                            cs42l42_wnf3_freq_text);
 
-static const char * const cs42l42_wnf05_freq_text[] = {
-       "280Hz", "315Hz", "350Hz", "385Hz",
-       "420Hz", "455Hz", "490Hz", "525Hz"
-};
-
-static SOC_ENUM_SINGLE_DECL(cs42l42_wnf05_freq_enum, CS42L42_ADC_WNF_HPF_CTL,
-                           CS42L42_ADC_WNF_CF_SHIFT,
-                           cs42l42_wnf05_freq_text);
-
 static const struct snd_kcontrol_new cs42l42_snd_controls[] = {
        /* ADC Volume and Filter Controls */
        SOC_SINGLE("ADC Notch Switch", CS42L42_ADC_CTL,
-                               CS42L42_ADC_NOTCH_DIS_SHIFT, true, false),
+                               CS42L42_ADC_NOTCH_DIS_SHIFT, true, true),
        SOC_SINGLE("ADC Weak Force Switch", CS42L42_ADC_CTL,
                                CS42L42_ADC_FORCE_WEAK_VCM_SHIFT, true, false),
        SOC_SINGLE("ADC Invert Switch", CS42L42_ADC_CTL,
                                CS42L42_ADC_INV_SHIFT, true, false),
        SOC_SINGLE("ADC Boost Switch", CS42L42_ADC_CTL,
                                CS42L42_ADC_DIG_BOOST_SHIFT, true, false),
-       SOC_SINGLE_SX_TLV("ADC Volume", CS42L42_ADC_VOLUME,
-                               CS42L42_ADC_VOL_SHIFT, 0xA0, 0x6C, adc_tlv),
+       SOC_SINGLE_S8_TLV("ADC Volume", CS42L42_ADC_VOLUME, -97, 12, adc_tlv),
        SOC_SINGLE("ADC WNF Switch", CS42L42_ADC_WNF_HPF_CTL,
                                CS42L42_ADC_WNF_EN_SHIFT, true, false),
        SOC_SINGLE("ADC HPF Switch", CS42L42_ADC_WNF_HPF_CTL,
                                CS42L42_ADC_HPF_EN_SHIFT, true, false),
        SOC_ENUM("HPF Corner Freq", cs42l42_hpf_freq_enum),
        SOC_ENUM("WNF 3dB Freq", cs42l42_wnf3_freq_enum),
-       SOC_ENUM("WNF 05dB Freq", cs42l42_wnf05_freq_enum),
 
        /* DAC Volume and Filter Controls */
        SOC_SINGLE("DACA Invert Switch", CS42L42_DAC_CTL1,
@@ -471,8 +460,8 @@ static const struct snd_soc_dapm_widget cs42l42_dapm_widgets[] = {
        SND_SOC_DAPM_OUTPUT("HP"),
        SND_SOC_DAPM_DAC("DAC", NULL, CS42L42_PWR_CTL1, CS42L42_HP_PDN_SHIFT, 1),
        SND_SOC_DAPM_MIXER("MIXER", CS42L42_PWR_CTL1, CS42L42_MIXER_PDN_SHIFT, 1, NULL, 0),
-       SND_SOC_DAPM_AIF_IN("SDIN1", NULL, 0, CS42L42_ASP_RX_DAI0_EN, CS42L42_ASP_RX0_CH1_SHIFT, 0),
-       SND_SOC_DAPM_AIF_IN("SDIN2", NULL, 1, CS42L42_ASP_RX_DAI0_EN, CS42L42_ASP_RX0_CH2_SHIFT, 0),
+       SND_SOC_DAPM_AIF_IN("SDIN1", NULL, 0, SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_AIF_IN("SDIN2", NULL, 1, SND_SOC_NOPM, 0, 0),
 
        /* Playback Requirements */
        SND_SOC_DAPM_SUPPLY("ASP DAI0", CS42L42_PWR_CTL1, CS42L42_ASP_DAI_PDN_SHIFT, 1, NULL, 0),
@@ -630,6 +619,8 @@ static int cs42l42_pll_config(struct snd_soc_component *component)
 
        for (i = 0; i < ARRAY_SIZE(pll_ratio_table); i++) {
                if (pll_ratio_table[i].sclk == clk) {
+                       cs42l42->pll_config = i;
+
                        /* Configure the internal sample rate */
                        snd_soc_component_update_bits(component, CS42L42_MCLK_CTL,
                                        CS42L42_INTERNAL_FS_MASK,
@@ -638,14 +629,9 @@ static int cs42l42_pll_config(struct snd_soc_component *component)
                                        (pll_ratio_table[i].mclk_int !=
                                        24000000)) <<
                                        CS42L42_INTERNAL_FS_SHIFT);
-                       /* Set the MCLK src (PLL or SCLK) and the divide
-                        * ratio
-                        */
+
                        snd_soc_component_update_bits(component, CS42L42_MCLK_SRC_SEL,
-                                       CS42L42_MCLK_SRC_SEL_MASK |
                                        CS42L42_MCLKDIV_MASK,
-                                       (pll_ratio_table[i].mclk_src_sel
-                                       << CS42L42_MCLK_SRC_SEL_SHIFT) |
                                        (pll_ratio_table[i].mclk_div <<
                                        CS42L42_MCLKDIV_SHIFT));
                        /* Set up the LRCLK */
@@ -681,15 +667,6 @@ static int cs42l42_pll_config(struct snd_soc_component *component)
                                        CS42L42_FSYNC_PULSE_WIDTH_MASK,
                                        CS42L42_FRAC1_VAL(fsync - 1) <<
                                        CS42L42_FSYNC_PULSE_WIDTH_SHIFT);
-                       snd_soc_component_update_bits(component,
-                                       CS42L42_ASP_FRM_CFG,
-                                       CS42L42_ASP_5050_MASK,
-                                       CS42L42_ASP_5050_MASK);
-                       /* Set the frame delay to 1.0 SCLK clocks */
-                       snd_soc_component_update_bits(component, CS42L42_ASP_FRM_CFG,
-                                       CS42L42_ASP_FSD_MASK,
-                                       CS42L42_ASP_FSD_1_0 <<
-                                       CS42L42_ASP_FSD_SHIFT);
                        /* Set the sample rates (96k or lower) */
                        snd_soc_component_update_bits(component, CS42L42_FS_RATE_EN,
                                        CS42L42_FS_EN_MASK,
@@ -789,7 +766,18 @@ static int cs42l42_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
        /* interface format */
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_I2S:
-       case SND_SOC_DAIFMT_LEFT_J:
+               /*
+                * 5050 mode, frame starts on falling edge of LRCLK,
+                * frame delayed by 1.0 SCLKs
+                */
+               snd_soc_component_update_bits(component,
+                                             CS42L42_ASP_FRM_CFG,
+                                             CS42L42_ASP_STP_MASK |
+                                             CS42L42_ASP_5050_MASK |
+                                             CS42L42_ASP_FSD_MASK,
+                                             CS42L42_ASP_5050_MASK |
+                                             (CS42L42_ASP_FSD_1_0 <<
+                                               CS42L42_ASP_FSD_SHIFT));
                break;
        default:
                return -EINVAL;
@@ -819,6 +807,25 @@ static int cs42l42_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
        return 0;
 }
 
+static int cs42l42_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
+{
+       struct snd_soc_component *component = dai->component;
+       struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component);
+
+       /*
+        * Sample rates < 44.1 kHz would produce an out-of-range SCLK with
+        * a standard I2S frame. If the machine driver sets SCLK it must be
+        * legal.
+        */
+       if (cs42l42->sclk)
+               return 0;
+
+       /* Machine driver has not set a SCLK, limit bottom end to 44.1 kHz */
+       return snd_pcm_hw_constraint_minmax(substream->runtime,
+                                           SNDRV_PCM_HW_PARAM_RATE,
+                                           44100, 192000);
+}
+
 static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
                                struct snd_pcm_hw_params *params,
                                struct snd_soc_dai *dai)
@@ -832,6 +839,10 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
        cs42l42->srate = params_rate(params);
        cs42l42->bclk = snd_soc_params_to_bclk(params);
 
+       /* I2S frame always has 2 channels even for mono audio */
+       if (channels == 1)
+               cs42l42->bclk *= 2;
+
        switch(substream->stream) {
        case SNDRV_PCM_STREAM_CAPTURE:
                if (channels == 2) {
@@ -855,6 +866,17 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
                snd_soc_component_update_bits(component, CS42L42_ASP_RX_DAI0_CH2_AP_RES,
                                                         CS42L42_ASP_RX_CH_AP_MASK |
                                                         CS42L42_ASP_RX_CH_RES_MASK, val);
+
+               /* Channel B comes from the last active channel */
+               snd_soc_component_update_bits(component, CS42L42_SP_RX_CH_SEL,
+                                             CS42L42_SP_RX_CHB_SEL_MASK,
+                                             (channels - 1) << CS42L42_SP_RX_CHB_SEL_SHIFT);
+
+               /* Both LRCLK slots must be enabled */
+               snd_soc_component_update_bits(component, CS42L42_ASP_RX_DAI0_EN,
+                                             CS42L42_ASP_RX0_CH_EN_MASK,
+                                             BIT(CS42L42_ASP_RX0_CH1_SHIFT) |
+                                             BIT(CS42L42_ASP_RX0_CH2_SHIFT));
                break;
        default:
                break;
@@ -900,13 +922,21 @@ static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
                         */
                        regmap_multi_reg_write(cs42l42->regmap, cs42l42_to_osc_seq,
                                               ARRAY_SIZE(cs42l42_to_osc_seq));
+
+                       /* Must disconnect PLL before stopping it */
+                       snd_soc_component_update_bits(component,
+                                                     CS42L42_MCLK_SRC_SEL,
+                                                     CS42L42_MCLK_SRC_SEL_MASK,
+                                                     0);
+                       usleep_range(100, 200);
+
                        snd_soc_component_update_bits(component, CS42L42_PLL_CTL1,
                                                      CS42L42_PLL_START_MASK, 0);
                }
        } else {
                if (!cs42l42->stream_use) {
                        /* SCLK must be running before codec unmute */
-                       if ((cs42l42->bclk < 11289600) && (cs42l42->sclk < 11289600)) {
+                       if (pll_ratio_table[cs42l42->pll_config].mclk_src_sel) {
                                snd_soc_component_update_bits(component, CS42L42_PLL_CTL1,
                                                              CS42L42_PLL_START_MASK, 1);
 
@@ -927,6 +957,12 @@ static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
                                                               CS42L42_PLL_LOCK_TIMEOUT_US);
                                if (ret < 0)
                                        dev_warn(component->dev, "PLL failed to lock: %d\n", ret);
+
+                               /* PLL must be running to drive glitchless switch logic */
+                               snd_soc_component_update_bits(component,
+                                                             CS42L42_MCLK_SRC_SEL,
+                                                             CS42L42_MCLK_SRC_SEL_MASK,
+                                                             CS42L42_MCLK_SRC_SEL_MASK);
                        }
 
                        /* Mark SCLK as present, turn off internal oscillator */
@@ -960,8 +996,8 @@ static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
                         SNDRV_PCM_FMTBIT_S24_LE |\
                         SNDRV_PCM_FMTBIT_S32_LE )
 
-
 static const struct snd_soc_dai_ops cs42l42_ops = {
+       .startup        = cs42l42_dai_startup,
        .hw_params      = cs42l42_pcm_hw_params,
        .set_fmt        = cs42l42_set_dai_fmt,
        .set_sysclk     = cs42l42_set_sysclk,
index 206b3c8..8734f68 100644 (file)
 
 /* Page 0x25 Audio Port Registers */
 #define CS42L42_SP_RX_CH_SEL           (CS42L42_PAGE_25 + 0x01)
+#define CS42L42_SP_RX_CHB_SEL_SHIFT    2
+#define CS42L42_SP_RX_CHB_SEL_MASK     (3 << CS42L42_SP_RX_CHB_SEL_SHIFT)
 
 #define CS42L42_SP_RX_ISOC_CTL         (CS42L42_PAGE_25 + 0x02)
 #define CS42L42_SP_RX_RSYNC_SHIFT      6
@@ -775,6 +777,7 @@ struct  cs42l42_private {
        struct gpio_desc *reset_gpio;
        struct completion pdn_done;
        struct snd_soc_jack *jack;
+       int pll_config;
        int bclk;
        u32 sclk;
        u32 srate;
index 15bd833..db88be4 100644 (file)
@@ -828,36 +828,6 @@ static void nau8824_int_status_clear_all(struct regmap *regmap)
        }
 }
 
-static void nau8824_dapm_disable_pin(struct nau8824 *nau8824, const char *pin)
-{
-       struct snd_soc_dapm_context *dapm = nau8824->dapm;
-       const char *prefix = dapm->component->name_prefix;
-       char prefixed_pin[80];
-
-       if (prefix) {
-               snprintf(prefixed_pin, sizeof(prefixed_pin), "%s %s",
-                        prefix, pin);
-               snd_soc_dapm_disable_pin(dapm, prefixed_pin);
-       } else {
-               snd_soc_dapm_disable_pin(dapm, pin);
-       }
-}
-
-static void nau8824_dapm_enable_pin(struct nau8824 *nau8824, const char *pin)
-{
-       struct snd_soc_dapm_context *dapm = nau8824->dapm;
-       const char *prefix = dapm->component->name_prefix;
-       char prefixed_pin[80];
-
-       if (prefix) {
-               snprintf(prefixed_pin, sizeof(prefixed_pin), "%s %s",
-                        prefix, pin);
-               snd_soc_dapm_force_enable_pin(dapm, prefixed_pin);
-       } else {
-               snd_soc_dapm_force_enable_pin(dapm, pin);
-       }
-}
-
 static void nau8824_eject_jack(struct nau8824 *nau8824)
 {
        struct snd_soc_dapm_context *dapm = nau8824->dapm;
@@ -866,8 +836,8 @@ static void nau8824_eject_jack(struct nau8824 *nau8824)
        /* Clear all interruption status */
        nau8824_int_status_clear_all(regmap);
 
-       nau8824_dapm_disable_pin(nau8824, "SAR");
-       nau8824_dapm_disable_pin(nau8824, "MICBIAS");
+       snd_soc_dapm_disable_pin(dapm, "SAR");
+       snd_soc_dapm_disable_pin(dapm, "MICBIAS");
        snd_soc_dapm_sync(dapm);
 
        /* Enable the insertion interruption, disable the ejection
@@ -897,8 +867,8 @@ static void nau8824_jdet_work(struct work_struct *work)
        struct regmap *regmap = nau8824->regmap;
        int adc_value, event = 0, event_mask = 0;
 
-       nau8824_dapm_enable_pin(nau8824, "MICBIAS");
-       nau8824_dapm_enable_pin(nau8824, "SAR");
+       snd_soc_dapm_enable_pin(dapm, "MICBIAS");
+       snd_soc_dapm_enable_pin(dapm, "SAR");
        snd_soc_dapm_sync(dapm);
 
        msleep(100);
@@ -909,8 +879,8 @@ static void nau8824_jdet_work(struct work_struct *work)
        if (adc_value < HEADSET_SARADC_THD) {
                event |= SND_JACK_HEADPHONE;
 
-               nau8824_dapm_disable_pin(nau8824, "SAR");
-               nau8824_dapm_disable_pin(nau8824, "MICBIAS");
+               snd_soc_dapm_disable_pin(dapm, "SAR");
+               snd_soc_dapm_disable_pin(dapm, "MICBIAS");
                snd_soc_dapm_sync(dapm);
        } else {
                event |= SND_JACK_HEADSET;
index abcd6f4..51ecaa2 100644 (file)
@@ -44,6 +44,7 @@ static const struct reg_sequence patch_list[] = {
        {RT5682_I2C_CTRL, 0x000f},
        {RT5682_PLL2_INTERNAL, 0x8266},
        {RT5682_SAR_IL_CMD_3, 0x8365},
+       {RT5682_SAR_IL_CMD_6, 0x0180},
 };
 
 void rt5682_apply_patch_list(struct rt5682_priv *rt5682, struct device *dev)
index b504d63..52d2c96 100644 (file)
@@ -35,6 +35,9 @@
 
 #include "tlv320aic31xx.h"
 
+static int aic31xx_set_jack(struct snd_soc_component *component,
+                            struct snd_soc_jack *jack, void *data);
+
 static const struct reg_default aic31xx_reg_defaults[] = {
        { AIC31XX_CLKMUX, 0x00 },
        { AIC31XX_PLLPR, 0x11 },
@@ -1256,6 +1259,13 @@ static int aic31xx_power_on(struct snd_soc_component *component)
                return ret;
        }
 
+       /*
+        * The jack detection configuration is in the same register
+        * that is used to report jack detect status so is volatile
+        * and not covered by the cache sync, restore it separately.
+        */
+       aic31xx_set_jack(component, aic31xx->jack, NULL);
+
        return 0;
 }
 
index dcd8aeb..2e9175b 100644 (file)
@@ -682,11 +682,20 @@ static int aic32x4_set_dosr(struct snd_soc_component *component, u16 dosr)
 static int aic32x4_set_processing_blocks(struct snd_soc_component *component,
                                                u8 r_block, u8 p_block)
 {
-       if (r_block > 18 || p_block > 25)
-               return -EINVAL;
+       struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
+
+       if (aic32x4->type == AIC32X4_TYPE_TAS2505) {
+               if (r_block || p_block > 3)
+                       return -EINVAL;
 
-       snd_soc_component_write(component, AIC32X4_ADCSPB, r_block);
-       snd_soc_component_write(component, AIC32X4_DACSPB, p_block);
+               snd_soc_component_write(component, AIC32X4_DACSPB, p_block);
+       } else { /* AIC32x4 */
+               if (r_block > 18 || p_block > 25)
+                       return -EINVAL;
+
+               snd_soc_component_write(component, AIC32X4_ADCSPB, r_block);
+               snd_soc_component_write(component, AIC32X4_DACSPB, p_block);
+       }
 
        return 0;
 }
@@ -695,6 +704,7 @@ static int aic32x4_setup_clocks(struct snd_soc_component *component,
                                unsigned int sample_rate, unsigned int channels,
                                unsigned int bit_depth)
 {
+       struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
        u8 aosr;
        u16 dosr;
        u8 adc_resource_class, dac_resource_class;
@@ -721,19 +731,28 @@ static int aic32x4_setup_clocks(struct snd_soc_component *component,
                adc_resource_class = 6;
                dac_resource_class = 8;
                dosr_increment = 8;
-               aic32x4_set_processing_blocks(component, 1, 1);
+               if (aic32x4->type == AIC32X4_TYPE_TAS2505)
+                       aic32x4_set_processing_blocks(component, 0, 1);
+               else
+                       aic32x4_set_processing_blocks(component, 1, 1);
        } else if (sample_rate <= 96000) {
                aosr = 64;
                adc_resource_class = 6;
                dac_resource_class = 8;
                dosr_increment = 4;
-               aic32x4_set_processing_blocks(component, 1, 9);
+               if (aic32x4->type == AIC32X4_TYPE_TAS2505)
+                       aic32x4_set_processing_blocks(component, 0, 1);
+               else
+                       aic32x4_set_processing_blocks(component, 1, 9);
        } else if (sample_rate == 192000) {
                aosr = 32;
                adc_resource_class = 3;
                dac_resource_class = 4;
                dosr_increment = 2;
-               aic32x4_set_processing_blocks(component, 13, 19);
+               if (aic32x4->type == AIC32X4_TYPE_TAS2505)
+                       aic32x4_set_processing_blocks(component, 0, 1);
+               else
+                       aic32x4_set_processing_blocks(component, 13, 19);
        } else {
                dev_err(component->dev, "Sampling rate not supported\n");
                return -EINVAL;
index 549d982..fe15cbc 100644 (file)
@@ -747,7 +747,6 @@ static void wm_adsp2_init_debugfs(struct wm_adsp *dsp,
 static void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp)
 {
        wm_adsp_debugfs_clear(dsp);
-       debugfs_remove_recursive(dsp->debugfs_root);
 }
 #else
 static inline void wm_adsp2_init_debugfs(struct wm_adsp *dsp,
index 4124aa2..905c796 100644 (file)
@@ -127,7 +127,7 @@ static void sst_fill_alloc_params(struct snd_pcm_substream *substream,
        snd_pcm_uframes_t period_size;
        ssize_t periodbytes;
        ssize_t buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
-       u32 buffer_addr = virt_to_phys(substream->dma_buffer.area);
+       u32 buffer_addr = virt_to_phys(substream->runtime->dma_area);
 
        channels = substream->runtime->channels;
        period_size = substream->runtime->period_size;
@@ -233,7 +233,6 @@ static int sst_platform_alloc_stream(struct snd_pcm_substream *substream,
        /* set codec params and inform SST driver the same */
        sst_fill_pcm_params(substream, &param);
        sst_fill_alloc_params(substream, &alloc_params);
-       substream->runtime->dma_area = substream->dma_buffer.area;
        str_params.sparams = param;
        str_params.aparams = alloc_params;
        str_params.codec = SST_CODEC_TYPE_PCM;
index 896251d..b7b3b0b 100644 (file)
@@ -404,7 +404,7 @@ static int audio_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        /* By default dais[0] is configured for max98373 */
-       if (!strcmp(pdev->name, "sof_da7219_max98360a")) {
+       if (!strcmp(pdev->name, "sof_da7219_mx98360a")) {
                dais[0] = (struct snd_soc_dai_link) {
                        .name = "SSP1-Codec",
                        .id = 0,
index c2a5933..700a185 100644 (file)
@@ -104,8 +104,6 @@ static int kirkwood_dma_open(struct snd_soc_component *component,
        int err;
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct kirkwood_dma_data *priv = kirkwood_priv(substream);
-       const struct mbus_dram_target_info *dram;
-       unsigned long addr;
 
        snd_soc_set_runtime_hwparams(substream, &kirkwood_dma_snd_hw);
 
@@ -142,20 +140,14 @@ static int kirkwood_dma_open(struct snd_soc_component *component,
                writel((unsigned int)-1, priv->io + KIRKWOOD_ERR_MASK);
        }
 
-       dram = mv_mbus_dram_info();
-       addr = substream->dma_buffer.addr;
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                if (priv->substream_play)
                        return -EBUSY;
                priv->substream_play = substream;
-               kirkwood_dma_conf_mbus_windows(priv->io,
-                       KIRKWOOD_PLAYBACK_WIN, addr, dram);
        } else {
                if (priv->substream_rec)
                        return -EBUSY;
                priv->substream_rec = substream;
-               kirkwood_dma_conf_mbus_windows(priv->io,
-                       KIRKWOOD_RECORD_WIN, addr, dram);
        }
 
        return 0;
@@ -182,6 +174,23 @@ static int kirkwood_dma_close(struct snd_soc_component *component,
        return 0;
 }
 
+static int kirkwood_dma_hw_params(struct snd_soc_component *component,
+                                 struct snd_pcm_substream *substream,
+                                 struct snd_pcm_hw_params *params)
+{
+       struct kirkwood_dma_data *priv = kirkwood_priv(substream);
+       const struct mbus_dram_target_info *dram = mv_mbus_dram_info();
+       unsigned long addr = substream->runtime->dma_addr;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               kirkwood_dma_conf_mbus_windows(priv->io,
+                       KIRKWOOD_PLAYBACK_WIN, addr, dram);
+       else
+               kirkwood_dma_conf_mbus_windows(priv->io,
+                       KIRKWOOD_RECORD_WIN, addr, dram);
+       return 0;
+}
+
 static int kirkwood_dma_prepare(struct snd_soc_component *component,
                                struct snd_pcm_substream *substream)
 {
@@ -246,6 +255,7 @@ const struct snd_soc_component_driver kirkwood_soc_component = {
        .name           = DRV_NAME,
        .open           = kirkwood_dma_open,
        .close          = kirkwood_dma_close,
+       .hw_params      = kirkwood_dma_hw_params,
        .prepare        = kirkwood_dma_prepare,
        .pointer        = kirkwood_dma_pointer,
        .pcm_construct  = kirkwood_dma_new,
index 3a5e84e..c8dfd0d 100644 (file)
@@ -148,86 +148,75 @@ int snd_soc_component_set_bias_level(struct snd_soc_component *component,
        return soc_component_ret(component, ret);
 }
 
-static int soc_component_pin(struct snd_soc_component *component,
-                            const char *pin,
-                            int (*pin_func)(struct snd_soc_dapm_context *dapm,
-                                            const char *pin))
-{
-       struct snd_soc_dapm_context *dapm =
-               snd_soc_component_get_dapm(component);
-       char *full_name;
-       int ret;
-
-       if (!component->name_prefix) {
-               ret = pin_func(dapm, pin);
-               goto end;
-       }
-
-       full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
-       if (!full_name) {
-               ret = -ENOMEM;
-               goto end;
-       }
-
-       ret = pin_func(dapm, full_name);
-       kfree(full_name);
-end:
-       return soc_component_ret(component, ret);
-}
-
 int snd_soc_component_enable_pin(struct snd_soc_component *component,
                                 const char *pin)
 {
-       return soc_component_pin(component, pin, snd_soc_dapm_enable_pin);
+       struct snd_soc_dapm_context *dapm =
+               snd_soc_component_get_dapm(component);
+       return snd_soc_dapm_enable_pin(dapm, pin);
 }
 EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin);
 
 int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component,
                                          const char *pin)
 {
-       return soc_component_pin(component, pin, snd_soc_dapm_enable_pin_unlocked);
+       struct snd_soc_dapm_context *dapm =
+               snd_soc_component_get_dapm(component);
+       return snd_soc_dapm_enable_pin_unlocked(dapm, pin);
 }
 EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin_unlocked);
 
 int snd_soc_component_disable_pin(struct snd_soc_component *component,
                                  const char *pin)
 {
-       return soc_component_pin(component, pin, snd_soc_dapm_disable_pin);
+       struct snd_soc_dapm_context *dapm =
+               snd_soc_component_get_dapm(component);
+       return snd_soc_dapm_disable_pin(dapm, pin);
 }
 EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin);
 
 int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component,
                                           const char *pin)
 {
-       return soc_component_pin(component, pin, snd_soc_dapm_disable_pin_unlocked);
+       struct snd_soc_dapm_context *dapm = 
+               snd_soc_component_get_dapm(component);
+       return snd_soc_dapm_disable_pin_unlocked(dapm, pin);
 }
 EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin_unlocked);
 
 int snd_soc_component_nc_pin(struct snd_soc_component *component,
                             const char *pin)
 {
-       return soc_component_pin(component, pin, snd_soc_dapm_nc_pin);
+       struct snd_soc_dapm_context *dapm =
+               snd_soc_component_get_dapm(component);
+       return snd_soc_dapm_nc_pin(dapm, pin);
 }
 EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin);
 
 int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component,
                                      const char *pin)
 {
-       return soc_component_pin(component, pin, snd_soc_dapm_nc_pin_unlocked);
+       struct snd_soc_dapm_context *dapm =
+               snd_soc_component_get_dapm(component);
+       return snd_soc_dapm_nc_pin_unlocked(dapm, pin);
 }
 EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin_unlocked);
 
 int snd_soc_component_get_pin_status(struct snd_soc_component *component,
                                     const char *pin)
 {
-       return soc_component_pin(component, pin, snd_soc_dapm_get_pin_status);
+       struct snd_soc_dapm_context *dapm =
+               snd_soc_component_get_dapm(component);
+       return snd_soc_dapm_get_pin_status(dapm, pin);
 }
 EXPORT_SYMBOL_GPL(snd_soc_component_get_pin_status);
 
 int snd_soc_component_force_enable_pin(struct snd_soc_component *component,
                                       const char *pin)
 {
-       return soc_component_pin(component, pin, snd_soc_dapm_force_enable_pin);
+       struct snd_soc_dapm_context *dapm =
+               snd_soc_component_get_dapm(component);
+       return snd_soc_dapm_force_enable_pin(dapm, pin);
 }
 EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin);
 
@@ -235,7 +224,9 @@ int snd_soc_component_force_enable_pin_unlocked(
        struct snd_soc_component *component,
        const char *pin)
 {
-       return soc_component_pin(component, pin, snd_soc_dapm_force_enable_pin_unlocked);
+       struct snd_soc_dapm_context *dapm =
+               snd_soc_component_get_dapm(component);
+       return snd_soc_dapm_force_enable_pin_unlocked(dapm, pin);
 }
 EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked);
 
index 4bce89b..4447f51 100644 (file)
@@ -278,6 +278,8 @@ config SND_SOC_SOF_HDA
 
 config SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE
        tristate
+       select SOUNDWIRE_INTEL if SND_SOC_SOF_INTEL_SOUNDWIRE
+       select SND_INTEL_SOUNDWIRE_ACPI if SND_SOC_SOF_INTEL_SOUNDWIRE
 
 config SND_SOC_SOF_INTEL_SOUNDWIRE
        tristate "SOF support for SoundWire"
@@ -285,8 +287,6 @@ config SND_SOC_SOF_INTEL_SOUNDWIRE
        depends on SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE
        depends on ACPI && SOUNDWIRE
        depends on !(SOUNDWIRE=m && SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE=y)
-       select SOUNDWIRE_INTEL
-       select SND_INTEL_SOUNDWIRE_ACPI
        help
          This adds support for SoundWire with Sound Open Firmware
          for Intel(R) platforms.
index c91aa95..acfeca4 100644 (file)
@@ -107,8 +107,8 @@ void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev)
        } else {
                /* reply correct size ? */
                if (reply.hdr.size != msg->reply_size &&
-                       /* getter payload is never known upfront */
-                       !(reply.hdr.cmd & SOF_IPC_GLB_PROBE)) {
+                   /* getter payload is never known upfront */
+                   ((reply.hdr.cmd & SOF_GLB_TYPE_MASK) != SOF_IPC_GLB_PROBE)) {
                        dev_err(sdev->dev, "error: reply expected %zu got %u bytes\n",
                                msg->reply_size, reply.hdr.size);
                        ret = -EINVAL;
index e1e368f..891e6e1 100644 (file)
@@ -187,12 +187,16 @@ static int hda_sdw_probe(struct snd_sof_dev *sdev)
 int hda_sdw_startup(struct snd_sof_dev *sdev)
 {
        struct sof_intel_hda_dev *hdev;
+       struct snd_sof_pdata *pdata = sdev->pdata;
 
        hdev = sdev->pdata->hw_pdata;
 
        if (!hdev->sdw)
                return 0;
 
+       if (pdata->machine && !pdata->machine->mach_params.link_mask)
+               return 0;
+
        return sdw_intel_startup(hdev->sdw);
 }
 
@@ -1002,6 +1006,14 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev)
                        hda_mach->mach_params.dmic_num = dmic_num;
                        pdata->machine = hda_mach;
                        pdata->tplg_filename = tplg_filename;
+
+                       if (codec_num == 2) {
+                               /*
+                                * Prevent SoundWire links from starting when an external
+                                * HDaudio codec is used
+                                */
+                               hda_mach->mach_params.link_mask = 0;
+                       }
                }
        }
 
index 3c1628a..3d9736e 100644 (file)
@@ -198,7 +198,7 @@ static int uniphier_aiodma_mmap(struct snd_soc_component *component,
        vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
 
        return remap_pfn_range(vma, vma->vm_start,
-                              substream->dma_buffer.addr >> PAGE_SHIFT,
+                              substream->runtime->dma_addr >> PAGE_SHIFT,
                               vma->vm_end - vma->vm_start, vma->vm_page_prot);
 }
 
index 1d59fb6..91afea9 100644 (file)
@@ -452,8 +452,8 @@ static int xlnx_formatter_pcm_hw_params(struct snd_soc_component *component,
 
        stream_data->buffer_size = size;
 
-       low = lower_32_bits(substream->dma_buffer.addr);
-       high = upper_32_bits(substream->dma_buffer.addr);
+       low = lower_32_bits(runtime->dma_addr);
+       high = upper_32_bits(runtime->dma_addr);
        writel(low, stream_data->mmio + XLNX_AUD_BUFF_ADDR_LSB);
        writel(high, stream_data->mmio + XLNX_AUD_BUFF_ADDR_MSB);
 
index 8146181..d9bd6f5 100644 (file)
@@ -131,8 +131,7 @@ static int copy_file(struct io_uring *ring, off_t insize)
        writes = reads = offset = 0;
 
        while (insize || write_left) {
-               unsigned long had_reads;
-               int got_comp;
+               int had_reads, got_comp;
 
                /*
                 * Queue up as many reads as we can
@@ -174,8 +173,13 @@ static int copy_file(struct io_uring *ring, off_t insize)
                        if (!got_comp) {
                                ret = io_uring_wait_cqe(ring, &cqe);
                                got_comp = 1;
-                       } else
+                       } else {
                                ret = io_uring_peek_cqe(ring, &cqe);
+                               if (ret == -EAGAIN) {
+                                       cqe = NULL;
+                                       ret = 0;
+                               }
+                       }
                        if (ret < 0) {
                                fprintf(stderr, "io_uring_peek_cqe: %s\n",
                                                        strerror(-ret));
@@ -194,7 +198,7 @@ static int copy_file(struct io_uring *ring, off_t insize)
                                fprintf(stderr, "cqe failed: %s\n",
                                                strerror(-cqe->res));
                                return 1;
-                       } else if ((size_t) cqe->res != data->iov.iov_len) {
+                       } else if (cqe->res != data->iov.iov_len) {
                                /* Short read/write, adjust and requeue */
                                data->iov.iov_base += cqe->res;
                                data->iov.iov_len -= cqe->res;
@@ -221,6 +225,25 @@ static int copy_file(struct io_uring *ring, off_t insize)
                }
        }
 
+       /* wait out pending writes */
+       while (writes) {
+               struct io_data *data;
+
+               ret = io_uring_wait_cqe(ring, &cqe);
+               if (ret) {
+                       fprintf(stderr, "wait_cqe=%d\n", ret);
+                       return 1;
+               }
+               if (cqe->res < 0) {
+                       fprintf(stderr, "write res=%d\n", cqe->res);
+                       return 1;
+               }
+               data = io_uring_cqe_get_data(cqe);
+               free(data);
+               writes--;
+               io_uring_cqe_seen(ring, cqe);
+       }
+
        return 0;
 }
 
index b46760b..7ff3d5c 100644 (file)
@@ -804,6 +804,7 @@ static struct btf *btf_new(const void *data, __u32 size, struct btf *base_btf)
        btf->nr_types = 0;
        btf->start_id = 1;
        btf->start_str_off = 0;
+       btf->fd = -1;
 
        if (base_btf) {
                btf->base_btf = base_btf;
@@ -832,8 +833,6 @@ static struct btf *btf_new(const void *data, __u32 size, struct btf *base_btf)
        if (err)
                goto done;
 
-       btf->fd = -1;
-
 done:
        if (err) {
                btf__free(btf);
index ecaae29..cd8c703 100644 (file)
@@ -75,6 +75,9 @@ probe_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns,
        case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
                xattr.expected_attach_type = BPF_CGROUP_INET4_CONNECT;
                break;
+       case BPF_PROG_TYPE_CGROUP_SOCKOPT:
+               xattr.expected_attach_type = BPF_CGROUP_GETSOCKOPT;
+               break;
        case BPF_PROG_TYPE_SK_LOOKUP:
                xattr.expected_attach_type = BPF_SK_LOOKUP;
                break;
@@ -104,7 +107,6 @@ probe_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns,
        case BPF_PROG_TYPE_SK_REUSEPORT:
        case BPF_PROG_TYPE_FLOW_DISSECTOR:
        case BPF_PROG_TYPE_CGROUP_SYSCTL:
-       case BPF_PROG_TYPE_CGROUP_SOCKOPT:
        case BPF_PROG_TYPE_TRACING:
        case BPF_PROG_TYPE_STRUCT_OPS:
        case BPF_PROG_TYPE_EXT:
index 54f367c..b1bff5f 100644 (file)
@@ -434,7 +434,7 @@ static int nd_intel_test_finish_query(struct nfit_test *t,
                dev_dbg(dev, "%s: transition out verify\n", __func__);
                fw->state = FW_STATE_UPDATED;
                fw->missed_activate = false;
-               /* fall through */
+               fallthrough;
        case FW_STATE_UPDATED:
                nd_cmd->status = 0;
                /* bogus test version */
index 2c8935b..ee45432 100644 (file)
        .result = ACCEPT,
        .retval = 2,
 },
+{
+       "dead code: zero extension",
+       .insns = {
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4),
+       BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1),
+       BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_10, -4),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
index dee7a3d..92bbc5a 100644 (file)
@@ -55,10 +55,27 @@ static bool alloc_q1q2_ctx(const uint8_t *s, const uint8_t *m,
        return true;
 }
 
+static void reverse_bytes(void *data, int length)
+{
+       int i = 0;
+       int j = length - 1;
+       uint8_t temp;
+       uint8_t *ptr = data;
+
+       while (i < j) {
+               temp = ptr[i];
+               ptr[i] = ptr[j];
+               ptr[j] = temp;
+               i++;
+               j--;
+       }
+}
+
 static bool calc_q1q2(const uint8_t *s, const uint8_t *m, uint8_t *q1,
                      uint8_t *q2)
 {
        struct q1q2_ctx ctx;
+       int len;
 
        if (!alloc_q1q2_ctx(s, m, &ctx)) {
                fprintf(stderr, "Not enough memory for Q1Q2 calculation\n");
@@ -89,8 +106,10 @@ static bool calc_q1q2(const uint8_t *s, const uint8_t *m, uint8_t *q1,
                goto out;
        }
 
-       BN_bn2bin(ctx.q1, q1);
-       BN_bn2bin(ctx.q2, q2);
+       len = BN_bn2bin(ctx.q1, q1);
+       reverse_bytes(q1, len);
+       len = BN_bn2bin(ctx.q2, q2);
+       reverse_bytes(q2, len);
 
        free_q1q2_ctx(&ctx);
        return true;
@@ -152,22 +171,6 @@ static RSA *gen_sign_key(void)
        return key;
 }
 
-static void reverse_bytes(void *data, int length)
-{
-       int i = 0;
-       int j = length - 1;
-       uint8_t temp;
-       uint8_t *ptr = data;
-
-       while (i < j) {
-               temp = ptr[i];
-               ptr[i] = ptr[j];
-               ptr[j] = temp;
-               i++;
-               j--;
-       }
-}
-
 enum mrtags {
        MRECREATE = 0x0045544145524345,
        MREADD = 0x0000000044444145,
@@ -367,8 +370,6 @@ bool encl_measure(struct encl *encl)
        /* BE -> LE */
        reverse_bytes(sigstruct->signature, SGX_MODULUS_SIZE);
        reverse_bytes(sigstruct->modulus, SGX_MODULUS_SIZE);
-       reverse_bytes(sigstruct->q1, SGX_MODULUS_SIZE);
-       reverse_bytes(sigstruct->q2, SGX_MODULUS_SIZE);
 
        EVP_MD_CTX_destroy(ctx);
        RSA_free(key);
index b587b9a..0d7bbe4 100644 (file)
@@ -4,7 +4,8 @@ test: virtio_test vringh_test
 virtio_test: virtio_ring.o virtio_test.o
 vringh_test: vringh_test.o vringh.o virtio_ring.o
 
-CFLAGS += -g -O2 -Werror -Wall -I. -I../include/ -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE -include ../../include/linux/kconfig.h
+CFLAGS += -g -O2 -Werror -Wno-maybe-uninitialized -Wall -I. -I../include/ -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE -include ../../include/linux/kconfig.h
+LDFLAGS += -lpthread
 vpath %.c ../../drivers/virtio ../../drivers/vhost
 mod:
        ${MAKE} -C `pwd`/../.. M=`pwd`/vhost_test V=${V}
diff --git a/tools/virtio/linux/spinlock.h b/tools/virtio/linux/spinlock.h
new file mode 100644 (file)
index 0000000..028e3cd
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef SPINLOCK_H_STUB
+#define SPINLOCK_H_STUB
+
+#include <pthread.h>
+
+typedef pthread_spinlock_t  spinlock_t;
+
+static inline void spin_lock_init(spinlock_t *lock)
+{
+       int r = pthread_spin_init(lock, 0);
+       assert(!r);
+}
+
+static inline void spin_lock(spinlock_t *lock)
+{
+       int ret = pthread_spin_lock(lock);
+       assert(!ret);
+}
+
+static inline void spin_unlock(spinlock_t *lock)
+{
+       int ret = pthread_spin_unlock(lock);
+       assert(!ret);
+}
+
+static inline void spin_lock_bh(spinlock_t *lock)
+{
+       spin_lock(lock);
+}
+
+static inline void spin_unlock_bh(spinlock_t *lock)
+{
+       spin_unlock(lock);
+}
+
+static inline void spin_lock_irq(spinlock_t *lock)
+{
+       spin_lock(lock);
+}
+
+static inline void spin_unlock_irq(spinlock_t *lock)
+{
+       spin_unlock(lock);
+}
+
+static inline void spin_lock_irqsave(spinlock_t *lock, unsigned long f)
+{
+       spin_lock(lock);
+}
+
+static inline void spin_unlock_irqrestore(spinlock_t *lock, unsigned long f)
+{
+       spin_unlock(lock);
+}
+
+#endif
index 5d90254..363b982 100644 (file)
@@ -3,6 +3,7 @@
 #define LINUX_VIRTIO_H
 #include <linux/scatterlist.h>
 #include <linux/kernel.h>
+#include <linux/spinlock.h>
 
 struct device {
        void *parent;
@@ -12,6 +13,7 @@ struct virtio_device {
        struct device dev;
        u64 features;
        struct list_head vqs;
+       spinlock_t vqs_list_lock;
 };
 
 struct virtqueue {