Merge tag 'block-5.16-2021-11-19' of git://git.kernel.dk/linux-block
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 20 Nov 2021 19:05:10 +0000 (11:05 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 20 Nov 2021 19:05:10 +0000 (11:05 -0800)
Pull block fixes from Jens Axboe:

 - Flip a cap check to avoid a selinux error (Alistair)

 - Fix for a regression this merge window where we can miss a queue ref
   put (me)

 - Un-mark pstore-blk as broken, as the condition that triggered that
   change has been rectified (Kees)

 - Queue quiesce and sync fixes (Ming)

 - FUA insertion fix (Ming)

 - blk-cgroup error path put fix (Yu)

* tag 'block-5.16-2021-11-19' of git://git.kernel.dk/linux-block:
  blk-mq: don't insert FUA request with data into scheduler queue
  blk-cgroup: fix missing put device in error path from blkg_conf_pref()
  block: avoid to quiesce queue in elevator_init_mq
  Revert "mark pstore-blk as broken"
  blk-mq: cancel blk-mq dispatch work in both blk_cleanup_queue and disk_release()
  block: fix missing queue put in error path
  block: Check ADMIN before NICE for IOPRIO_CLASS_RT

327 files changed:
.mailmap
Documentation/admin-guide/laptops/thinkpad-acpi.rst
Documentation/admin-guide/sysctl/kernel.rst
Documentation/arm/marvell.rst
Documentation/bpf/index.rst
Documentation/doc-guide/sphinx.rst
Documentation/filesystems/autofs.rst
Documentation/power/energy-model.rst
Documentation/process/changes.rst
Documentation/process/submitting-patches.rst
Documentation/trace/ftrace.rst
Documentation/translations/it_IT/doc-guide/sphinx.rst
Documentation/translations/it_IT/process/changes.rst
Documentation/translations/zh_CN/doc-guide/sphinx.rst
Documentation/translations/zh_CN/process/management-style.rst
MAINTAINERS
arch/arm64/kvm/arm.c
arch/m68k/kernel/traps.c
arch/mips/bcm63xx/clk.c
arch/mips/generic/yamon-dt.c
arch/mips/kernel/syscalls/syscall_n32.tbl
arch/mips/kernel/syscalls/syscall_n64.tbl
arch/mips/kernel/syscalls/syscall_o32.tbl
arch/mips/kvm/mips.c
arch/mips/lantiq/clk.c
arch/parisc/configs/generic-32bit_defconfig
arch/parisc/include/asm/assembly.h
arch/parisc/include/asm/jump_label.h
arch/parisc/include/asm/rt_sigframe.h
arch/parisc/kernel/signal.c
arch/parisc/kernel/signal32.h
arch/parisc/kernel/syscalls/syscall.tbl
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/signal_64.c
arch/powerpc/kernel/watchdog.c
arch/powerpc/kvm/powerpc.c
arch/riscv/Makefile
arch/riscv/configs/defconfig
arch/riscv/configs/rv32_defconfig
arch/riscv/kvm/vcpu.c
arch/riscv/kvm/vcpu_sbi.c
arch/riscv/kvm/vm.c
arch/s390/Kconfig
arch/s390/Makefile
arch/s390/boot/startup.c
arch/s390/include/asm/kexec.h
arch/s390/kernel/crash_dump.c
arch/s390/kernel/ipl.c
arch/s390/kernel/machine_kexec_file.c
arch/s390/kernel/setup.c
arch/s390/kernel/syscalls/syscall.tbl
arch/s390/kernel/traps.c
arch/s390/kernel/vdso32/Makefile
arch/s390/kernel/vdso64/Makefile
arch/s390/kvm/kvm-s390.c
arch/sparc/kernel/signal_32.c
arch/sparc/kernel/windows.c
arch/x86/Kconfig
arch/x86/entry/vsyscall/vsyscall_64.c
arch/x86/hyperv/hv_init.c
arch/x86/include/asm/kvm_host.h
arch/x86/kernel/cpu/mshyperv.c
arch/x86/kernel/process.c
arch/x86/kernel/vm86_32.c
arch/x86/kvm/cpuid.c
arch/x86/kvm/hyperv.c
arch/x86/kvm/mmu/mmu.c
arch/x86/kvm/svm/sev.c
arch/x86/kvm/svm/svm.h
arch/x86/kvm/vmx/nested.c
arch/x86/kvm/vmx/vmx.h
arch/x86/kvm/x86.c
arch/x86/kvm/x86.h
arch/x86/kvm/xen.c
drivers/acpi/glue.c
drivers/acpi/internal.h
drivers/acpi/scan.c
drivers/ata/ahci.c
drivers/ata/libahci.c
drivers/ata/libata-core.c
drivers/ata/libata-sata.c
drivers/gpio/Kconfig
drivers/gpio/gpio-virtio.c
drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/include/amd_shared.h
drivers/gpu/drm/amd/pm/amdgpu_dpm.c
drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.h
drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
drivers/gpu/drm/drm_gem_cma_helper.c
drivers/gpu/drm/i915/display/icl_dsi.c
drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c
drivers/gpu/drm/scheduler/sched_main.c
drivers/gpu/drm/sun4i/Kconfig
drivers/hv/hv_balloon.c
drivers/infiniband/core/nldev.c
drivers/infiniband/core/verbs.c
drivers/infiniband/hw/hfi1/verbs.c
drivers/infiniband/hw/mlx4/main.c
drivers/net/amt.c
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
drivers/net/ethernet/asix/ax88796c_main.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
drivers/net/ethernet/dec/tulip/de4x5.c
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
drivers/net/ethernet/intel/e100.c
drivers/net/ethernet/intel/i40e/i40e.h
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
drivers/net/ethernet/intel/iavf/iavf.h
drivers/net/ethernet/intel/iavf/iavf_ethtool.c
drivers/net/ethernet/intel/iavf/iavf_main.c
drivers/net/ethernet/lantiq_etop.c
drivers/net/ethernet/marvell/mvmdio.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
drivers/net/ethernet/mellanox/mlx5/core/cmd.c
drivers/net/ethernet/mellanox/mlx5/core/cq.c
drivers/net/ethernet/mellanox/mlx5/core/debugfs.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h
drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_matcher.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h
drivers/net/ethernet/sis/sis900.c
drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/hamradio/6pack.c
drivers/net/ipa/ipa_endpoint.c
drivers/net/ipa/ipa_resource.c
drivers/net/tun.c
drivers/net/usb/r8152.c
drivers/pinctrl/pinctrl-amd.c
drivers/pinctrl/pinctrl-apple-gpio.c
drivers/pinctrl/qcom/Kconfig
drivers/pinctrl/qcom/pinctrl-sdm845.c
drivers/pinctrl/qcom/pinctrl-sm8350.c
drivers/pinctrl/ralink/pinctrl-mt7620.c
drivers/pinctrl/tegra/pinctrl-tegra.c
drivers/pinctrl/tegra/pinctrl-tegra194.c
drivers/platform/mellanox/mlxreg-lc.c
drivers/platform/x86/Kconfig
drivers/platform/x86/dell/Kconfig
drivers/platform/x86/hp_accel.c
drivers/platform/x86/samsung-laptop.c
drivers/platform/x86/think-lmi.c
drivers/platform/x86/think-lmi.h
drivers/platform/x86/thinkpad_acpi.c
drivers/powercap/dtpm_cpu.c
drivers/ptp/ptp_clockmatrix.c
drivers/ptp/ptp_ocp.c
drivers/s390/block/dasd_devmap.c
drivers/s390/char/raw3270.c
drivers/s390/cio/chp.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/scsi_transport_iscsi.c
drivers/scsi/ufs/ufshcd.c
drivers/spi/spi-cadence-quadspi.c
drivers/spi/spi-fsl-lpspi.c
drivers/spi/spi-geni-qcom.c
drivers/spi/spi.c
drivers/thermal/intel/int340x_thermal/Kconfig
drivers/thermal/thermal_core.c
drivers/video/console/sticon.c
drivers/video/fbdev/efifb.c
drivers/video/fbdev/simplefb.c
fs/attr.c
fs/btrfs/async-thread.c
fs/btrfs/disk-io.c
fs/btrfs/ioctl.c
fs/btrfs/lzo.c
fs/btrfs/scrub.c
fs/btrfs/volumes.c
fs/cifs/cifs_swn.c
fs/cifs/cifsproto.h
fs/cifs/connect.c
fs/cifs/dfs_cache.c
fs/cifs/sess.c
fs/gfs2/bmap.c
fs/gfs2/file.c
fs/gfs2/glock.c
fs/gfs2/super.c
fs/nfsd/nfs4xdr.c
fs/udf/dir.c
fs/udf/namei.c
fs/udf/super.c
include/linux/acpi.h
include/linux/bpf.h
include/linux/kvm_host.h
include/linux/kvm_types.h
include/linux/mlx5/eswitch.h
include/linux/mm_types.h
include/linux/percpu.h
include/linux/printk.h
include/linux/sched/signal.h
include/linux/sdb.h [deleted file]
include/linux/skbuff.h
include/linux/trace_events.h
include/linux/virtio_net.h
include/net/nfc/nci_core.h
include/net/page_pool.h
include/rdma/rdma_netlink.h
init/Kconfig
kernel/bpf/cgroup.c
kernel/bpf/helpers.c
kernel/bpf/syscall.c
kernel/bpf/verifier.c
kernel/entry/syscall_user_dispatch.c
kernel/printk/printk.c
kernel/signal.c
kernel/trace/bpf_trace.c
kernel/trace/trace.c
kernel/trace/trace_events_hist.c
lib/nmi_backtrace.c
lib/zstd/Makefile
lib/zstd/common/compiler.h
lib/zstd/compress/zstd_compress_superblock.c
lib/zstd/compress/zstd_opt.c
net/core/devlink.c
net/core/filter.c
net/core/page_pool.c
net/core/sock.c
net/ipv4/bpf_tcp_ca.c
net/ipv4/devinet.c
net/ipv4/tcp.c
net/ipv4/udp.c
net/ipv6/esp6.c
net/mac80211/cfg.c
net/mac80211/iface.c
net/mac80211/led.h
net/mac80211/rx.c
net/mac80211/tx.c
net/mac80211/util.c
net/mac80211/wme.c
net/nfc/core.c
net/nfc/nci/core.c
net/sched/act_mirred.c
net/smc/af_smc.c
net/smc/smc_core.c
net/tipc/crypto.c
net/tipc/link.c
net/wireless/nl80211.c
net/wireless/nl80211.h
net/wireless/util.c
net/xdp/xsk_buff_pool.c
samples/Kconfig
samples/Makefile
samples/bpf/hbm_kern.h
samples/bpf/xdp_redirect_cpu_user.c
samples/bpf/xdp_sample_user.c
samples/ftrace/Makefile
samples/ftrace/ftrace-direct-multi.c
tools/arch/x86/include/asm/cpufeatures.h
tools/arch/x86/include/uapi/asm/kvm.h
tools/bpf/runqslower/Makefile
tools/build/feature/test-all.c
tools/include/uapi/linux/kvm.h
tools/lib/bpf/bpf_gen_internal.h
tools/lib/bpf/gen_loader.c
tools/lib/bpf/libbpf.c
tools/perf/Makefile.config
tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl
tools/perf/bench/sched-messaging.c
tools/perf/builtin-report.c
tools/perf/tests/event_update.c
tools/perf/tests/sample-parsing.c
tools/perf/tests/wp.c
tools/perf/ui/hist.c
tools/perf/util/arm-spe.c
tools/perf/util/evsel.c
tools/perf/util/header.c
tools/perf/util/hist.c
tools/perf/util/hist.h
tools/perf/util/parse-events.c
tools/perf/util/sort.c
tools/perf/util/sort.h
tools/perf/util/util.c
tools/perf/util/util.h
tools/testing/selftests/bpf/Makefile
tools/testing/selftests/bpf/prog_tests/helper_restricted.c [new file with mode: 0644]
tools/testing/selftests/bpf/progs/test_helper_restricted.c [new file with mode: 0644]
tools/testing/selftests/bpf/test_verifier.c
tools/testing/selftests/bpf/verifier/helper_restricted.c [new file with mode: 0644]
tools/testing/selftests/bpf/verifier/map_in_map.c
tools/testing/selftests/gpio/Makefile
tools/testing/selftests/gpio/gpio-mockup-cdev.c
tools/testing/selftests/kvm/.gitignore
tools/testing/selftests/kvm/access_tracking_perf_test.c
tools/testing/selftests/kvm/demand_paging_test.c
tools/testing/selftests/kvm/dirty_log_perf_test.c
tools/testing/selftests/kvm/dirty_log_test.c
tools/testing/selftests/kvm/include/perf_test_util.h
tools/testing/selftests/kvm/include/test_util.h
tools/testing/selftests/kvm/kvm_page_table_test.c
tools/testing/selftests/kvm/lib/elf.c
tools/testing/selftests/kvm/lib/kvm_util.c
tools/testing/selftests/kvm/lib/perf_test_util.c
tools/testing/selftests/kvm/lib/test_util.c
tools/testing/selftests/kvm/memslot_modification_stress_test.c
tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c
tools/testing/selftests/net/forwarding/config
tools/testing/selftests/net/forwarding/tc_actions.sh
tools/testing/selftests/net/gre_gso.sh
virt/kvm/kvm_main.c

index 14314e3..6277bb2 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -71,6 +71,9 @@ Chao Yu <chao@kernel.org> <chao2.yu@samsung.com>
 Chao Yu <chao@kernel.org> <yuchao0@huawei.com>
 Chris Chiu <chris.chiu@canonical.com> <chiu@endlessm.com>
 Chris Chiu <chris.chiu@canonical.com> <chiu@endlessos.org>
+Christian Borntraeger <borntraeger@linux.ibm.com> <borntraeger@de.ibm.com>
+Christian Borntraeger <borntraeger@linux.ibm.com> <cborntra@de.ibm.com>
+Christian Borntraeger <borntraeger@linux.ibm.com> <borntrae@de.ibm.com>
 Christophe Ricard <christophe.ricard@gmail.com>
 Christoph Hellwig <hch@lst.de>
 Colin Ian King <colin.king@intel.com> <colin.king@canonical.com>
index 6721a80..475eb0e 100644 (file)
@@ -1520,15 +1520,15 @@ This sysfs attribute controls the keyboard "face" that will be shown on the
 Lenovo X1 Carbon 2nd gen (2014)'s adaptive keyboard. The value can be read
 and set.
 
-- 1 = Home mode
-- 2 = Web-browser mode
-- 3 = Web-conference mode
-- 4 = Function mode
-- 5 = Layflat mode
+- 0 = Home mode
+- 1 = Web-browser mode
+- 2 = Web-conference mode
+- 3 = Function mode
+- 4 = Layflat mode
 
 For more details about which buttons will appear depending on the mode, please
 review the laptop's user guide:
-http://www.lenovo.com/shop/americas/content/user_guides/x1carbon_2_ug_en.pdf
+https://download.lenovo.com/ibmdl/pub/pc/pccbbs/mobiles_pdf/x1carbon_2_ug_en.pdf
 
 Battery charge control
 ----------------------
index 4261620..0e486f4 100644 (file)
@@ -1099,7 +1099,7 @@ task_delayacct
 ===============
 
 Enables/disables task delay accounting (see
-:doc:`accounting/delay-accounting.rst`). Enabling this feature incurs
+Documentation/accounting/delay-accounting.rst. Enabling this feature incurs
 a small amount of overhead in the scheduler but is useful for debugging
 and performance tuning. It is required by some tools such as iotop.
 
index 8323c79..9485a5a 100644 (file)
@@ -104,6 +104,8 @@ Discovery family
 
                 Not supported by the Linux kernel.
 
+  Homepage:
+        https://web.archive.org/web/20110924171043/http://www.marvell.com/embedded-processors/discovery-innovation/
   Core:
        Feroceon 88fr571-vd ARMv5 compatible
 
@@ -120,6 +122,7 @@ EBU Armada family
         - 88F6707
         - 88F6W11
 
+    - Product infos:   https://web.archive.org/web/20141002083258/http://www.marvell.com/embedded-processors/armada-370/
     - Product Brief:   https://web.archive.org/web/20121115063038/http://www.marvell.com/embedded-processors/armada-300/assets/Marvell_ARMADA_370_SoC.pdf
     - Hardware Spec:   https://web.archive.org/web/20140617183747/http://www.marvell.com/embedded-processors/armada-300/assets/ARMADA370-datasheet.pdf
     - Functional Spec: https://web.archive.org/web/20140617183701/http://www.marvell.com/embedded-processors/armada-300/assets/ARMADA370-FunctionalSpec-datasheet.pdf
@@ -127,9 +130,29 @@ EBU Armada family
   Core:
        Sheeva ARMv7 compatible PJ4B
 
+  Armada XP Flavors:
+        - MV78230
+        - MV78260
+        - MV78460
+
+    NOTE:
+       not to be confused with the non-SMP 78xx0 SoCs
+
+    - Product infos:   https://web.archive.org/web/20150101215721/http://www.marvell.com/embedded-processors/armada-xp/
+    - Product Brief:   https://web.archive.org/web/20121021173528/http://www.marvell.com/embedded-processors/armada-xp/assets/Marvell-ArmadaXP-SoC-product%20brief.pdf
+    - Functional Spec: https://web.archive.org/web/20180829171131/http://www.marvell.com/embedded-processors/armada-xp/assets/ARMADA-XP-Functional-SpecDatasheet.pdf
+    - Hardware Specs:
+        - https://web.archive.org/web/20141127013651/http://www.marvell.com/embedded-processors/armada-xp/assets/HW_MV78230_OS.PDF
+        - https://web.archive.org/web/20141222000224/http://www.marvell.com/embedded-processors/armada-xp/assets/HW_MV78260_OS.PDF
+        - https://web.archive.org/web/20141222000230/http://www.marvell.com/embedded-processors/armada-xp/assets/HW_MV78460_OS.PDF
+
+  Core:
+       Sheeva ARMv7 compatible Dual-core or Quad-core PJ4B-MP
+
   Armada 375 Flavors:
        - 88F6720
 
+    - Product infos: https://web.archive.org/web/20140108032402/http://www.marvell.com/embedded-processors/armada-375/
     - Product Brief: https://web.archive.org/web/20131216023516/http://www.marvell.com/embedded-processors/armada-300/assets/ARMADA_375_SoC-01_product_brief.pdf
 
   Core:
@@ -162,29 +185,6 @@ EBU Armada family
   Core:
        ARM Cortex-A9
 
-  Armada XP Flavors:
-        - MV78230
-        - MV78260
-        - MV78460
-
-    NOTE:
-       not to be confused with the non-SMP 78xx0 SoCs
-
-    Product Brief:
-       https://web.archive.org/web/20121021173528/http://www.marvell.com/embedded-processors/armada-xp/assets/Marvell-ArmadaXP-SoC-product%20brief.pdf
-
-    Functional Spec:
-       https://web.archive.org/web/20180829171131/http://www.marvell.com/embedded-processors/armada-xp/assets/ARMADA-XP-Functional-SpecDatasheet.pdf
-
-    - Hardware Specs:
-
-        - https://web.archive.org/web/20141127013651/http://www.marvell.com/embedded-processors/armada-xp/assets/HW_MV78230_OS.PDF
-        - https://web.archive.org/web/20141222000224/http://www.marvell.com/embedded-processors/armada-xp/assets/HW_MV78260_OS.PDF
-        - https://web.archive.org/web/20141222000230/http://www.marvell.com/embedded-processors/armada-xp/assets/HW_MV78460_OS.PDF
-
-  Core:
-       Sheeva ARMv7 compatible Dual-core or Quad-core PJ4B-MP
-
   Linux kernel mach directory:
        arch/arm/mach-mvebu
   Linux kernel plat directory:
@@ -436,7 +436,7 @@ Berlin family (Multimedia Solutions)
   - Flavors:
        - 88DE3010, Armada 1000 (no Linux support)
                - Core:         Marvell PJ1 (ARMv5TE), Dual-core
-               - Product Brief:        http://www.marvell.com.cn/digital-entertainment/assets/armada_1000_pb.pdf
+               - Product Brief:        https://web.archive.org/web/20131103162620/http://www.marvell.com/digital-entertainment/assets/armada_1000_pb.pdf
        - 88DE3005, Armada 1500 Mini
                - Design name:  BG2CD
                - Core:         ARM Cortex-A9, PL310 L2CC
index 37f273a..610450f 100644 (file)
@@ -15,7 +15,7 @@ that goes into great technical depth about the BPF Architecture.
 libbpf
 ======
 
-Documentation/bpf/libbpf/libbpf.rst is a userspace library for loading and interacting with bpf programs.
+Documentation/bpf/libbpf/index.rst is a userspace library for loading and interacting with bpf programs.
 
 BPF Type Format (BTF)
 =====================
index ec3e71f..e445cb1 100644 (file)
@@ -27,7 +27,7 @@ Sphinx Install
 ==============
 
 The ReST markups currently used by the Documentation/ files are meant to be
-built with ``Sphinx`` version 1.3 or higher.
+built with ``Sphinx`` version 1.7 or higher.
 
 There's a script that checks for the Sphinx requirements. Please see
 :ref:`sphinx-pre-install` for further details.
@@ -43,10 +43,6 @@ or ``virtualenv``, depending on how your distribution packaged Python 3.
 
 .. note::
 
-   #) Sphinx versions below 1.5 don't work properly with Python's
-      docutils version 0.13.1 or higher. So, if you're willing to use
-      those versions, you should run ``pip install 'docutils==0.12'``.
-
    #) It is recommended to use the RTD theme for html output. Depending
       on the Sphinx version, it should be installed separately,
       with ``pip install sphinx_rtd_theme``.
@@ -55,13 +51,13 @@ or ``virtualenv``, depending on how your distribution packaged Python 3.
       those expressions are written using LaTeX notation. It needs texlive
       installed with amsfonts and amsmath in order to evaluate them.
 
-In summary, if you want to install Sphinx version 1.7.9, you should do::
+In summary, if you want to install Sphinx version 2.4.4, you should do::
 
-       $ virtualenv sphinx_1.7.9
-       $ . sphinx_1.7.9/bin/activate
-       (sphinx_1.7.9) $ pip install -r Documentation/sphinx/requirements.txt
+       $ virtualenv sphinx_2.4.4
+       $ . sphinx_2.4.4/bin/activate
+       (sphinx_2.4.4) $ pip install -r Documentation/sphinx/requirements.txt
 
-After running ``. sphinx_1.7.9/bin/activate``, the prompt will change,
+After running ``. sphinx_2.4.4/bin/activate``, the prompt will change,
 in order to indicate that you're using the new environment. If you
 open a new shell, you need to rerun this command to enter again at
 the virtual environment before building the documentation.
@@ -81,7 +77,7 @@ output.
 PDF and LaTeX builds
 --------------------
 
-Such builds are currently supported only with Sphinx versions 1.4 and higher.
+Such builds are currently supported only with Sphinx versions 2.4 and higher.
 
 For PDF and LaTeX output, you'll also need ``XeLaTeX`` version 3.14159265.
 
@@ -104,8 +100,8 @@ command line options for your distro::
        You should run:
 
                sudo dnf install -y texlive-luatex85
-               /usr/bin/virtualenv sphinx_1.7.9
-               . sphinx_1.7.9/bin/activate
+               /usr/bin/virtualenv sphinx_2.4.4
+               . sphinx_2.4.4/bin/activate
                pip install -r Documentation/sphinx/requirements.txt
 
        Can't build as 1 mandatory dependency is missing at ./scripts/sphinx-pre-install line 468.
index 681c6a4..4f49027 100644 (file)
@@ -35,7 +35,7 @@ This document describes only the kernel module and the interactions
 required with any user-space program.  Subsequent text refers to this
 as the "automount daemon" or simply "the daemon".
 
-"autofs" is a Linux kernel module with provides the "autofs"
+"autofs" is a Linux kernel module which provides the "autofs"
 filesystem type.  Several "autofs" filesystems can be mounted and they
 can each be managed separately, or all managed by the same daemon.
 
index 8a2788a..5ac62a7 100644 (file)
@@ -84,6 +84,16 @@ CONFIG_ENERGY_MODEL must be enabled to use the EM framework.
 2.2 Registration of performance domains
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+Registration of 'advanced' EM
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The 'advanced' EM gets it's name due to the fact that the driver is allowed
+to provide more precised power model. It's not limited to some implemented math
+formula in the framework (like it's in 'simple' EM case). It can better reflect
+the real power measurements performed for each performance state. Thus, this
+registration method should be preferred in case considering EM static power
+(leakage) is important.
+
 Drivers are expected to register performance domains into the EM framework by
 calling the following API::
 
@@ -103,6 +113,18 @@ to: return warning/error, stop working or panic.
 See Section 3. for an example of driver implementing this
 callback, or Section 2.4 for further documentation on this API
 
+Registration of 'simple' EM
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The 'simple' EM is registered using the framework helper function
+cpufreq_register_em_with_opp(). It implements a power model which is tight to
+math formula::
+
+       Power = C * V^2 * f
+
+The EM which is registered using this method might not reflect correctly the
+physics of a real device, e.g. when static power (leakage) is important.
+
 
 2.3 Accessing performance domains
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -138,6 +160,10 @@ or in Section 2.4
 3. Example driver
 -----------------
 
+The CPUFreq framework supports dedicated callback for registering
+the EM for a given CPU(s) 'policy' object: cpufreq_driver::register_em().
+That callback has to be implemented properly for a given driver,
+because the framework would call it at the right time during setup.
 This section provides a simple example of a CPUFreq driver registering a
 performance domain in the Energy Model framework using the (fake) 'foo'
 protocol. The driver implements an est_power() function to be provided to the
@@ -167,25 +193,22 @@ EM framework::
   20           return 0;
   21   }
   22
-  23   static int foo_cpufreq_init(struct cpufreq_policy *policy)
+  23   static void foo_cpufreq_register_em(struct cpufreq_policy *policy)
   24   {
   25           struct em_data_callback em_cb = EM_DATA_CB(est_power);
   26           struct device *cpu_dev;
-  27           int nr_opp, ret;
+  27           int nr_opp;
   28
   29           cpu_dev = get_cpu_device(cpumask_first(policy->cpus));
   30
-  31           /* Do the actual CPUFreq init work ... */
-  32           ret = do_foo_cpufreq_init(policy);
-  33           if (ret)
-  34                   return ret;
-  35
-  36           /* Find the number of OPPs for this policy */
-  37           nr_opp = foo_get_nr_opp(policy);
+  31           /* Find the number of OPPs for this policy */
+  32           nr_opp = foo_get_nr_opp(policy);
+  33
+  34           /* And register the new performance domain */
+  35           em_dev_register_perf_domain(cpu_dev, nr_opp, &em_cb, policy->cpus,
+  36                                       true);
+  37   }
   38
-  39           /* And register the new performance domain */
-  40           em_dev_register_perf_domain(cpu_dev, nr_opp, &em_cb, policy->cpus,
-  41                                       true);
-  42
-  43           return 0;
-  44   }
+  39   static struct cpufreq_driver foo_cpufreq_driver = {
+  40           .register_em = foo_cpufreq_register_em,
+  41   };
index e35ab74..b398b85 100644 (file)
@@ -54,7 +54,7 @@ mcelog                 0.6              mcelog --version
 iptables               1.4.2            iptables -V
 openssl & libcrypto    1.0.0            openssl version
 bc                     1.06.95          bc --version
-Sphinx\ [#f1]_        1.3              sphinx-build --version
+Sphinx\ [#f1]_         1.7              sphinx-build --version
 ====================== ===============  ========================================
 
 .. [#f1] Sphinx is needed only to build the Kernel documentation
index a0cc969..da085d6 100644 (file)
@@ -22,8 +22,8 @@ use it, it will make your life as a kernel developer and in general much
 easier.
 
 Some subsystems and maintainer trees have additional information about
-their workflow and expectations, see :ref:`Documentation/process/maintainer
-handbooks <maintainer_handbooks_main>`.
+their workflow and expectations, see
+:ref:`Documentation/process/maintainer-handbooks.rst <maintainer_handbooks_main>`.
 
 Obtain a current source tree
 ----------------------------
index 4e5b26f..b3166c4 100644 (file)
@@ -2442,11 +2442,10 @@ Or this simple script!
   #!/bin/bash
 
   tracefs=`sed -ne 's/^tracefs \(.*\) tracefs.*/\1/p' /proc/mounts`
-  echo nop > $tracefs/tracing/current_tracer
-  echo 0 > $tracefs/tracing/tracing_on
-  echo $$ > $tracefs/tracing/set_ftrace_pid
-  echo function > $tracefs/tracing/current_tracer
-  echo 1 > $tracefs/tracing/tracing_on
+  echo 0 > $tracefs/tracing_on
+  echo $$ > $tracefs/set_ftrace_pid
+  echo function > $tracefs/current_tracer
+  echo 1 > $tracefs/tracing_on
   exec "$@"
 
 
index 0046d75..9762452 100644 (file)
@@ -35,7 +35,7 @@ Installazione Sphinx
 ====================
 
 I marcatori ReST utilizzati nei file in Documentation/ sono pensati per essere
-processati da ``Sphinx`` nella versione 1.3 o superiore.
+processati da ``Sphinx`` nella versione 1.7 o superiore.
 
 Esiste uno script che verifica i requisiti Sphinx. Per ulteriori dettagli
 consultate :ref:`it_sphinx-pre-install`.
@@ -53,11 +53,6 @@ pacchettizzato dalla vostra distribuzione.
 
 .. note::
 
-   #) Le versioni di Sphinx inferiori alla 1.5 non funzionano bene
-      con il pacchetto Python docutils versione 0.13.1 o superiore.
-      Se volete usare queste versioni, allora dovere eseguire
-      ``pip install 'docutils==0.12'``.
-
    #) Viene raccomandato l'uso del tema RTD per la documentazione in HTML.
       A seconda della versione di Sphinx, potrebbe essere necessaria
       l'installazione tramite il comando ``pip install sphinx_rtd_theme``.
@@ -67,13 +62,13 @@ pacchettizzato dalla vostra distribuzione.
       utilizzando LaTeX. Per una corretta interpretazione, è necessario aver
       installato texlive con i pacchetti amdfonts e amsmath.
 
-Riassumendo, se volete installare la versione 1.7.9 di Sphinx dovete eseguire::
+Riassumendo, se volete installare la versione 2.4.4 di Sphinx dovete eseguire::
 
-       $ virtualenv sphinx_1.7.9
-       $ . sphinx_1.7.9/bin/activate
-       (sphinx_1.7.9) $ pip install -r Documentation/sphinx/requirements.txt
+       $ virtualenv sphinx_2.4.4
+       $ . sphinx_2.4.4/bin/activate
+       (sphinx_2.4.4) $ pip install -r Documentation/sphinx/requirements.txt
 
-Dopo aver eseguito ``. sphinx_1.7.9/bin/activate``, il prompt cambierà per
+Dopo aver eseguito ``. sphinx_2.4.4/bin/activate``, il prompt cambierà per
 indicare che state usando il nuovo ambiente. Se aprite un nuova sessione,
 prima di generare la documentazione, dovrete rieseguire questo comando per
 rientrare nell'ambiente virtuale.
@@ -94,7 +89,7 @@ Generazione in PDF e LaTeX
 --------------------------
 
 Al momento, la generazione di questi documenti è supportata solo dalle
-versioni di Sphinx superiori alla 1.4.
+versioni di Sphinx superiori alla 2.4.
 
 Per la generazione di PDF e LaTeX, avrete bisogno anche del pacchetto
 ``XeLaTeX`` nella versione 3.14159265
@@ -119,8 +114,8 @@ l'installazione::
        You should run:
 
                sudo dnf install -y texlive-luatex85
-               /usr/bin/virtualenv sphinx_1.7.9
-               . sphinx_1.7.9/bin/activate
+               /usr/bin/virtualenv sphinx_2.4.4
+               . sphinx_2.4.4/bin/activate
                pip install -r Documentation/sphinx/requirements.txt
 
        Can't build as 1 mandatory dependency is missing at ./scripts/sphinx-pre-install line 468.
index 87d0818..dc71933 100644 (file)
@@ -57,7 +57,7 @@ mcelog                 0.6                mcelog --version
 iptables               1.4.2              iptables -V
 openssl & libcrypto    1.0.0              openssl version
 bc                     1.06.95            bc --version
-Sphinx\ [#f1]_         1.3                sphinx-build --version
+Sphinx\ [#f1]_         1.7                sphinx-build --version
 ====================== =================  ========================================
 
 .. [#f1] Sphinx è necessario solo per produrre la documentazione del Kernel
index 951595c..23eac67 100644 (file)
@@ -26,7 +26,7 @@ reStructuredText文件可能包含包含来自源文件的结构化文档注释
 安装Sphinx
 ==========
 
-Documentation/ 下的ReST文件现在使用sphinx1.3或更高版本构建。
+Documentation/ 下的ReST文件现在使用sphinx1.7或更高版本构建。
 
 这有一个脚本可以检查Sphinx的依赖项。更多详细信息见
 :ref:`sphinx-pre-install_zh` 。
@@ -40,22 +40,19 @@ Documentation/ 下的ReST文件现在使用sphinx1.3或更高版本构建。
 
 .. note::
 
-   #) 低于1.5版本的Sphinx无法与Python的0.13.1或更高版本docutils一起正常工作。
-      如果您想使用这些版本,那么应该运行 ``pip install 'docutils==0.12'`` 。
-
    #) html输出建议使用RTD主题。根据Sphinx版本的不同,它应该用
       ``pip install sphinx_rtd_theme`` 单独安装。
 
    #) 一些ReST页面包含数学表达式。由于Sphinx的工作方式,这些表达式是使用 LaTeX
       编写的。它需要安装amsfonts和amsmath宏包,以便显示。
 
-总之,如您要安装Sphinx 1.7.9版本,应执行::
+总之,如您要安装Sphinx 2.4.4版本,应执行::
 
-       $ virtualenv sphinx_1.7.9
-       $ . sphinx_1.7.9/bin/activate
-       (sphinx_1.7.9) $ pip install -r Documentation/sphinx/requirements.txt
+       $ virtualenv sphinx_2.4.4
+       $ . sphinx_2.4.4/bin/activate
+       (sphinx_2.4.4) $ pip install -r Documentation/sphinx/requirements.txt
 
-在运行 ``. sphinx_1.7.9/bin/activate`` 之后,提示符将变化,以指示您正在使用新
+在运行 ``. sphinx_2.4.4/bin/activate`` 之后,提示符将变化,以指示您正在使用新
 环境。如果您打开了一个新的shell,那么在构建文档之前,您需要重新运行此命令以再
 次进入虚拟环境中。
 
@@ -71,7 +68,7 @@ Documentation/ 下的ReST文件现在使用sphinx1.3或更高版本构建。
 PDF和LaTeX构建
 --------------
 
-目前只有Sphinx 1.4及更高版本才支持这种构建。
+目前只有Sphinx 2.4及更高版本才支持这种构建。
 
 对于PDF和LaTeX输出,还需要 ``XeLaTeX`` 3.14159265版本。(译注:此版本号真实
 存在)
@@ -93,8 +90,8 @@ PDF和LaTeX构建
        You should run:
 
                sudo dnf install -y texlive-luatex85
-               /usr/bin/virtualenv sphinx_1.7.9
-               . sphinx_1.7.9/bin/activate
+               /usr/bin/virtualenv sphinx_2.4.4
+               . sphinx_2.4.4/bin/activate
                pip install -r Documentation/sphinx/requirements.txt
 
        Can't build as 1 mandatory dependency is missing at ./scripts/sphinx-pre-install line 468.
index c6a5bb2..8053ae4 100644 (file)
@@ -36,14 +36,14 @@ Linux内核管理风格
 每个人都认为管理者做决定,而且决策很重要。决定越大越痛苦,管理者就必须越高级。
 这很明显,但事实并非如此。
 
¸¸æ\88\8fç\9a\84å\90\8då­\97是 **避免** 做出决定。尤其是,如果有人告诉你“选择(a)或(b),
\9c\80é\87\8dè¦\81ç\9a\84是 **避免** 做出决定。尤其是,如果有人告诉你“选择(a)或(b),
 我们真的需要你来做决定”,你就是陷入麻烦的管理者。你管理的人比你更了解细节,
 所以如果他们来找你做技术决策,你完蛋了。你显然没有能力为他们做这个决定。
 
 (推论:如果你管理的人不比你更了解细节,你也会被搞砸,尽管原因完全不同。
 也就是说,你的工作是错的,他们应该管理你的才智)
 
\89\80以游æ\88\8fç\9a\84å\90\8då­\97是 **避免** 做出决定,至少是那些大而痛苦的决定。做一些小的
\89\80以æ\9c\80é\87\8dè¦\81ç\9a\84是 **避免** 做出决定,至少是那些大而痛苦的决定。做一些小的
 和非结果性的决定是很好的,并且使您看起来好像知道自己在做什么,所以内核管理者
 需要做的是将那些大的和痛苦的决定变成那些没有人真正关心的小事情。
 
index 7a2345c..5250298 100644 (file)
@@ -3733,7 +3733,7 @@ F:        drivers/scsi/bnx2i/
 BROADCOM BNX2X 10 GIGABIT ETHERNET DRIVER
 M:     Ariel Elior <aelior@marvell.com>
 M:     Sudarsana Kalluru <skalluru@marvell.com>
-M:     GR-everest-linux-l2@marvell.com
+M:     Manish Chopra <manishc@marvell.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/broadcom/bnx2x/
@@ -10445,7 +10445,7 @@ F:      arch/riscv/include/uapi/asm/kvm*
 F:     arch/riscv/kvm/
 
 KERNEL VIRTUAL MACHINE for s390 (KVM/s390)
-M:     Christian Borntraeger <borntraeger@de.ibm.com>
+M:     Christian Borntraeger <borntraeger@linux.ibm.com>
 M:     Janosch Frank <frankja@linux.ibm.com>
 R:     David Hildenbrand <david@redhat.com>
 R:     Claudio Imbrenda <imbrenda@linux.ibm.com>
@@ -15593,7 +15593,7 @@ F:      drivers/scsi/qedi/
 
 QLOGIC QL4xxx ETHERNET DRIVER
 M:     Ariel Elior <aelior@marvell.com>
-M:     GR-everest-linux-l2@marvell.com
+M:     Manish Chopra <manishc@marvell.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/qlogic/qed/
@@ -16573,7 +16573,7 @@ F:      drivers/video/fbdev/savage/
 S390
 M:     Heiko Carstens <hca@linux.ibm.com>
 M:     Vasily Gorbik <gor@linux.ibm.com>
-M:     Christian Borntraeger <borntraeger@de.ibm.com>
+M:     Christian Borntraeger <borntraeger@linux.ibm.com>
 R:     Alexander Gordeev <agordeev@linux.ibm.com>
 L:     linux-s390@vger.kernel.org
 S:     Supported
@@ -20317,7 +20317,8 @@ F:      arch/x86/include/asm/vmware.h
 F:     arch/x86/kernel/cpu/vmware.c
 
 VMWARE PVRDMA DRIVER
-M:     Adit Ranadive <aditr@vmware.com>
+M:     Bryan Tan <bryantan@vmware.com>
+M:     Vishnu Dasa <vdasa@vmware.com>
 M:     VMware PV-Drivers <pv-drivers@vmware.com>
 L:     linux-rdma@vger.kernel.org
 S:     Maintained
index 2f03cbf..e4727dc 100644 (file)
@@ -223,7 +223,14 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
                r = 1;
                break;
        case KVM_CAP_NR_VCPUS:
-               r = num_online_cpus();
+               /*
+                * ARM64 treats KVM_CAP_NR_CPUS differently from all other
+                * architectures, as it does not always bound it to
+                * KVM_CAP_MAX_VCPUS. It should not matter much because
+                * this is just an advisory value.
+                */
+               r = min_t(unsigned int, num_online_cpus(),
+                         kvm_arm_default_max_vcpus());
                break;
        case KVM_CAP_MAX_VCPUS:
        case KVM_CAP_MAX_VCPU_ID:
index 99058a6..34d6458 100644 (file)
@@ -1145,7 +1145,7 @@ asmlinkage void set_esp0(unsigned long ssp)
  */
 asmlinkage void fpsp040_die(void)
 {
-       force_fatal_sig(SIGSEGV);
+       force_exit_sig(SIGSEGV);
 }
 
 #ifdef CONFIG_M68KFPU_EMU
index 5a3e325..1c91064 100644 (file)
@@ -381,6 +381,12 @@ void clk_disable(struct clk *clk)
 
 EXPORT_SYMBOL(clk_disable);
 
+struct clk *clk_get_parent(struct clk *clk)
+{
+       return NULL;
+}
+EXPORT_SYMBOL(clk_get_parent);
+
 unsigned long clk_get_rate(struct clk *clk)
 {
        if (!clk)
index a3aa22c..a07a5ed 100644 (file)
@@ -75,7 +75,7 @@ static unsigned int __init gen_fdt_mem_array(
 __init int yamon_dt_append_memory(void *fdt,
                                  const struct yamon_mem_region *regions)
 {
-       unsigned long phys_memsize, memsize;
+       unsigned long phys_memsize = 0, memsize;
        __be32 mem_array[2 * MAX_MEM_ARRAY_ENTRIES];
        unsigned int mem_entries;
        int i, err, mem_off;
index 70e32de..72d02d3 100644 (file)
 446    n32     landlock_restrict_self          sys_landlock_restrict_self
 # 447 reserved for memfd_secret
 448    n32     process_mrelease                sys_process_mrelease
+449    n32     futex_waitv                     sys_futex_waitv
index 1ca7bc3..e2c481f 100644 (file)
 446    n64     landlock_restrict_self          sys_landlock_restrict_self
 # 447 reserved for memfd_secret
 448    n64     process_mrelease                sys_process_mrelease
+449    n64     futex_waitv                     sys_futex_waitv
index a61c35e..3714c97 100644 (file)
 446    o32     landlock_restrict_self          sys_landlock_restrict_self
 # 447 reserved for memfd_secret
 448    o32     process_mrelease                sys_process_mrelease
+449    o32     futex_waitv                     sys_futex_waitv
index 562aa87..aa20d07 100644 (file)
@@ -1067,7 +1067,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
                r = 1;
                break;
        case KVM_CAP_NR_VCPUS:
-               r = num_online_cpus();
+               r = min_t(unsigned int, num_online_cpus(), KVM_MAX_VCPUS);
                break;
        case KVM_CAP_MAX_VCPUS:
                r = KVM_MAX_VCPUS;
index dd819e3..4916ccc 100644 (file)
@@ -158,6 +158,12 @@ void clk_deactivate(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_deactivate);
 
+struct clk *clk_get_parent(struct clk *clk)
+{
+       return NULL;
+}
+EXPORT_SYMBOL(clk_get_parent);
+
 static inline u32 get_counter_resolution(void)
 {
        u32 res;
index d6fd8fa..53061cb 100644 (file)
@@ -231,6 +231,7 @@ CONFIG_CRYPTO_DEFLATE=y
 CONFIG_CRC_CCITT=m
 CONFIG_CRC_T10DIF=y
 CONFIG_FONTS=y
+CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_MEMORY_INIT=y
index 7085df0..39e7985 100644 (file)
@@ -3,38 +3,19 @@
  * Copyright (C) 1999 Hewlett-Packard (Frank Rowand)
  * Copyright (C) 1999 Philipp Rumpf <prumpf@tux.org>
  * Copyright (C) 1999 SuSE GmbH
+ * Copyright (C) 2021 Helge Deller <deller@gmx.de>
  */
 
 #ifndef _PARISC_ASSEMBLY_H
 #define _PARISC_ASSEMBLY_H
 
-#define CALLEE_FLOAT_FRAME_SIZE        80
-
 #ifdef CONFIG_64BIT
-#define LDREG  ldd
-#define STREG  std
-#define LDREGX  ldd,s
-#define LDREGM ldd,mb
-#define STREGM std,ma
-#define SHRREG shrd
-#define SHLREG shld
-#define ANDCM   andcm,*
-#define        COND(x) * ## x
 #define RP_OFFSET      16
 #define FRAME_SIZE     128
 #define CALLEE_REG_FRAME_SIZE  144
 #define REG_SZ         8
 #define ASM_ULONG_INSN .dword
 #else  /* CONFIG_64BIT */
-#define LDREG  ldw
-#define STREG  stw
-#define LDREGX  ldwx,s
-#define LDREGM ldwm
-#define STREGM stwm
-#define SHRREG shr
-#define SHLREG shlw
-#define ANDCM   andcm
-#define COND(x)        x
 #define RP_OFFSET      20
 #define FRAME_SIZE     64
 #define CALLEE_REG_FRAME_SIZE  128
@@ -45,6 +26,7 @@
 /* Frame alignment for 32- and 64-bit */
 #define FRAME_ALIGN     64
 
+#define CALLEE_FLOAT_FRAME_SIZE        80
 #define CALLEE_SAVE_FRAME_SIZE (CALLEE_REG_FRAME_SIZE + CALLEE_FLOAT_FRAME_SIZE)
 
 #ifdef CONFIG_PA20
 #ifdef __ASSEMBLY__
 
 #ifdef CONFIG_64BIT
+#define LDREG  ldd
+#define STREG  std
+#define LDREGX  ldd,s
+#define LDREGM ldd,mb
+#define STREGM std,ma
+#define SHRREG shrd
+#define SHLREG shld
+#define ANDCM   andcm,*
+#define        COND(x) * ## x
+#else  /* CONFIG_64BIT */
+#define LDREG  ldw
+#define STREG  stw
+#define LDREGX  ldwx,s
+#define LDREGM ldwm
+#define STREGM stwm
+#define SHRREG shr
+#define SHLREG shlw
+#define ANDCM   andcm
+#define COND(x)        x
+#endif
+
+#ifdef CONFIG_64BIT
 /* the 64-bit pa gnu assembler unfortunately defaults to .level 1.1 or 2.0 so
  * work around that for now... */
        .level 2.0w
index 7efb1aa..af2a598 100644 (file)
@@ -5,6 +5,7 @@
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
+#include <linux/stringify.h>
 #include <asm/assembly.h>
 
 #define JUMP_LABEL_NOP_SIZE 4
index 4b9e3d7..2b3010a 100644 (file)
@@ -2,7 +2,7 @@
 #ifndef _ASM_PARISC_RT_SIGFRAME_H
 #define _ASM_PARISC_RT_SIGFRAME_H
 
-#define SIGRETURN_TRAMP 3
+#define SIGRETURN_TRAMP 4
 #define SIGRESTARTBLOCK_TRAMP 5 
 #define TRAMP_SIZE (SIGRETURN_TRAMP + SIGRESTARTBLOCK_TRAMP)
 
index bbfe23c..46b1050 100644 (file)
@@ -288,21 +288,22 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs,
           already in userspace. The first words of tramp are used to
           save the previous sigrestartblock trampoline that might be
           on the stack. We start the sigreturn trampoline at 
-          SIGRESTARTBLOCK_TRAMP. */
+          SIGRESTARTBLOCK_TRAMP+X. */
        err |= __put_user(in_syscall ? INSN_LDI_R25_1 : INSN_LDI_R25_0,
                        &frame->tramp[SIGRESTARTBLOCK_TRAMP+0]);
-       err |= __put_user(INSN_BLE_SR2_R0, 
+       err |= __put_user(INSN_LDI_R20, 
                        &frame->tramp[SIGRESTARTBLOCK_TRAMP+1]);
-       err |= __put_user(INSN_LDI_R20,
+       err |= __put_user(INSN_BLE_SR2_R0, 
                        &frame->tramp[SIGRESTARTBLOCK_TRAMP+2]);
+       err |= __put_user(INSN_NOP, &frame->tramp[SIGRESTARTBLOCK_TRAMP+3]);
 
-       start = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP+0];
-       end = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP+3];
+       start = (unsigned long) &frame->tramp[0];
+       end = (unsigned long) &frame->tramp[TRAMP_SIZE];
        flush_user_dcache_range_asm(start, end);
        flush_user_icache_range_asm(start, end);
 
        /* TRAMP Words 0-4, Length 5 = SIGRESTARTBLOCK_TRAMP
-        * TRAMP Words 5-7, Length 3 = SIGRETURN_TRAMP
+        * TRAMP Words 5-9, Length 4 = SIGRETURN_TRAMP
         * So the SIGRETURN_TRAMP is at the end of SIGRESTARTBLOCK_TRAMP
         */
        rp = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP];
index a5bdbb5..f166250 100644 (file)
@@ -36,7 +36,7 @@ struct compat_regfile {
         compat_int_t rf_sar;
 };
 
-#define COMPAT_SIGRETURN_TRAMP 3
+#define COMPAT_SIGRETURN_TRAMP 4
 #define COMPAT_SIGRESTARTBLOCK_TRAMP 5
 #define COMPAT_TRAMP_SIZE (COMPAT_SIGRETURN_TRAMP + \
                                COMPAT_SIGRESTARTBLOCK_TRAMP)
index bf751e0..358c000 100644 (file)
 446    common  landlock_restrict_self          sys_landlock_restrict_self
 # 447 reserved for memfd_secret
 448    common  process_mrelease                sys_process_mrelease
+449    common  futex_waitv                     sys_futex_waitv
index 00a9c9c..3e053e2 100644 (file)
@@ -1063,7 +1063,7 @@ SYSCALL_DEFINE3(swapcontext, struct ucontext __user *, old_ctx,
         * We kill the task with a SIGSEGV in this situation.
         */
        if (do_setcontext(new_ctx, regs, 0)) {
-               force_fatal_sig(SIGSEGV);
+               force_exit_sig(SIGSEGV);
                return -EFAULT;
        }
 
index ef51853..d1e1fc0 100644 (file)
@@ -704,7 +704,7 @@ SYSCALL_DEFINE3(swapcontext, struct ucontext __user *, old_ctx,
         */
 
        if (__get_user_sigset(&set, &new_ctx->uc_sigmask)) {
-               force_fatal_sig(SIGSEGV);
+               force_exit_sig(SIGSEGV);
                return -EFAULT;
        }
        set_current_blocked(&set);
@@ -713,7 +713,7 @@ SYSCALL_DEFINE3(swapcontext, struct ucontext __user *, old_ctx,
                return -EFAULT;
        if (__unsafe_restore_sigcontext(current, NULL, 0, &new_ctx->uc_mcontext)) {
                user_read_access_end();
-               force_fatal_sig(SIGSEGV);
+               force_exit_sig(SIGSEGV);
                return -EFAULT;
        }
        user_read_access_end();
index f9ea0e5..3fa6d24 100644 (file)
@@ -187,6 +187,12 @@ static void watchdog_smp_panic(int cpu, u64 tb)
        if (sysctl_hardlockup_all_cpu_backtrace)
                trigger_allbutself_cpu_backtrace();
 
+       /*
+        * Force flush any remote buffers that might be stuck in IRQ context
+        * and therefore could not run their irq_work.
+        */
+       printk_trigger_flush();
+
        if (hardlockup_panic)
                nmi_panic(NULL, "Hard LOCKUP");
 
index 35e9ccc..a72920f 100644 (file)
@@ -641,9 +641,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
                 * implementations just count online CPUs.
                 */
                if (hv_enabled)
-                       r = num_present_cpus();
+                       r = min_t(unsigned int, num_present_cpus(), KVM_MAX_VCPUS);
                else
-                       r = num_online_cpus();
+                       r = min_t(unsigned int, num_online_cpus(), KVM_MAX_VCPUS);
                break;
        case KVM_CAP_MAX_VCPUS:
                r = KVM_MAX_VCPUS;
index 5927c94..8a107ed 100644 (file)
@@ -107,11 +107,13 @@ PHONY += vdso_install
 vdso_install:
        $(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso $@
 
+ifeq ($(KBUILD_EXTMOD),)
 ifeq ($(CONFIG_MMU),y)
 prepare: vdso_prepare
 vdso_prepare: prepare0
        $(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso include/generated/vdso-offsets.h
 endif
+endif
 
 ifneq ($(CONFIG_XIP_KERNEL),y)
 ifeq ($(CONFIG_RISCV_M_MODE)$(CONFIG_SOC_CANAAN),yy)
index c252fd5..ef473e2 100644 (file)
@@ -19,6 +19,8 @@ CONFIG_SOC_VIRT=y
 CONFIG_SOC_MICROCHIP_POLARFIRE=y
 CONFIG_SMP=y
 CONFIG_HOTPLUG_CPU=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM=m
 CONFIG_JUMP_LABEL=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
index 434ef5b..6e9f12f 100644 (file)
@@ -19,6 +19,8 @@ CONFIG_SOC_VIRT=y
 CONFIG_ARCH_RV32I=y
 CONFIG_SMP=y
 CONFIG_HOTPLUG_CPU=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM=m
 CONFIG_JUMP_LABEL=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
index e3d3aed..fb84619 100644 (file)
@@ -740,7 +740,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
                 * Ensure we set mode to IN_GUEST_MODE after we disable
                 * interrupts and before the final VCPU requests check.
                 * See the comment in kvm_vcpu_exiting_guest_mode() and
-                * Documentation/virtual/kvm/vcpu-requests.rst
+                * Documentation/virt/kvm/vcpu-requests.rst
                 */
                vcpu->mode = IN_GUEST_MODE;
 
index eb3c045..3b0e703 100644 (file)
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0
-/**
+/*
  * Copyright (c) 2019 Western Digital Corporation or its affiliates.
  *
  * Authors:
index 26399df..fb18af3 100644 (file)
@@ -74,7 +74,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
                r = 1;
                break;
        case KVM_CAP_NR_VCPUS:
-               r = num_online_cpus();
+               r = min_t(unsigned int, num_online_cpus(), KVM_MAX_VCPUS);
                break;
        case KVM_CAP_MAX_VCPUS:
                r = KVM_MAX_VCPUS;
index 8857ec3..2a5bb4f 100644 (file)
@@ -47,7 +47,7 @@ config ARCH_SUPPORTS_UPROBES
 config KASAN_SHADOW_OFFSET
        hex
        depends on KASAN
-       default 0x18000000000000
+       default 0x1C000000000000
 
 config S390
        def_bool y
@@ -194,6 +194,7 @@ config S390
        select HAVE_RELIABLE_STACKTRACE
        select HAVE_RSEQ
        select HAVE_SAMPLE_FTRACE_DIRECT
+       select HAVE_SAMPLE_FTRACE_DIRECT_MULTI
        select HAVE_SOFTIRQ_ON_OWN_STACK
        select HAVE_SYSCALL_TRACEPOINTS
        select HAVE_VIRT_CPU_ACCOUNTING
index 69c45f6..609e369 100644 (file)
@@ -77,10 +77,12 @@ KBUILD_AFLAGS_DECOMPRESSOR += $(aflags-y)
 KBUILD_CFLAGS_DECOMPRESSOR += $(cflags-y)
 
 ifneq ($(call cc-option,-mstack-size=8192 -mstack-guard=128),)
-cflags-$(CONFIG_CHECK_STACK) += -mstack-size=$(STACK_SIZE)
-ifeq ($(call cc-option,-mstack-size=8192),)
-cflags-$(CONFIG_CHECK_STACK) += -mstack-guard=$(CONFIG_STACK_GUARD)
-endif
+  CC_FLAGS_CHECK_STACK := -mstack-size=$(STACK_SIZE)
+  ifeq ($(call cc-option,-mstack-size=8192),)
+    CC_FLAGS_CHECK_STACK += -mstack-guard=$(CONFIG_STACK_GUARD)
+  endif
+  export CC_FLAGS_CHECK_STACK
+  cflags-$(CONFIG_CHECK_STACK) += $(CC_FLAGS_CHECK_STACK)
 endif
 
 ifdef CONFIG_EXPOLINE
index 7571dee..1aa11a8 100644 (file)
@@ -149,82 +149,56 @@ static void setup_ident_map_size(unsigned long max_physmem_end)
 
 static void setup_kernel_memory_layout(void)
 {
-       bool vmalloc_size_verified = false;
-       unsigned long vmemmap_off;
-       unsigned long vspace_left;
+       unsigned long vmemmap_start;
        unsigned long rte_size;
        unsigned long pages;
-       unsigned long vmax;
 
        pages = ident_map_size / PAGE_SIZE;
        /* vmemmap contains a multiple of PAGES_PER_SECTION struct pages */
        vmemmap_size = SECTION_ALIGN_UP(pages) * sizeof(struct page);
 
        /* choose kernel address space layout: 4 or 3 levels. */
-       vmemmap_off = round_up(ident_map_size, _REGION3_SIZE);
+       vmemmap_start = round_up(ident_map_size, _REGION3_SIZE);
        if (IS_ENABLED(CONFIG_KASAN) ||
            vmalloc_size > _REGION2_SIZE ||
-           vmemmap_off + vmemmap_size + vmalloc_size + MODULES_LEN > _REGION2_SIZE)
-               vmax = _REGION1_SIZE;
-       else
-               vmax = _REGION2_SIZE;
-
-       /* keep vmemmap_off aligned to a top level region table entry */
-       rte_size = vmax == _REGION1_SIZE ? _REGION2_SIZE : _REGION3_SIZE;
-       MODULES_END = vmax;
-       if (is_prot_virt_host()) {
-               /*
-                * forcing modules and vmalloc area under the ultravisor
-                * secure storage limit, so that any vmalloc allocation
-                * we do could be used to back secure guest storage.
-                */
-               adjust_to_uv_max(&MODULES_END);
-       }
-
-#ifdef CONFIG_KASAN
-       if (MODULES_END < vmax) {
-               /* force vmalloc and modules below kasan shadow */
-               MODULES_END = min(MODULES_END, KASAN_SHADOW_START);
+           vmemmap_start + vmemmap_size + vmalloc_size + MODULES_LEN >
+                   _REGION2_SIZE) {
+               MODULES_END = _REGION1_SIZE;
+               rte_size = _REGION2_SIZE;
        } else {
-               /*
-                * leave vmalloc and modules above kasan shadow but make
-                * sure they don't overlap with it
-                */
-               vmalloc_size = min(vmalloc_size, vmax - KASAN_SHADOW_END - MODULES_LEN);
-               vmalloc_size_verified = true;
-               vspace_left = KASAN_SHADOW_START;
+               MODULES_END = _REGION2_SIZE;
+               rte_size = _REGION3_SIZE;
        }
+       /*
+        * forcing modules and vmalloc area under the ultravisor
+        * secure storage limit, so that any vmalloc allocation
+        * we do could be used to back secure guest storage.
+        */
+       adjust_to_uv_max(&MODULES_END);
+#ifdef CONFIG_KASAN
+       /* force vmalloc and modules below kasan shadow */
+       MODULES_END = min(MODULES_END, KASAN_SHADOW_START);
 #endif
        MODULES_VADDR = MODULES_END - MODULES_LEN;
        VMALLOC_END = MODULES_VADDR;
 
-       if (vmalloc_size_verified) {
-               VMALLOC_START = VMALLOC_END - vmalloc_size;
-       } else {
-               vmemmap_off = round_up(ident_map_size, rte_size);
-
-               if (vmemmap_off + vmemmap_size > VMALLOC_END ||
-                   vmalloc_size > VMALLOC_END - vmemmap_off - vmemmap_size) {
-                       /*
-                        * allow vmalloc area to occupy up to 1/2 of
-                        * the rest virtual space left.
-                        */
-                       vmalloc_size = min(vmalloc_size, VMALLOC_END / 2);
-               }
-               VMALLOC_START = VMALLOC_END - vmalloc_size;
-               vspace_left = VMALLOC_START;
-       }
+       /* allow vmalloc area to occupy up to about 1/2 of the rest virtual space left */
+       vmalloc_size = min(vmalloc_size, round_down(VMALLOC_END / 2, _REGION3_SIZE));
+       VMALLOC_START = VMALLOC_END - vmalloc_size;
 
-       pages = vspace_left / (PAGE_SIZE + sizeof(struct page));
+       /* split remaining virtual space between 1:1 mapping & vmemmap array */
+       pages = VMALLOC_START / (PAGE_SIZE + sizeof(struct page));
        pages = SECTION_ALIGN_UP(pages);
-       vmemmap_off = round_up(vspace_left - pages * sizeof(struct page), rte_size);
-       /* keep vmemmap left most starting from a fresh region table entry */
-       vmemmap_off = min(vmemmap_off, round_up(ident_map_size, rte_size));
-       /* take care that identity map is lower then vmemmap */
-       ident_map_size = min(ident_map_size, vmemmap_off);
+       /* keep vmemmap_start aligned to a top level region table entry */
+       vmemmap_start = round_down(VMALLOC_START - pages * sizeof(struct page), rte_size);
+       /* vmemmap_start is the future VMEM_MAX_PHYS, make sure it is within MAX_PHYSMEM */
+       vmemmap_start = min(vmemmap_start, 1UL << MAX_PHYSMEM_BITS);
+       /* make sure identity map doesn't overlay with vmemmap */
+       ident_map_size = min(ident_map_size, vmemmap_start);
        vmemmap_size = SECTION_ALIGN_UP(ident_map_size / PAGE_SIZE) * sizeof(struct page);
-       VMALLOC_START = max(vmemmap_off + vmemmap_size, VMALLOC_START);
-       vmemmap = (struct page *)vmemmap_off;
+       /* make sure vmemmap doesn't overlay with vmalloc area */
+       VMALLOC_START = max(vmemmap_start + vmemmap_size, VMALLOC_START);
+       vmemmap = (struct page *)vmemmap_start;
 }
 
 /*
index ea398a0..7f3c9ac 100644 (file)
@@ -74,6 +74,12 @@ void *kexec_file_add_components(struct kimage *image,
 int arch_kexec_do_relocs(int r_type, void *loc, unsigned long val,
                         unsigned long addr);
 
+#define ARCH_HAS_KIMAGE_ARCH
+
+struct kimage_arch {
+       void *ipl_buf;
+};
+
 extern const struct kexec_file_ops s390_kexec_image_ops;
 extern const struct kexec_file_ops s390_kexec_elf_ops;
 
index d72a6df..785d54c 100644 (file)
@@ -191,8 +191,8 @@ static int copy_oldmem_user(void __user *dst, void *src, size_t count)
                                return rc;
                } else {
                        /* Check for swapped kdump oldmem areas */
-                       if (oldmem_data.start && from - oldmem_data.size < oldmem_data.size) {
-                               from -= oldmem_data.size;
+                       if (oldmem_data.start && from - oldmem_data.start < oldmem_data.size) {
+                               from -= oldmem_data.start;
                                len = min(count, oldmem_data.size - from);
                        } else if (oldmem_data.start && from < oldmem_data.size) {
                                len = min(count, oldmem_data.size - from);
index e2cc357..5ad1dde 100644 (file)
@@ -2156,7 +2156,7 @@ void *ipl_report_finish(struct ipl_report *report)
 
        buf = vzalloc(report->size);
        if (!buf)
-               return ERR_PTR(-ENOMEM);
+               goto out;
        ptr = buf;
 
        memcpy(ptr, report->ipib, report->ipib->hdr.len);
@@ -2195,6 +2195,7 @@ void *ipl_report_finish(struct ipl_report *report)
        }
 
        BUG_ON(ptr > buf + report->size);
+out:
        return buf;
 }
 
index 528edff..9975ad2 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/kexec.h>
 #include <linux/module_signature.h>
 #include <linux/verification.h>
+#include <linux/vmalloc.h>
 #include <asm/boot_data.h>
 #include <asm/ipl.h>
 #include <asm/setup.h>
@@ -170,6 +171,7 @@ static int kexec_file_add_ipl_report(struct kimage *image,
        struct kexec_buf buf;
        unsigned long addr;
        void *ptr, *end;
+       int ret;
 
        buf.image = image;
 
@@ -199,9 +201,13 @@ static int kexec_file_add_ipl_report(struct kimage *image,
                ptr += len;
        }
 
+       ret = -ENOMEM;
        buf.buffer = ipl_report_finish(data->report);
+       if (!buf.buffer)
+               goto out;
        buf.bufsz = data->report->size;
        buf.memsz = buf.bufsz;
+       image->arch.ipl_buf = buf.buffer;
 
        data->memsz += buf.memsz;
 
@@ -209,7 +215,9 @@ static int kexec_file_add_ipl_report(struct kimage *image,
                data->kernel_buf + offsetof(struct lowcore, ipl_parmblock_ptr);
        *lc_ipl_parmblock_ptr = (__u32)buf.mem;
 
-       return kexec_add_buffer(&buf);
+       ret = kexec_add_buffer(&buf);
+out:
+       return ret;
 }
 
 void *kexec_file_add_components(struct kimage *image,
@@ -322,3 +330,11 @@ int arch_kexec_apply_relocations_add(struct purgatory_info *pi,
        }
        return 0;
 }
+
+int arch_kimage_file_post_load_cleanup(struct kimage *image)
+{
+       vfree(image->arch.ipl_buf);
+       image->arch.ipl_buf = NULL;
+
+       return kexec_image_post_load_cleanup_default(image);
+}
index 40405f2..225ab2d 100644 (file)
@@ -606,7 +606,7 @@ static void __init setup_resources(void)
 
 static void __init setup_memory_end(void)
 {
-       memblock_remove(ident_map_size, ULONG_MAX);
+       memblock_remove(ident_map_size, PHYS_ADDR_MAX - ident_map_size);
        max_pfn = max_low_pfn = PFN_DOWN(ident_map_size);
        pr_notice("The maximum memory size is %luMB\n", ident_map_size >> 20);
 }
@@ -638,14 +638,6 @@ static struct notifier_block kdump_mem_nb = {
 #endif
 
 /*
- * Make sure that the area above identity mapping is protected
- */
-static void __init reserve_above_ident_map(void)
-{
-       memblock_reserve(ident_map_size, ULONG_MAX);
-}
-
-/*
  * Reserve memory for kdump kernel to be loaded with kexec
  */
 static void __init reserve_crashkernel(void)
@@ -785,7 +777,6 @@ static void __init memblock_add_mem_detect_info(void)
        }
        memblock_set_bottom_up(false);
        memblock_set_node(0, ULONG_MAX, &memblock.memory, 0);
-       memblock_dump_all();
 }
 
 /*
@@ -826,9 +817,6 @@ static void __init setup_memory(void)
                storage_key_init_range(start, end);
 
        psw_set_key(PAGE_DEFAULT_KEY);
-
-       /* Only cosmetics */
-       memblock_enforce_memory_limit(memblock_end_of_DRAM());
 }
 
 static void __init relocate_amode31_section(void)
@@ -999,24 +987,24 @@ void __init setup_arch(char **cmdline_p)
        setup_control_program_code();
 
        /* Do some memory reservations *before* memory is added to memblock */
-       reserve_above_ident_map();
        reserve_kernel();
        reserve_initrd();
        reserve_certificate_list();
        reserve_mem_detect_info();
+       memblock_set_current_limit(ident_map_size);
        memblock_allow_resize();
 
        /* Get information about *all* installed memory */
        memblock_add_mem_detect_info();
 
        free_mem_detect_info();
+       setup_memory_end();
+       memblock_dump_all();
+       setup_memory();
 
        relocate_amode31_section();
        setup_cr();
-
        setup_uv();
-       setup_memory_end();
-       setup_memory();
        dma_contiguous_reserve(ident_map_size);
        vmcp_cma_reserve();
        if (MACHINE_HAS_EDAT2)
index df5261e..ed9c5c2 100644 (file)
 446  common    landlock_restrict_self  sys_landlock_restrict_self      sys_landlock_restrict_self
 # 447 reserved for memfd_secret
 448  common    process_mrelease        sys_process_mrelease            sys_process_mrelease
+449  common    futex_waitv             sys_futex_waitv                 sys_futex_waitv
index 035705c..2b78078 100644 (file)
@@ -84,7 +84,7 @@ static void default_trap_handler(struct pt_regs *regs)
 {
        if (user_mode(regs)) {
                report_user_fault(regs, SIGSEGV, 0);
-               force_fatal_sig(SIGSEGV);
+               force_exit_sig(SIGSEGV);
        } else
                die(regs, "Unknown program exception");
 }
index e3e6ac5..245bddf 100644 (file)
@@ -22,7 +22,7 @@ KBUILD_AFLAGS_32 += -m31 -s
 KBUILD_CFLAGS_32 := $(filter-out -m64,$(KBUILD_CFLAGS))
 KBUILD_CFLAGS_32 += -m31 -fPIC -shared -fno-common -fno-builtin
 
-LDFLAGS_vdso32.so.dbg += -fPIC -shared -nostdlib -soname=linux-vdso32.so.1 \
+LDFLAGS_vdso32.so.dbg += -fPIC -shared -soname=linux-vdso32.so.1 \
        --hash-style=both --build-id=sha1 -melf_s390 -T
 
 $(targets:%=$(obj)/%.dbg): KBUILD_CFLAGS = $(KBUILD_CFLAGS_32)
index 6568de2..9e2b95a 100644 (file)
@@ -8,8 +8,9 @@ ARCH_REL_TYPE_ABS += R_390_GOT|R_390_PLT
 include $(srctree)/lib/vdso/Makefile
 obj-vdso64 = vdso_user_wrapper.o note.o
 obj-cvdso64 = vdso64_generic.o getcpu.o
-CFLAGS_REMOVE_getcpu.o = -pg $(CC_FLAGS_FTRACE) $(CC_FLAGS_EXPOLINE)
-CFLAGS_REMOVE_vdso64_generic.o = -pg $(CC_FLAGS_FTRACE) $(CC_FLAGS_EXPOLINE)
+VDSO_CFLAGS_REMOVE := -pg $(CC_FLAGS_FTRACE) $(CC_FLAGS_EXPOLINE) $(CC_FLAGS_CHECK_STACK)
+CFLAGS_REMOVE_getcpu.o = $(VDSO_CFLAGS_REMOVE)
+CFLAGS_REMOVE_vdso64_generic.o = $(VDSO_CFLAGS_REMOVE)
 
 # Build rules
 
@@ -25,7 +26,7 @@ KBUILD_AFLAGS_64 += -m64 -s
 
 KBUILD_CFLAGS_64 := $(filter-out -m64,$(KBUILD_CFLAGS))
 KBUILD_CFLAGS_64 += -m64 -fPIC -shared -fno-common -fno-builtin
-ldflags-y := -fPIC -shared -nostdlib -soname=linux-vdso64.so.1 \
+ldflags-y := -fPIC -shared -soname=linux-vdso64.so.1 \
             --hash-style=both --build-id=sha1 -T
 
 $(targets:%=$(obj)/%.dbg): KBUILD_CFLAGS = $(KBUILD_CFLAGS_64)
index c6257f6..14a18ba 100644 (file)
@@ -585,6 +585,8 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
                        r = KVM_MAX_VCPUS;
                else if (sclp.has_esca && sclp.has_64bscao)
                        r = KVM_S390_ESCA_CPU_SLOTS;
+               if (ext == KVM_CAP_NR_VCPUS)
+                       r = min_t(unsigned int, num_online_cpus(), r);
                break;
        case KVM_CAP_S390_COW:
                r = MACHINE_HAS_ESOP;
index cd677bc..ffab163 100644 (file)
@@ -244,7 +244,7 @@ static int setup_frame(struct ksignal *ksig, struct pt_regs *regs,
                get_sigframe(ksig, regs, sigframe_size);
 
        if (invalid_frame_pointer(sf, sigframe_size)) {
-               force_fatal_sig(SIGILL);
+               force_exit_sig(SIGILL);
                return -EINVAL;
        }
 
@@ -336,7 +336,7 @@ static int setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs,
        sf = (struct rt_signal_frame __user *)
                get_sigframe(ksig, regs, sigframe_size);
        if (invalid_frame_pointer(sf, sigframe_size)) {
-               force_fatal_sig(SIGILL);
+               force_exit_sig(SIGILL);
                return -EINVAL;
        }
 
index bbbd40c..8f20862 100644 (file)
@@ -122,7 +122,7 @@ void try_to_clear_window_buffer(struct pt_regs *regs, int who)
                if ((sp & 7) ||
                    copy_to_user((char __user *) sp, &tp->reg_window[window],
                                 sizeof(struct reg_window32))) {
-                       force_fatal_sig(SIGILL);
+                       force_exit_sig(SIGILL);
                        return;
                }
        }
index 95dd1ee..7399327 100644 (file)
@@ -193,7 +193,7 @@ config X86
        select HAVE_DYNAMIC_FTRACE_WITH_ARGS    if X86_64
        select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
        select HAVE_SAMPLE_FTRACE_DIRECT        if X86_64
-       select HAVE_SAMPLE_FTRACE_MULTI_DIRECT  if X86_64
+       select HAVE_SAMPLE_FTRACE_DIRECT_MULTI  if X86_64
        select HAVE_EBPF_JIT
        select HAVE_EFFICIENT_UNALIGNED_ACCESS
        select HAVE_EISA
index 0b6b277..fd2ee94 100644 (file)
@@ -226,7 +226,7 @@ bool emulate_vsyscall(unsigned long error_code,
        if ((!tmp && regs->orig_ax != syscall_nr) || regs->ip != address) {
                warn_bad_vsyscall(KERN_DEBUG, regs,
                                  "seccomp tried to change syscall nr or ip");
-               force_fatal_sig(SIGSYS);
+               force_exit_sig(SIGSYS);
                return true;
        }
        regs->orig_ax = -1;
index 24f4a06..96eb7db 100644 (file)
@@ -177,6 +177,9 @@ void set_hv_tscchange_cb(void (*cb)(void))
                return;
        }
 
+       if (!hv_vp_index)
+               return;
+
        hv_reenlightenment_cb = cb;
 
        /* Make sure callback is registered before we write to MSRs */
@@ -383,20 +386,13 @@ static void __init hv_get_partition_id(void)
  */
 void __init hyperv_init(void)
 {
-       u64 guest_id, required_msrs;
+       u64 guest_id;
        union hv_x64_msr_hypercall_contents hypercall_msr;
        int cpuhp;
 
        if (x86_hyper_type != X86_HYPER_MS_HYPERV)
                return;
 
-       /* Absolutely required MSRs */
-       required_msrs = HV_MSR_HYPERCALL_AVAILABLE |
-               HV_MSR_VP_INDEX_AVAILABLE;
-
-       if ((ms_hyperv.features & required_msrs) != required_msrs)
-               return;
-
        if (hv_common_init())
                return;
 
index e5d8700..6ac61f8 100644 (file)
@@ -363,6 +363,7 @@ union kvm_mmu_extended_role {
                unsigned int cr4_smap:1;
                unsigned int cr4_smep:1;
                unsigned int cr4_la57:1;
+               unsigned int efer_lma:1;
        };
 };
 
index 4794b71..ff55df6 100644 (file)
@@ -163,12 +163,22 @@ static uint32_t  __init ms_hyperv_platform(void)
        cpuid(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS,
              &eax, &hyp_signature[0], &hyp_signature[1], &hyp_signature[2]);
 
-       if (eax >= HYPERV_CPUID_MIN &&
-           eax <= HYPERV_CPUID_MAX &&
-           !memcmp("Microsoft Hv", hyp_signature, 12))
-               return HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS;
+       if (eax < HYPERV_CPUID_MIN || eax > HYPERV_CPUID_MAX ||
+           memcmp("Microsoft Hv", hyp_signature, 12))
+               return 0;
 
-       return 0;
+       /* HYPERCALL and VP_INDEX MSRs are mandatory for all features. */
+       eax = cpuid_eax(HYPERV_CPUID_FEATURES);
+       if (!(eax & HV_MSR_HYPERCALL_AVAILABLE)) {
+               pr_warn("x86/hyperv: HYPERCALL MSR not available.\n");
+               return 0;
+       }
+       if (!(eax & HV_MSR_VP_INDEX_AVAILABLE)) {
+               pr_warn("x86/hyperv: VP_INDEX MSR not available.\n");
+               return 0;
+       }
+
+       return HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS;
 }
 
 static unsigned char hv_get_nmi_reason(void)
index e9ee8b5..04143a6 100644 (file)
@@ -964,6 +964,9 @@ unsigned long __get_wchan(struct task_struct *p)
        struct unwind_state state;
        unsigned long addr = 0;
 
+       if (!try_get_task_stack(p))
+               return 0;
+
        for (unwind_start(&state, p, NULL, NULL); !unwind_done(&state);
             unwind_next_frame(&state)) {
                addr = unwind_get_return_address(&state);
@@ -974,6 +977,8 @@ unsigned long __get_wchan(struct task_struct *p)
                break;
        }
 
+       put_task_stack(p);
+
        return addr;
 }
 
index cce1c89..c21bcd6 100644 (file)
@@ -160,7 +160,7 @@ Efault_end:
        user_access_end();
 Efault:
        pr_alert("could not access userspace vm86 info\n");
-       force_fatal_sig(SIGSEGV);
+       force_exit_sig(SIGSEGV);
        goto exit_vm86;
 }
 
index e19dabf..07e9215 100644 (file)
@@ -125,7 +125,7 @@ static void kvm_update_kvm_cpuid_base(struct kvm_vcpu *vcpu)
        }
 }
 
-struct kvm_cpuid_entry2 *kvm_find_kvm_cpuid_features(struct kvm_vcpu *vcpu)
+static struct kvm_cpuid_entry2 *kvm_find_kvm_cpuid_features(struct kvm_vcpu *vcpu)
 {
        u32 base = vcpu->arch.kvm_cpuid_base;
 
index 4a555f3..5e19e6e 100644 (file)
@@ -2022,7 +2022,7 @@ static void kvm_hv_hypercall_set_result(struct kvm_vcpu *vcpu, u64 result)
 {
        bool longmode;
 
-       longmode = is_64_bit_mode(vcpu);
+       longmode = is_64_bit_hypercall(vcpu);
        if (longmode)
                kvm_rax_write(vcpu, result);
        else {
@@ -2171,7 +2171,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
        }
 
 #ifdef CONFIG_X86_64
-       if (is_64_bit_mode(vcpu)) {
+       if (is_64_bit_hypercall(vcpu)) {
                hc.param = kvm_rcx_read(vcpu);
                hc.ingpa = kvm_rdx_read(vcpu);
                hc.outgpa = kvm_r8_read(vcpu);
index 3379437..3be9bee 100644 (file)
@@ -4682,6 +4682,7 @@ static union kvm_mmu_extended_role kvm_calc_mmu_role_ext(struct kvm_vcpu *vcpu,
                /* PKEY and LA57 are active iff long mode is active. */
                ext.cr4_pke = ____is_efer_lma(regs) && ____is_cr4_pke(regs);
                ext.cr4_la57 = ____is_efer_lma(regs) && ____is_cr4_la57(regs);
+               ext.efer_lma = ____is_efer_lma(regs);
        }
 
        ext.valid = 1;
index 902c52a..21ac0a5 100644 (file)
@@ -237,7 +237,6 @@ static void sev_unbind_asid(struct kvm *kvm, unsigned int handle)
 static int sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp)
 {
        struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info;
-       bool es_active = argp->id == KVM_SEV_ES_INIT;
        int asid, ret;
 
        if (kvm->created_vcpus)
@@ -247,7 +246,8 @@ static int sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp)
        if (unlikely(sev->active))
                return ret;
 
-       sev->es_active = es_active;
+       sev->active = true;
+       sev->es_active = argp->id == KVM_SEV_ES_INIT;
        asid = sev_asid_new(sev);
        if (asid < 0)
                goto e_no_asid;
@@ -257,8 +257,6 @@ static int sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp)
        if (ret)
                goto e_free;
 
-       sev->active = true;
-       sev->asid = asid;
        INIT_LIST_HEAD(&sev->regions_list);
 
        return 0;
@@ -268,6 +266,7 @@ e_free:
        sev->asid = 0;
 e_no_asid:
        sev->es_active = false;
+       sev->active = false;
        return ret;
 }
 
@@ -1530,7 +1529,7 @@ static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp)
        return sev_issue_cmd(kvm, SEV_CMD_RECEIVE_FINISH, &data, &argp->error);
 }
 
-static bool cmd_allowed_from_miror(u32 cmd_id)
+static bool is_cmd_allowed_from_mirror(u32 cmd_id)
 {
        /*
         * Allow mirrors VM to call KVM_SEV_LAUNCH_UPDATE_VMSA to enable SEV-ES
@@ -1757,7 +1756,7 @@ int svm_mem_enc_op(struct kvm *kvm, void __user *argp)
 
        /* Only the enc_context_owner handles some memory enc operations. */
        if (is_mirroring_enc_context(kvm) &&
-           !cmd_allowed_from_miror(sev_cmd.id)) {
+           !is_cmd_allowed_from_mirror(sev_cmd.id)) {
                r = -EINVAL;
                goto out;
        }
@@ -1990,7 +1989,12 @@ int svm_vm_copy_asid_from(struct kvm *kvm, unsigned int source_fd)
        mutex_unlock(&source_kvm->lock);
        mutex_lock(&kvm->lock);
 
-       if (sev_guest(kvm)) {
+       /*
+        * Disallow out-of-band SEV/SEV-ES init if the target is already an
+        * SEV guest, or if vCPUs have been created.  KVM relies on vCPUs being
+        * created after SEV/SEV-ES initialization, e.g. to init intercepts.
+        */
+       if (sev_guest(kvm) || kvm->created_vcpus) {
                ret = -EINVAL;
                goto e_mirror_unlock;
        }
index 437e685..5faad3d 100644 (file)
@@ -247,7 +247,7 @@ static __always_inline bool sev_es_guest(struct kvm *kvm)
 #ifdef CONFIG_KVM_AMD_SEV
        struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info;
 
-       return sev_guest(kvm) && sev->es_active;
+       return sev->es_active && !WARN_ON_ONCE(!sev->active);
 #else
        return false;
 #endif
index b213ca9..1e2f669 100644 (file)
@@ -670,33 +670,39 @@ static inline bool nested_vmx_prepare_msr_bitmap(struct kvm_vcpu *vcpu,
 static void nested_cache_shadow_vmcs12(struct kvm_vcpu *vcpu,
                                       struct vmcs12 *vmcs12)
 {
-       struct kvm_host_map map;
-       struct vmcs12 *shadow;
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
+       struct gfn_to_hva_cache *ghc = &vmx->nested.shadow_vmcs12_cache;
 
        if (!nested_cpu_has_shadow_vmcs(vmcs12) ||
            vmcs12->vmcs_link_pointer == INVALID_GPA)
                return;
 
-       shadow = get_shadow_vmcs12(vcpu);
-
-       if (kvm_vcpu_map(vcpu, gpa_to_gfn(vmcs12->vmcs_link_pointer), &map))
+       if (ghc->gpa != vmcs12->vmcs_link_pointer &&
+           kvm_gfn_to_hva_cache_init(vcpu->kvm, ghc,
+                                     vmcs12->vmcs_link_pointer, VMCS12_SIZE))
                return;
 
-       memcpy(shadow, map.hva, VMCS12_SIZE);
-       kvm_vcpu_unmap(vcpu, &map, false);
+       kvm_read_guest_cached(vmx->vcpu.kvm, ghc, get_shadow_vmcs12(vcpu),
+                             VMCS12_SIZE);
 }
 
 static void nested_flush_cached_shadow_vmcs12(struct kvm_vcpu *vcpu,
                                              struct vmcs12 *vmcs12)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
+       struct gfn_to_hva_cache *ghc = &vmx->nested.shadow_vmcs12_cache;
 
        if (!nested_cpu_has_shadow_vmcs(vmcs12) ||
            vmcs12->vmcs_link_pointer == INVALID_GPA)
                return;
 
-       kvm_write_guest(vmx->vcpu.kvm, vmcs12->vmcs_link_pointer,
-                       get_shadow_vmcs12(vcpu), VMCS12_SIZE);
+       if (ghc->gpa != vmcs12->vmcs_link_pointer &&
+           kvm_gfn_to_hva_cache_init(vcpu->kvm, ghc,
+                                     vmcs12->vmcs_link_pointer, VMCS12_SIZE))
+               return;
+
+       kvm_write_guest_cached(vmx->vcpu.kvm, ghc, get_shadow_vmcs12(vcpu),
+                              VMCS12_SIZE);
 }
 
 /*
@@ -2830,6 +2836,17 @@ static int nested_vmx_check_controls(struct kvm_vcpu *vcpu,
        return 0;
 }
 
+static int nested_vmx_check_address_space_size(struct kvm_vcpu *vcpu,
+                                      struct vmcs12 *vmcs12)
+{
+#ifdef CONFIG_X86_64
+       if (CC(!!(vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE) !=
+               !!(vcpu->arch.efer & EFER_LMA)))
+               return -EINVAL;
+#endif
+       return 0;
+}
+
 static int nested_vmx_check_host_state(struct kvm_vcpu *vcpu,
                                       struct vmcs12 *vmcs12)
 {
@@ -2854,18 +2871,16 @@ static int nested_vmx_check_host_state(struct kvm_vcpu *vcpu,
                return -EINVAL;
 
 #ifdef CONFIG_X86_64
-       ia32e = !!(vcpu->arch.efer & EFER_LMA);
+       ia32e = !!(vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE);
 #else
        ia32e = false;
 #endif
 
        if (ia32e) {
-               if (CC(!(vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE)) ||
-                   CC(!(vmcs12->host_cr4 & X86_CR4_PAE)))
+               if (CC(!(vmcs12->host_cr4 & X86_CR4_PAE)))
                        return -EINVAL;
        } else {
-               if (CC(vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE) ||
-                   CC(vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE) ||
+               if (CC(vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE) ||
                    CC(vmcs12->host_cr4 & X86_CR4_PCIDE) ||
                    CC((vmcs12->host_rip) >> 32))
                        return -EINVAL;
@@ -2910,9 +2925,9 @@ static int nested_vmx_check_host_state(struct kvm_vcpu *vcpu,
 static int nested_vmx_check_vmcs_link_ptr(struct kvm_vcpu *vcpu,
                                          struct vmcs12 *vmcs12)
 {
-       int r = 0;
-       struct vmcs12 *shadow;
-       struct kvm_host_map map;
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
+       struct gfn_to_hva_cache *ghc = &vmx->nested.shadow_vmcs12_cache;
+       struct vmcs_hdr hdr;
 
        if (vmcs12->vmcs_link_pointer == INVALID_GPA)
                return 0;
@@ -2920,17 +2935,21 @@ static int nested_vmx_check_vmcs_link_ptr(struct kvm_vcpu *vcpu,
        if (CC(!page_address_valid(vcpu, vmcs12->vmcs_link_pointer)))
                return -EINVAL;
 
-       if (CC(kvm_vcpu_map(vcpu, gpa_to_gfn(vmcs12->vmcs_link_pointer), &map)))
-               return -EINVAL;
+       if (ghc->gpa != vmcs12->vmcs_link_pointer &&
+           CC(kvm_gfn_to_hva_cache_init(vcpu->kvm, ghc,
+                                        vmcs12->vmcs_link_pointer, VMCS12_SIZE)))
+                return -EINVAL;
 
-       shadow = map.hva;
+       if (CC(kvm_read_guest_offset_cached(vcpu->kvm, ghc, &hdr,
+                                           offsetof(struct vmcs12, hdr),
+                                           sizeof(hdr))))
+               return -EINVAL;
 
-       if (CC(shadow->hdr.revision_id != VMCS12_REVISION) ||
-           CC(shadow->hdr.shadow_vmcs != nested_cpu_has_shadow_vmcs(vmcs12)))
-               r = -EINVAL;
+       if (CC(hdr.revision_id != VMCS12_REVISION) ||
+           CC(hdr.shadow_vmcs != nested_cpu_has_shadow_vmcs(vmcs12)))
+               return -EINVAL;
 
-       kvm_vcpu_unmap(vcpu, &map, false);
-       return r;
+       return 0;
 }
 
 /*
@@ -3535,6 +3554,9 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
        if (nested_vmx_check_controls(vcpu, vmcs12))
                return nested_vmx_fail(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
 
+       if (nested_vmx_check_address_space_size(vcpu, vmcs12))
+               return nested_vmx_fail(vcpu, VMXERR_ENTRY_INVALID_HOST_STATE_FIELD);
+
        if (nested_vmx_check_host_state(vcpu, vmcs12))
                return nested_vmx_fail(vcpu, VMXERR_ENTRY_INVALID_HOST_STATE_FIELD);
 
@@ -5264,10 +5286,11 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu)
                return 1;
 
        if (vmx->nested.current_vmptr != vmptr) {
-               struct kvm_host_map map;
-               struct vmcs12 *new_vmcs12;
+               struct gfn_to_hva_cache *ghc = &vmx->nested.vmcs12_cache;
+               struct vmcs_hdr hdr;
 
-               if (kvm_vcpu_map(vcpu, gpa_to_gfn(vmptr), &map)) {
+               if (ghc->gpa != vmptr &&
+                   kvm_gfn_to_hva_cache_init(vcpu->kvm, ghc, vmptr, VMCS12_SIZE)) {
                        /*
                         * Reads from an unbacked page return all 1s,
                         * which means that the 32 bits located at the
@@ -5278,12 +5301,16 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu)
                                VMXERR_VMPTRLD_INCORRECT_VMCS_REVISION_ID);
                }
 
-               new_vmcs12 = map.hva;
+               if (kvm_read_guest_offset_cached(vcpu->kvm, ghc, &hdr,
+                                                offsetof(struct vmcs12, hdr),
+                                                sizeof(hdr))) {
+                       return nested_vmx_fail(vcpu,
+                               VMXERR_VMPTRLD_INCORRECT_VMCS_REVISION_ID);
+               }
 
-               if (new_vmcs12->hdr.revision_id != VMCS12_REVISION ||
-                   (new_vmcs12->hdr.shadow_vmcs &&
+               if (hdr.revision_id != VMCS12_REVISION ||
+                   (hdr.shadow_vmcs &&
                     !nested_cpu_has_vmx_shadow_vmcs(vcpu))) {
-                       kvm_vcpu_unmap(vcpu, &map, false);
                        return nested_vmx_fail(vcpu,
                                VMXERR_VMPTRLD_INCORRECT_VMCS_REVISION_ID);
                }
@@ -5294,8 +5321,11 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu)
                 * Load VMCS12 from guest memory since it is not already
                 * cached.
                 */
-               memcpy(vmx->nested.cached_vmcs12, new_vmcs12, VMCS12_SIZE);
-               kvm_vcpu_unmap(vcpu, &map, false);
+               if (kvm_read_guest_cached(vcpu->kvm, ghc, vmx->nested.cached_vmcs12,
+                                         VMCS12_SIZE)) {
+                       return nested_vmx_fail(vcpu,
+                               VMXERR_VMPTRLD_INCORRECT_VMCS_REVISION_ID);
+               }
 
                set_current_vmptr(vmx, vmptr);
        }
index a4ead60..4df2ac2 100644 (file)
@@ -142,6 +142,16 @@ struct nested_vmx {
        struct vmcs12 *cached_shadow_vmcs12;
 
        /*
+        * GPA to HVA cache for accessing vmcs12->vmcs_link_pointer
+        */
+       struct gfn_to_hva_cache shadow_vmcs12_cache;
+
+       /*
+        * GPA to HVA cache for VMCS12
+        */
+       struct gfn_to_hva_cache vmcs12_cache;
+
+       /*
         * Indicates if the shadow vmcs or enlightened vmcs must be updated
         * with the data held by struct vmcs12.
         */
index dc7eb5f..5a403d9 100644 (file)
@@ -3307,9 +3307,9 @@ static void record_steal_time(struct kvm_vcpu *vcpu)
                             "xor %1, %1\n"
                             "2:\n"
                             _ASM_EXTABLE_UA(1b, 2b)
-                            : "+r" (st_preempted),
-                              "+&r" (err)
-                            : "m" (st->preempted));
+                            : "+q" (st_preempted),
+                              "+&r" (err),
+                              "+m" (st->preempted));
                if (err)
                        goto out;
 
@@ -4179,7 +4179,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
                r = !static_call(kvm_x86_cpu_has_accelerated_tpr)();
                break;
        case KVM_CAP_NR_VCPUS:
-               r = num_online_cpus();
+               r = min_t(unsigned int, num_online_cpus(), KVM_MAX_VCPUS);
                break;
        case KVM_CAP_MAX_VCPUS:
                r = KVM_MAX_VCPUS;
@@ -8848,7 +8848,7 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
 
        trace_kvm_hypercall(nr, a0, a1, a2, a3);
 
-       op_64_bit = is_64_bit_mode(vcpu);
+       op_64_bit = is_64_bit_hypercall(vcpu);
        if (!op_64_bit) {
                nr &= 0xFFFFFFFF;
                a0 &= 0xFFFFFFFF;
@@ -9547,12 +9547,16 @@ static void vcpu_load_eoi_exitmap(struct kvm_vcpu *vcpu)
        if (!kvm_apic_hw_enabled(vcpu->arch.apic))
                return;
 
-       if (to_hv_vcpu(vcpu))
+       if (to_hv_vcpu(vcpu)) {
                bitmap_or((ulong *)eoi_exit_bitmap,
                          vcpu->arch.ioapic_handled_vectors,
                          to_hv_synic(vcpu)->vec_bitmap, 256);
+               static_call(kvm_x86_load_eoi_exitmap)(vcpu, eoi_exit_bitmap);
+               return;
+       }
 
-       static_call(kvm_x86_load_eoi_exitmap)(vcpu, eoi_exit_bitmap);
+       static_call(kvm_x86_load_eoi_exitmap)(
+               vcpu, (u64 *)vcpu->arch.ioapic_handled_vectors);
 }
 
 void kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm,
index ea264c4..997669a 100644 (file)
@@ -153,12 +153,24 @@ static inline bool is_64_bit_mode(struct kvm_vcpu *vcpu)
 {
        int cs_db, cs_l;
 
+       WARN_ON_ONCE(vcpu->arch.guest_state_protected);
+
        if (!is_long_mode(vcpu))
                return false;
        static_call(kvm_x86_get_cs_db_l_bits)(vcpu, &cs_db, &cs_l);
        return cs_l;
 }
 
+static inline bool is_64_bit_hypercall(struct kvm_vcpu *vcpu)
+{
+       /*
+        * If running with protected guest state, the CS register is not
+        * accessible. The hypercall register values will have had to been
+        * provided in 64-bit mode, so assume the guest is in 64-bit.
+        */
+       return vcpu->arch.guest_state_protected || is_64_bit_mode(vcpu);
+}
+
 static inline bool x86_exception_has_error_code(unsigned int vector)
 {
        static u32 exception_has_error_code = BIT(DF_VECTOR) | BIT(TS_VECTOR) |
index 8f62bae..dff2bdf 100644 (file)
@@ -127,9 +127,9 @@ void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, int state)
        state_entry_time = vx->runstate_entry_time;
        state_entry_time |= XEN_RUNSTATE_UPDATE;
 
-       BUILD_BUG_ON(sizeof(((struct vcpu_runstate_info *)0)->state_entry_time) !=
+       BUILD_BUG_ON(sizeof_field(struct vcpu_runstate_info, state_entry_time) !=
                     sizeof(state_entry_time));
-       BUILD_BUG_ON(sizeof(((struct compat_vcpu_runstate_info *)0)->state_entry_time) !=
+       BUILD_BUG_ON(sizeof_field(struct compat_vcpu_runstate_info, state_entry_time) !=
                     sizeof(state_entry_time));
 
        if (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache,
@@ -144,9 +144,9 @@ void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, int state)
         */
        BUILD_BUG_ON(offsetof(struct vcpu_runstate_info, state) !=
                     offsetof(struct compat_vcpu_runstate_info, state));
-       BUILD_BUG_ON(sizeof(((struct vcpu_runstate_info *)0)->state) !=
+       BUILD_BUG_ON(sizeof_field(struct vcpu_runstate_info, state) !=
                     sizeof(vx->current_runstate));
-       BUILD_BUG_ON(sizeof(((struct compat_vcpu_runstate_info *)0)->state) !=
+       BUILD_BUG_ON(sizeof_field(struct compat_vcpu_runstate_info, state) !=
                     sizeof(vx->current_runstate));
 
        if (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache,
@@ -163,9 +163,9 @@ void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, int state)
                     offsetof(struct vcpu_runstate_info, time) - sizeof(u64));
        BUILD_BUG_ON(offsetof(struct compat_vcpu_runstate_info, state_entry_time) !=
                     offsetof(struct compat_vcpu_runstate_info, time) - sizeof(u64));
-       BUILD_BUG_ON(sizeof(((struct vcpu_runstate_info *)0)->time) !=
-                    sizeof(((struct compat_vcpu_runstate_info *)0)->time));
-       BUILD_BUG_ON(sizeof(((struct vcpu_runstate_info *)0)->time) !=
+       BUILD_BUG_ON(sizeof_field(struct vcpu_runstate_info, time) !=
+                    sizeof_field(struct compat_vcpu_runstate_info, time));
+       BUILD_BUG_ON(sizeof_field(struct vcpu_runstate_info, time) !=
                     sizeof(vx->runstate_times));
 
        if (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache,
@@ -205,9 +205,9 @@ int __kvm_xen_has_interrupt(struct kvm_vcpu *v)
        BUILD_BUG_ON(offsetof(struct vcpu_info, evtchn_upcall_pending) !=
                     offsetof(struct compat_vcpu_info, evtchn_upcall_pending));
        BUILD_BUG_ON(sizeof(rc) !=
-                    sizeof(((struct vcpu_info *)0)->evtchn_upcall_pending));
+                    sizeof_field(struct vcpu_info, evtchn_upcall_pending));
        BUILD_BUG_ON(sizeof(rc) !=
-                    sizeof(((struct compat_vcpu_info *)0)->evtchn_upcall_pending));
+                    sizeof_field(struct compat_vcpu_info, evtchn_upcall_pending));
 
        /*
         * For efficiency, this mirrors the checks for using the valid
@@ -299,7 +299,7 @@ int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data)
                break;
 
        case KVM_XEN_ATTR_TYPE_SHARED_INFO:
-               data->u.shared_info.gfn = gpa_to_gfn(kvm->arch.xen.shinfo_gfn);
+               data->u.shared_info.gfn = kvm->arch.xen.shinfo_gfn;
                r = 0;
                break;
 
@@ -698,7 +698,7 @@ int kvm_xen_hypercall(struct kvm_vcpu *vcpu)
            kvm_hv_hypercall_enabled(vcpu))
                return kvm_hv_hypercall(vcpu);
 
-       longmode = is_64_bit_mode(vcpu);
+       longmode = is_64_bit_hypercall(vcpu);
        if (!longmode) {
                params[0] = (u32)kvm_rbx_read(vcpu);
                params[1] = (u32)kvm_rcx_read(vcpu);
index 7cd0009..ef10480 100644 (file)
@@ -347,28 +347,3 @@ void acpi_device_notify_remove(struct device *dev)
 
        acpi_unbind_one(dev);
 }
-
-int acpi_dev_turn_off_if_unused(struct device *dev, void *not_used)
-{
-       struct acpi_device *adev = to_acpi_device(dev);
-
-       /*
-        * Skip device objects with device IDs, because they may be in use even
-        * if they are not companions of any physical device objects.
-        */
-       if (adev->pnp.type.hardware_id)
-               return 0;
-
-       mutex_lock(&adev->physical_node_lock);
-
-       /*
-        * Device objects without device IDs are not in use if they have no
-        * corresponding physical device objects.
-        */
-       if (list_empty(&adev->physical_node_list))
-               acpi_device_set_power(adev, ACPI_STATE_D3_COLD);
-
-       mutex_unlock(&adev->physical_node_lock);
-
-       return 0;
-}
index 8fbdc17..d91b560 100644 (file)
@@ -117,7 +117,6 @@ bool acpi_device_is_battery(struct acpi_device *adev);
 bool acpi_device_is_first_physical_node(struct acpi_device *adev,
                                        const struct device *dev);
 int acpi_bus_register_early_device(int type);
-int acpi_dev_turn_off_if_unused(struct device *dev, void *not_used);
 
 /* --------------------------------------------------------------------------
                      Device Matching and Notification
index a50f196..2c80765 100644 (file)
@@ -2564,12 +2564,6 @@ int __init acpi_scan_init(void)
                }
        }
 
-       /*
-        * Make sure that power management resources are not blocked by ACPI
-        * device objects with no users.
-        */
-       bus_for_each_dev(&acpi_bus_type, NULL, NULL, acpi_dev_turn_off_if_unused);
-
        acpi_turn_off_unused_power_resources();
 
        acpi_scan_initialized = true;
index d60f347..1e1167e 100644 (file)
@@ -438,6 +438,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        /* AMD */
        { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */
        { PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */
+       { PCI_VDEVICE(AMD, 0x7901), board_ahci_mobile }, /* AMD Green Sardine */
        /* AMD is using RAID class only for ahci controllers */
        { PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
          PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci },
index 8a6835b..f76b841 100644 (file)
@@ -2323,6 +2323,18 @@ int ahci_port_resume(struct ata_port *ap)
 EXPORT_SYMBOL_GPL(ahci_port_resume);
 
 #ifdef CONFIG_PM
+static void ahci_handle_s2idle(struct ata_port *ap)
+{
+       void __iomem *port_mmio = ahci_port_base(ap);
+       u32 devslp;
+
+       if (pm_suspend_via_firmware())
+               return;
+       devslp = readl(port_mmio + PORT_DEVSLP);
+       if ((devslp & PORT_DEVSLP_ADSE))
+               ata_msleep(ap, devslp_idle_timeout);
+}
+
 static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
 {
        const char *emsg = NULL;
@@ -2336,6 +2348,9 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
                ata_port_freeze(ap);
        }
 
+       if (acpi_storage_d3(ap->host->dev))
+               ahci_handle_s2idle(ap);
+
        ahci_rpm_put_port(ap);
        return rc;
 }
index 8a0ccb1..59ad8c9 100644 (file)
@@ -2031,8 +2031,9 @@ retry:
                        dev->horkage |= ATA_HORKAGE_NO_DMA_LOG;
                        goto retry;
                }
-               ata_dev_err(dev, "Read log page 0x%02x failed, Emask 0x%x\n",
-                           (unsigned int)page, err_mask);
+               ata_dev_err(dev,
+                           "Read log 0x%02x page 0x%02x failed, Emask 0x%x\n",
+                           (unsigned int)log, (unsigned int)page, err_mask);
        }
 
        return err_mask;
@@ -2177,6 +2178,9 @@ static void ata_dev_config_ncq_prio(struct ata_device *dev)
        struct ata_port *ap = dev->link->ap;
        unsigned int err_mask;
 
+       if (!ata_identify_page_supported(dev, ATA_LOG_SATA_SETTINGS))
+               return;
+
        err_mask = ata_read_log_page(dev,
                                     ATA_LOG_IDENTIFY_DEVICE,
                                     ATA_LOG_SATA_SETTINGS,
@@ -2453,7 +2457,8 @@ static void ata_dev_config_devslp(struct ata_device *dev)
         * Check device sleep capability. Get DevSlp timing variables
         * from SATA Settings page of Identify Device Data Log.
         */
-       if (!ata_id_has_devslp(dev->id))
+       if (!ata_id_has_devslp(dev->id) ||
+           !ata_identify_page_supported(dev, ATA_LOG_SATA_SETTINGS))
                return;
 
        err_mask = ata_read_log_page(dev,
index 4e88597..5b78e86 100644 (file)
@@ -922,7 +922,7 @@ DEVICE_ATTR(ncq_prio_enable, S_IRUGO | S_IWUSR,
            ata_ncq_prio_enable_show, ata_ncq_prio_enable_store);
 EXPORT_SYMBOL_GPL(dev_attr_ncq_prio_enable);
 
-struct attribute *ata_ncq_sdev_attrs[] = {
+static struct attribute *ata_ncq_sdev_attrs[] = {
        &dev_attr_unload_heads.attr,
        &dev_attr_ncq_prio_enable.attr,
        &dev_attr_ncq_prio_supported.attr,
index 072ed61..60d9374 100644 (file)
@@ -523,6 +523,7 @@ config GPIO_REG
 config GPIO_ROCKCHIP
        tristate "Rockchip GPIO support"
        depends on ARCH_ROCKCHIP || COMPILE_TEST
+       select GENERIC_IRQ_CHIP
        select GPIOLIB_IRQCHIP
        default ARCH_ROCKCHIP
        help
index aeec4bf..84f96b7 100644 (file)
@@ -434,7 +434,7 @@ static void virtio_gpio_event_vq(struct virtqueue *vq)
                ret = generic_handle_domain_irq(vgpio->gc.irq.domain, gpio);
                if (ret)
                        dev_err(dev, "failed to handle interrupt: %d\n", ret);
-       };
+       }
 }
 
 static void virtio_gpio_request_vq(struct virtqueue *vq)
index b9c11c2..0de66f5 100644 (file)
@@ -827,6 +827,7 @@ static int amdgpu_connector_vga_get_modes(struct drm_connector *connector)
 
        amdgpu_connector_get_edid(connector);
        ret = amdgpu_connector_ddc_get_modes(connector);
+       amdgpu_get_native_mode(connector);
 
        return ret;
 }
index 5625f77..188accb 100644 (file)
@@ -3509,6 +3509,9 @@ int amdgpu_device_init(struct amdgpu_device *adev,
                adev->rmmio_size = pci_resource_len(adev->pdev, 2);
        }
 
+       for (i = 0; i < AMD_IP_BLOCK_TYPE_NUM; i++)
+               atomic_set(&adev->pm.pwr_state[i], POWER_STATE_UNKNOWN);
+
        adev->rmmio = ioremap(adev->rmmio_base, adev->rmmio_size);
        if (adev->rmmio == NULL) {
                return -ENOMEM;
index ff70bc2..4e36694 100644 (file)
@@ -587,6 +587,9 @@ static int amdgpu_discovery_set_common_ip_blocks(struct amdgpu_device *adev)
                amdgpu_device_ip_block_add(adev, &nv_common_ip_block);
                break;
        default:
+               dev_err(adev->dev,
+                       "Failed to add common ip block(GC_HWIP:0x%x)\n",
+                       adev->ip_versions[GC_HWIP][0]);
                return -EINVAL;
        }
        return 0;
@@ -619,6 +622,9 @@ static int amdgpu_discovery_set_gmc_ip_blocks(struct amdgpu_device *adev)
                amdgpu_device_ip_block_add(adev, &gmc_v10_0_ip_block);
                break;
        default:
+               dev_err(adev->dev,
+                       "Failed to add gmc ip block(GC_HWIP:0x%x)\n",
+                       adev->ip_versions[GC_HWIP][0]);
                return -EINVAL;
        }
        return 0;
@@ -648,6 +654,9 @@ static int amdgpu_discovery_set_ih_ip_blocks(struct amdgpu_device *adev)
                amdgpu_device_ip_block_add(adev, &navi10_ih_ip_block);
                break;
        default:
+               dev_err(adev->dev,
+                       "Failed to add ih ip block(OSSSYS_HWIP:0x%x)\n",
+                       adev->ip_versions[OSSSYS_HWIP][0]);
                return -EINVAL;
        }
        return 0;
@@ -688,6 +697,9 @@ static int amdgpu_discovery_set_psp_ip_blocks(struct amdgpu_device *adev)
                amdgpu_device_ip_block_add(adev, &psp_v13_0_ip_block);
                break;
        default:
+               dev_err(adev->dev,
+                       "Failed to add psp ip block(MP0_HWIP:0x%x)\n",
+                       adev->ip_versions[MP0_HWIP][0]);
                return -EINVAL;
        }
        return 0;
@@ -726,6 +738,9 @@ static int amdgpu_discovery_set_smu_ip_blocks(struct amdgpu_device *adev)
                amdgpu_device_ip_block_add(adev, &smu_v13_0_ip_block);
                break;
        default:
+               dev_err(adev->dev,
+                       "Failed to add smu ip block(MP1_HWIP:0x%x)\n",
+                       adev->ip_versions[MP1_HWIP][0]);
                return -EINVAL;
        }
        return 0;
@@ -753,6 +768,9 @@ static int amdgpu_discovery_set_display_ip_blocks(struct amdgpu_device *adev)
                        amdgpu_device_ip_block_add(adev, &dm_ip_block);
                        break;
                default:
+                       dev_err(adev->dev,
+                               "Failed to add dm ip block(DCE_HWIP:0x%x)\n",
+                               adev->ip_versions[DCE_HWIP][0]);
                        return -EINVAL;
                }
        } else if (adev->ip_versions[DCI_HWIP][0]) {
@@ -763,6 +781,9 @@ static int amdgpu_discovery_set_display_ip_blocks(struct amdgpu_device *adev)
                        amdgpu_device_ip_block_add(adev, &dm_ip_block);
                        break;
                default:
+                       dev_err(adev->dev,
+                               "Failed to add dm ip block(DCI_HWIP:0x%x)\n",
+                               adev->ip_versions[DCI_HWIP][0]);
                        return -EINVAL;
                }
 #endif
@@ -796,6 +817,9 @@ static int amdgpu_discovery_set_gc_ip_blocks(struct amdgpu_device *adev)
                amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block);
                break;
        default:
+               dev_err(adev->dev,
+                       "Failed to add gfx ip block(GC_HWIP:0x%x)\n",
+                       adev->ip_versions[GC_HWIP][0]);
                return -EINVAL;
        }
        return 0;
@@ -829,6 +853,9 @@ static int amdgpu_discovery_set_sdma_ip_blocks(struct amdgpu_device *adev)
                amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block);
                break;
        default:
+               dev_err(adev->dev,
+                       "Failed to add sdma ip block(SDMA0_HWIP:0x%x)\n",
+                       adev->ip_versions[SDMA0_HWIP][0]);
                return -EINVAL;
        }
        return 0;
@@ -845,6 +872,9 @@ static int amdgpu_discovery_set_mm_ip_blocks(struct amdgpu_device *adev)
                                amdgpu_device_ip_block_add(adev, &uvd_v7_0_ip_block);
                        break;
                default:
+                       dev_err(adev->dev,
+                               "Failed to add uvd v7 ip block(UVD_HWIP:0x%x)\n",
+                               adev->ip_versions[UVD_HWIP][0]);
                        return -EINVAL;
                }
                switch (adev->ip_versions[VCE_HWIP][0]) {
@@ -855,6 +885,9 @@ static int amdgpu_discovery_set_mm_ip_blocks(struct amdgpu_device *adev)
                                amdgpu_device_ip_block_add(adev, &vce_v4_0_ip_block);
                        break;
                default:
+                       dev_err(adev->dev,
+                               "Failed to add VCE v4 ip block(VCE_HWIP:0x%x)\n",
+                               adev->ip_versions[VCE_HWIP][0]);
                        return -EINVAL;
                }
        } else {
@@ -893,6 +926,9 @@ static int amdgpu_discovery_set_mm_ip_blocks(struct amdgpu_device *adev)
                        amdgpu_device_ip_block_add(adev, &vcn_v3_0_ip_block);
                        break;
                default:
+                       dev_err(adev->dev,
+                               "Failed to add vcn/jpeg ip block(UVD_HWIP:0x%x)\n",
+                               adev->ip_versions[UVD_HWIP][0]);
                        return -EINVAL;
                }
        }
index 0fad2bf..567df2d 100644 (file)
@@ -386,6 +386,7 @@ struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev)
                        "%s", "xgmi_hive_info");
        if (ret) {
                dev_err(adev->dev, "XGMI: failed initializing kobject for xgmi hive\n");
+               kobject_put(&hive->kobj);
                kfree(hive);
                hive = NULL;
                goto pro_end;
index 003ba6a..93e33dd 100644 (file)
@@ -1226,6 +1226,11 @@ static int stop_cpsch(struct device_queue_manager *dqm)
        bool hanging;
 
        dqm_lock(dqm);
+       if (!dqm->sched_running) {
+               dqm_unlock(dqm);
+               return 0;
+       }
+
        if (!dqm->is_hws_hang)
                unmap_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0);
        hanging = dqm->is_hws_hang || dqm->is_resetting;
index c911b30..c27cb47 100644 (file)
@@ -4242,7 +4242,8 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
                } else if (dc_link_detect(link, DETECT_REASON_BOOT)) {
                        amdgpu_dm_update_connector_after_detect(aconnector);
                        register_backlight_device(dm, link);
-
+                       if (dm->num_of_edps)
+                               update_connector_ext_caps(aconnector);
                        if (psr_feature_enabled)
                                amdgpu_dm_set_psr_caps(link);
                }
index f1a46d1..4b9e68a 100644 (file)
@@ -98,7 +98,8 @@ enum amd_ip_block_type {
        AMD_IP_BLOCK_TYPE_ACP,
        AMD_IP_BLOCK_TYPE_VCN,
        AMD_IP_BLOCK_TYPE_MES,
-       AMD_IP_BLOCK_TYPE_JPEG
+       AMD_IP_BLOCK_TYPE_JPEG,
+       AMD_IP_BLOCK_TYPE_NUM,
 };
 
 enum amd_clockgating_state {
index 03581d5..08362d5 100644 (file)
@@ -927,6 +927,13 @@ int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block
 {
        int ret = 0;
        const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
+       enum ip_power_state pwr_state = gate ? POWER_STATE_OFF : POWER_STATE_ON;
+
+       if (atomic_read(&adev->pm.pwr_state[block_type]) == pwr_state) {
+               dev_dbg(adev->dev, "IP block%d already in the target %s state!",
+                               block_type, gate ? "gate" : "ungate");
+               return 0;
+       }
 
        switch (block_type) {
        case AMD_IP_BLOCK_TYPE_UVD:
@@ -979,6 +986,9 @@ int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block
                break;
        }
 
+       if (!ret)
+               atomic_set(&adev->pm.pwr_state[block_type], pwr_state);
+
        return ret;
 }
 
index 98f1b3d..16e3f72 100644 (file)
@@ -417,6 +417,12 @@ struct amdgpu_dpm {
        enum amd_dpm_forced_level forced_level;
 };
 
+enum ip_power_state {
+       POWER_STATE_UNKNOWN,
+       POWER_STATE_ON,
+       POWER_STATE_OFF,
+};
+
 struct amdgpu_pm {
        struct mutex            mutex;
        u32                     current_sclk;
@@ -452,6 +458,8 @@ struct amdgpu_pm {
        struct i2c_adapter smu_i2c;
        struct mutex            smu_i2c_mutex;
        struct list_head        pm_attr_list;
+
+       atomic_t                pwr_state[AMD_IP_BLOCK_TYPE_NUM];
 };
 
 #define R600_SSTU_DFLT                               0
index cbc3f99..2238ee1 100644 (file)
@@ -309,6 +309,7 @@ static int cyan_skillfish_print_clk_levels(struct smu_context *smu,
 {
        int ret = 0, size = 0;
        uint32_t cur_value = 0;
+       int i;
 
        smu_cmn_get_sysfs_buf(&buf, &size);
 
@@ -334,8 +335,6 @@ static int cyan_skillfish_print_clk_levels(struct smu_context *smu,
                size += sysfs_emit_at(buf, size, "VDDC: %7umV  %10umV\n",
                                                CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX);
                break;
-       case SMU_GFXCLK:
-       case SMU_SCLK:
        case SMU_FCLK:
        case SMU_MCLK:
        case SMU_SOCCLK:
@@ -346,6 +345,25 @@ static int cyan_skillfish_print_clk_levels(struct smu_context *smu,
                        return ret;
                size += sysfs_emit_at(buf, size, "0: %uMhz *\n", cur_value);
                break;
+       case SMU_SCLK:
+       case SMU_GFXCLK:
+               ret = cyan_skillfish_get_current_clk_freq(smu, clk_type, &cur_value);
+               if (ret)
+                       return ret;
+               if (cur_value  == CYAN_SKILLFISH_SCLK_MAX)
+                       i = 2;
+               else if (cur_value == CYAN_SKILLFISH_SCLK_MIN)
+                       i = 0;
+               else
+                       i = 1;
+               size += sysfs_emit_at(buf, size, "0: %uMhz %s\n", CYAN_SKILLFISH_SCLK_MIN,
+                               i == 0 ? "*" : "");
+               size += sysfs_emit_at(buf, size, "1: %uMhz %s\n",
+                               i == 1 ? cur_value : cyan_skillfish_sclk_default,
+                               i == 1 ? "*" : "");
+               size += sysfs_emit_at(buf, size, "2: %uMhz %s\n", CYAN_SKILLFISH_SCLK_MAX,
+                               i == 2 ? "*" : "");
+               break;
        default:
                dev_warn(smu->adev->dev, "Unsupported clock type\n");
                return ret;
index 71161f6..60a5570 100644 (file)
@@ -1265,7 +1265,7 @@ static int navi10_print_clk_levels(struct smu_context *smu,
                        enum smu_clk_type clk_type, char *buf)
 {
        uint16_t *curve_settings;
-       int i, size = 0, ret = 0;
+       int i, levels, size = 0, ret = 0;
        uint32_t cur_value = 0, value = 0, count = 0;
        uint32_t freq_values[3] = {0};
        uint32_t mark_index = 0;
@@ -1319,14 +1319,17 @@ static int navi10_print_clk_levels(struct smu_context *smu,
                        freq_values[1] = cur_value;
                        mark_index = cur_value == freq_values[0] ? 0 :
                                     cur_value == freq_values[2] ? 2 : 1;
-                       if (mark_index != 1)
-                               freq_values[1] = (freq_values[0] + freq_values[2]) / 2;
 
-                       for (i = 0; i < 3; i++) {
+                       levels = 3;
+                       if (mark_index != 1) {
+                               levels = 2;
+                               freq_values[1] = freq_values[2];
+                       }
+
+                       for (i = 0; i < levels; i++) {
                                size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, freq_values[i],
                                                i == mark_index ? "*" : "");
                        }
-
                }
                break;
        case SMU_PCIE:
index 421f38e..c02ed65 100644 (file)
@@ -683,6 +683,7 @@ static int vangogh_print_clk_levels(struct smu_context *smu,
        int i, size = 0, ret = 0;
        uint32_t cur_value = 0, value = 0, count = 0;
        bool cur_value_match_level = false;
+       uint32_t min, max;
 
        memset(&metrics, 0, sizeof(metrics));
 
@@ -743,6 +744,13 @@ static int vangogh_print_clk_levels(struct smu_context *smu,
                if (ret)
                        return ret;
                break;
+       case SMU_GFXCLK:
+       case SMU_SCLK:
+               ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetGfxclkFrequency, 0, &cur_value);
+               if (ret) {
+                       return ret;
+               }
+               break;
        default:
                break;
        }
@@ -768,6 +776,24 @@ static int vangogh_print_clk_levels(struct smu_context *smu,
                if (!cur_value_match_level)
                        size += sysfs_emit_at(buf, size, "   %uMhz *\n", cur_value);
                break;
+       case SMU_GFXCLK:
+       case SMU_SCLK:
+               min = (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq;
+               max = (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq;
+               if (cur_value  == max)
+                       i = 2;
+               else if (cur_value == min)
+                       i = 0;
+               else
+                       i = 1;
+               size += sysfs_emit_at(buf, size, "0: %uMhz %s\n", min,
+                               i == 0 ? "*" : "");
+               size += sysfs_emit_at(buf, size, "1: %uMhz %s\n",
+                               i == 1 ? cur_value : VANGOGH_UMD_PSTATE_STANDARD_GFXCLK,
+                               i == 1 ? "*" : "");
+               size += sysfs_emit_at(buf, size, "2: %uMhz %s\n", max,
+                               i == 2 ? "*" : "");
+               break;
        default:
                break;
        }
index 8215bbf..caf1775 100644 (file)
@@ -697,6 +697,11 @@ static int yellow_carp_get_current_clk_freq(struct smu_context *smu,
        case SMU_FCLK:
                return smu_cmn_send_smc_msg_with_param(smu,
                                SMU_MSG_GetFclkFrequency, 0, value);
+       case SMU_GFXCLK:
+       case SMU_SCLK:
+               return smu_cmn_send_smc_msg_with_param(smu,
+                               SMU_MSG_GetGfxclkFrequency, 0, value);
+               break;
        default:
                return -EINVAL;
        }
@@ -967,6 +972,7 @@ static int yellow_carp_print_clk_levels(struct smu_context *smu,
 {
        int i, size = 0, ret = 0;
        uint32_t cur_value = 0, value = 0, count = 0;
+       uint32_t min, max;
 
        smu_cmn_get_sysfs_buf(&buf, &size);
 
@@ -1005,6 +1011,27 @@ static int yellow_carp_print_clk_levels(struct smu_context *smu,
                                        cur_value == value ? "*" : "");
                }
                break;
+       case SMU_GFXCLK:
+       case SMU_SCLK:
+               ret = yellow_carp_get_current_clk_freq(smu, clk_type, &cur_value);
+               if (ret)
+                       goto print_clk_out;
+               min = (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq;
+               max = (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq;
+               if (cur_value  == max)
+                       i = 2;
+               else if (cur_value == min)
+                       i = 0;
+               else
+                       i = 1;
+               size += sysfs_emit_at(buf, size, "0: %uMhz %s\n", min,
+                               i == 0 ? "*" : "");
+               size += sysfs_emit_at(buf, size, "1: %uMhz %s\n",
+                               i == 1 ? cur_value : YELLOW_CARP_UMD_PSTATE_GFXCLK,
+                               i == 1 ? "*" : "");
+               size += sysfs_emit_at(buf, size, "2: %uMhz %s\n", max,
+                               i == 2 ? "*" : "");
+               break;
        default:
                break;
        }
index b3ad835..a9205a8 100644 (file)
@@ -24,5 +24,6 @@
 #define __YELLOW_CARP_PPT_H__
 
 extern void yellow_carp_set_ppt_funcs(struct smu_context *smu);
+#define YELLOW_CARP_UMD_PSTATE_GFXCLK       1100
 
 #endif
index 843d2cb..ea6f50c 100644 (file)
@@ -139,9 +139,13 @@ static void __smu_cmn_reg_print_error(struct smu_context *smu,
        const char *message = smu_get_message_name(smu, msg);
 
        switch (reg_c2pmsg_90) {
-       case SMU_RESP_NONE:
+       case SMU_RESP_NONE: {
+               u32 msg_idx = RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_66);
+               u32 prm     = RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82);
                dev_err_ratelimited(adev->dev,
-                                   "SMU: I'm not done with your previous command!");
+                                   "SMU: I'm not done with your previous command: SMN_C2PMSG_66:0x%08X SMN_C2PMSG_82:0x%08X",
+                                   msg_idx, prm);
+       }
                break;
        case SMU_RESP_OK:
                /* The SMU executed the command. It completed with a
index d533881..9d05674 100644 (file)
@@ -210,8 +210,13 @@ void drm_gem_cma_free_object(struct drm_gem_object *gem_obj)
                        dma_buf_vunmap(gem_obj->import_attach->dmabuf, &map);
                drm_prime_gem_destroy(gem_obj, cma_obj->sgt);
        } else if (cma_obj->vaddr) {
-               dma_free_wc(gem_obj->dev->dev, cma_obj->base.size,
-                           cma_obj->vaddr, cma_obj->paddr);
+               if (cma_obj->map_noncoherent)
+                       dma_free_noncoherent(gem_obj->dev->dev, cma_obj->base.size,
+                                            cma_obj->vaddr, cma_obj->paddr,
+                                            DMA_TO_DEVICE);
+               else
+                       dma_free_wc(gem_obj->dev->dev, cma_obj->base.size,
+                                   cma_obj->vaddr, cma_obj->paddr);
        }
 
        drm_gem_object_release(gem_obj);
index 168c84a..71fbdcd 100644 (file)
@@ -696,10 +696,7 @@ static void gen11_dsi_map_pll(struct intel_encoder *encoder,
        intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, val);
 
        for_each_dsi_phy(phy, intel_dsi->phys) {
-               if (DISPLAY_VER(dev_priv) >= 12)
-                       val |= ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy);
-               else
-                       val &= ~ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy);
+               val &= ~ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy);
        }
        intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, val);
 
@@ -1135,8 +1132,6 @@ static void
 gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder,
                              const struct intel_crtc_state *crtc_state)
 {
-       struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
-
        /* step 4a: power up all lanes of the DDI used by DSI */
        gen11_dsi_power_up_lanes(encoder);
 
@@ -1162,8 +1157,7 @@ gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder,
        gen11_dsi_configure_transcoder(encoder, crtc_state);
 
        /* Step 4l: Gate DDI clocks */
-       if (DISPLAY_VER(dev_priv) == 11)
-               gen11_dsi_gate_clocks(encoder);
+       gen11_dsi_gate_clocks(encoder);
 }
 
 static void gen11_dsi_powerup_panel(struct intel_encoder *encoder)
@@ -1271,7 +1265,8 @@ static void adlp_set_lp_hs_wakeup_gb(struct intel_encoder *encoder)
        if (DISPLAY_VER(i915) == 13) {
                for_each_dsi_port(port, intel_dsi->ports)
                        intel_de_rmw(i915, TGL_DSI_CHKN_REG(port),
-                                    TGL_DSI_CHKN_LSHS_GB, 0x4);
+                                    TGL_DSI_CHKN_LSHS_GB_MASK,
+                                    TGL_DSI_CHKN_LSHS_GB(4));
        }
 }
 
index 38b47e7..c48557d 100644 (file)
@@ -3080,8 +3080,8 @@ guc_create_parallel(struct intel_engine_cs **engines,
 
                ce = intel_engine_create_virtual(siblings, num_siblings,
                                                 FORCE_VIRTUAL);
-               if (!ce) {
-                       err = ERR_PTR(-ENOMEM);
+               if (IS_ERR(ce)) {
+                       err = ERR_CAST(ce);
                        goto unwind;
                }
 
index da9055c..bcee121 100644 (file)
@@ -11717,7 +11717,9 @@ enum skl_power_gate {
 #define TGL_DSI_CHKN_REG(port)         _MMIO_PORT(port,        \
                                                    _TGL_DSI_CHKN_REG_0, \
                                                    _TGL_DSI_CHKN_REG_1)
-#define TGL_DSI_CHKN_LSHS_GB                   REG_GENMASK(15, 12)
+#define TGL_DSI_CHKN_LSHS_GB_MASK              REG_GENMASK(15, 12)
+#define TGL_DSI_CHKN_LSHS_GB(byte_clocks)      REG_FIELD_PREP(TGL_DSI_CHKN_LSHS_GB_MASK, \
+                                                              (byte_clocks))
 
 /* Display Stream Splitter Control */
 #define DSS_CTL1                               _MMIO(0x67400)
index 6e3c450..3ff4934 100644 (file)
@@ -62,7 +62,6 @@ gv100_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet,
                nvkm_wr32(device, 0x6f0108 + hdmi, vendor_infoframe.header);
                nvkm_wr32(device, 0x6f010c + hdmi, vendor_infoframe.subpack0_low);
                nvkm_wr32(device, 0x6f0110 + hdmi, vendor_infoframe.subpack0_high);
-               nvkm_wr32(device, 0x6f0110 + hdmi, 0x00000000);
                nvkm_wr32(device, 0x6f0114 + hdmi, 0x00000000);
                nvkm_wr32(device, 0x6f0118 + hdmi, 0x00000000);
                nvkm_wr32(device, 0x6f011c + hdmi, 0x00000000);
index 5bc5f77..f91fb31 100644 (file)
@@ -704,9 +704,13 @@ int drm_sched_job_add_implicit_dependencies(struct drm_sched_job *job,
        int ret;
 
        dma_resv_for_each_fence(&cursor, obj->resv, write, fence) {
+               /* Make sure to grab an additional ref on the added fence */
+               dma_fence_get(fence);
                ret = drm_sched_job_add_dependency(job, fence);
-               if (ret)
+               if (ret) {
+                       dma_fence_put(fence);
                        return ret;
+               }
        }
        return 0;
 }
index 5755f04..8c796de 100644 (file)
@@ -46,6 +46,7 @@ config DRM_SUN6I_DSI
        default MACH_SUN8I
        select CRC_CCITT
        select DRM_MIPI_DSI
+       select RESET_CONTROLLER
        select PHY_SUN6I_MIPI_DPHY
        help
          Choose this option if you want have an Allwinner SoC with
index 7f11ea0..ca873a3 100644 (file)
@@ -480,7 +480,7 @@ module_param(pressure_report_delay, uint, (S_IRUGO | S_IWUSR));
 MODULE_PARM_DESC(pressure_report_delay, "Delay in secs in reporting pressure");
 static atomic_t trans_id = ATOMIC_INIT(0);
 
-static int dm_ring_size = 20 * 1024;
+static int dm_ring_size = VMBUS_RING_SIZE(16 * 1024);
 
 /*
  * Driver specific state.
index fedc0fa..f5aacaf 100644 (file)
@@ -1906,7 +1906,8 @@ static int nldev_stat_set_mode_doit(struct sk_buff *msg,
        int ret;
 
        /* Currently only counter for QP is supported */
-       if (nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_RES]) != RDMA_NLDEV_ATTR_RES_QP)
+       if (!tb[RDMA_NLDEV_ATTR_STAT_RES] ||
+           nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_RES]) != RDMA_NLDEV_ATTR_RES_QP)
                return -EINVAL;
 
        mode = nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_MODE]);
index 692d5ff..c18634b 100644 (file)
@@ -1232,6 +1232,9 @@ static struct ib_qp *create_qp(struct ib_device *dev, struct ib_pd *pd,
        INIT_LIST_HEAD(&qp->rdma_mrs);
        INIT_LIST_HEAD(&qp->sig_mrs);
 
+       qp->send_cq = attr->send_cq;
+       qp->recv_cq = attr->recv_cq;
+
        rdma_restrack_new(&qp->res, RDMA_RESTRACK_QP);
        WARN_ONCE(!udata && !caller, "Missing kernel QP owner");
        rdma_restrack_set_name(&qp->res, udata ? NULL : caller);
index ed9fa0d..dc9211f 100644 (file)
@@ -1628,8 +1628,7 @@ static int init_cntr_names(const char *names_in, const size_t names_len,
                        n++;
 
        names_out =
-               kmalloc((n + num_extra_names) * sizeof(struct rdma_stat_desc) +
-                               names_len,
+               kzalloc((n + num_extra_names) * sizeof(*q) + names_len,
                        GFP_KERNEL);
        if (!names_out) {
                *num_cntrs = 0;
@@ -1637,7 +1636,7 @@ static int init_cntr_names(const char *names_in, const size_t names_len,
                return -ENOMEM;
        }
 
-       p = names_out + (n + num_extra_names) * sizeof(struct rdma_stat_desc);
+       p = names_out + (n + num_extra_names) * sizeof(*q);
        memcpy(p, names_in, names_len);
 
        q = (struct rdma_stat_desc *)names_out;
index ceca059..0d2fa33 100644 (file)
@@ -2215,6 +2215,11 @@ static const struct ib_device_ops mlx4_ib_hw_stats_ops = {
        .get_hw_stats = mlx4_ib_get_hw_stats,
 };
 
+static const struct ib_device_ops mlx4_ib_hw_stats_ops1 = {
+       .alloc_hw_device_stats = mlx4_ib_alloc_hw_device_stats,
+       .get_hw_stats = mlx4_ib_get_hw_stats,
+};
+
 static int mlx4_ib_alloc_diag_counters(struct mlx4_ib_dev *ibdev)
 {
        struct mlx4_ib_diag_counters *diag = ibdev->diag_counters;
@@ -2227,9 +2232,16 @@ static int mlx4_ib_alloc_diag_counters(struct mlx4_ib_dev *ibdev)
                return 0;
 
        for (i = 0; i < MLX4_DIAG_COUNTERS_TYPES; i++) {
-               /* i == 1 means we are building port counters */
-               if (i && !per_port)
-                       continue;
+               /*
+                * i == 1 means we are building port counters, set a different
+                * stats ops without port stats callback.
+                */
+               if (i && !per_port) {
+                       ib_set_device_ops(&ibdev->ib_dev,
+                                         &mlx4_ib_hw_stats_ops1);
+
+                       return 0;
+               }
 
                ret = __mlx4_ib_alloc_diag_counters(ibdev, &diag[i].descs,
                                                    &diag[i].offset,
index 47a04c3..b732ee9 100644 (file)
@@ -3286,7 +3286,7 @@ static void __exit amt_fini(void)
 {
        rtnl_link_unregister(&amt_link_ops);
        unregister_netdevice_notifier(&amt_notifier_block);
-       cancel_delayed_work(&source_gc_wq);
+       cancel_delayed_work_sync(&source_gc_wq);
        __amt_source_gc_work();
        destroy_workqueue(amt_wq);
 }
index fc0e660..3f1704c 100644 (file)
@@ -559,6 +559,11 @@ int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
                        goto err_exit;
 
                if (fw.len == 0xFFFFU) {
+                       if (sw.len > sizeof(self->rpc)) {
+                               printk(KERN_INFO "Invalid sw len: %x\n", sw.len);
+                               err = -EINVAL;
+                               goto err_exit;
+                       }
                        err = hw_atl_utils_fw_rpc_call(self, sw.len);
                        if (err < 0)
                                goto err_exit;
@@ -567,6 +572,11 @@ int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
 
        if (rpc) {
                if (fw.len) {
+                       if (fw.len > sizeof(self->rpc)) {
+                               printk(KERN_INFO "Invalid fw len: %x\n", fw.len);
+                               err = -EINVAL;
+                               goto err_exit;
+                       }
                        err =
                        hw_atl_utils_fw_downld_dwords(self,
                                                      self->rpc_addr,
index 80263c3..4a83c99 100644 (file)
@@ -127,9 +127,9 @@ struct ax88796c_device {
                #define AX_PRIV_FLAGS_MASK      (AX_CAP_COMP)
 
        unsigned long           flags;
-               #define EVENT_INTR              BIT(0)
-               #define EVENT_TX                BIT(1)
-               #define EVENT_SET_MULTI         BIT(2)
+               #define EVENT_INTR              0
+               #define EVENT_TX                1
+               #define EVENT_SET_MULTI         2
 
 };
 
index 1835d2e..fc7fce6 100644 (file)
@@ -635,11 +635,13 @@ static int bnx2x_ilt_client_mem_op(struct bnx2x *bp, int cli_num,
 {
        int i, rc;
        struct bnx2x_ilt *ilt = BP_ILT(bp);
-       struct ilt_client_info *ilt_cli = &ilt->clients[cli_num];
+       struct ilt_client_info *ilt_cli;
 
        if (!ilt || !ilt->lines)
                return -1;
 
+       ilt_cli = &ilt->clients[cli_num];
+
        if (ilt_cli->flags & (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM))
                return 0;
 
index d0d5da9..4c9507d 100644 (file)
@@ -2258,6 +2258,16 @@ static inline void bnxt_db_write(struct bnxt *bp, struct bnxt_db_info *db,
        }
 }
 
+/* Must hold rtnl_lock */
+static inline bool bnxt_sriov_cfg(struct bnxt *bp)
+{
+#if defined(CONFIG_BNXT_SRIOV)
+       return BNXT_PF(bp) && (bp->pf.active_vfs || bp->sriov_cfg);
+#else
+       return false;
+#endif
+}
+
 extern const u16 bnxt_lhint_arr[];
 
 int bnxt_alloc_rx_data(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
index 5c464ea..951c4c5 100644 (file)
@@ -360,7 +360,7 @@ bnxt_dl_livepatch_report_err(struct bnxt *bp, struct netlink_ext_ack *extack,
                NL_SET_ERR_MSG_MOD(extack, "Live patch already applied");
                break;
        default:
-               netdev_err(bp->dev, "Unexpected live patch error: %hhd\n", err);
+               netdev_err(bp->dev, "Unexpected live patch error: %d\n", err);
                NL_SET_ERR_MSG_MOD(extack, "Failed to activate live patch");
                break;
        }
@@ -441,12 +441,13 @@ static int bnxt_dl_reload_down(struct devlink *dl, bool netns_change,
 
        switch (action) {
        case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: {
-               if (BNXT_PF(bp) && bp->pf.active_vfs) {
+               rtnl_lock();
+               if (bnxt_sriov_cfg(bp)) {
                        NL_SET_ERR_MSG_MOD(extack,
-                                          "reload is unsupported when VFs are allocated");
+                                          "reload is unsupported while VFs are allocated or being configured");
+                       rtnl_unlock();
                        return -EOPNOTSUPP;
                }
-               rtnl_lock();
                if (bp->dev->reg_state == NETREG_UNREGISTERED) {
                        rtnl_unlock();
                        return -ENODEV;
index e6a4a76..1471b61 100644 (file)
@@ -1868,7 +1868,7 @@ static int bnxt_tc_setup_indr_block_cb(enum tc_setup_type type,
        struct flow_cls_offload *flower = type_data;
        struct bnxt *bp = priv->bp;
 
-       if (flower->common.chain_index)
+       if (!tc_cls_can_offload_and_chain0(bp->dev, type_data))
                return -EOPNOTSUPP;
 
        switch (type) {
index 13121c4..71730ef 100644 (file)
@@ -4709,6 +4709,10 @@ type3_infoblock(struct net_device *dev, u_char count, u_char *p)
         lp->ibn = 3;
         lp->active = *p++;
        if (MOTO_SROM_BUG) lp->active = 0;
+       /* if (MOTO_SROM_BUG) statement indicates lp->active could
+        * be 8 (i.e. the size of array lp->phy) */
+       if (WARN_ON(lp->active >= ARRAY_SIZE(lp->phy)))
+               return -EINVAL;
        lp->phy[lp->active].gep = (*p ? p : NULL); p += (2 * (*p) + 1);
        lp->phy[lp->active].rst = (*p ? p : NULL); p += (2 * (*p) + 1);
        lp->phy[lp->active].mc  = get_unaligned_le16(p); p += 2;
@@ -5000,19 +5004,23 @@ mii_get_phy(struct net_device *dev)
        }
        if ((j == limit) && (i < DE4X5_MAX_MII)) {
            for (k=0; k < DE4X5_MAX_PHY && lp->phy[k].id; k++);
-           lp->phy[k].addr = i;
-           lp->phy[k].id = id;
-           lp->phy[k].spd.reg = GENERIC_REG;      /* ANLPA register         */
-           lp->phy[k].spd.mask = GENERIC_MASK;    /* 100Mb/s technologies   */
-           lp->phy[k].spd.value = GENERIC_VALUE;  /* TX & T4, H/F Duplex    */
-           lp->mii_cnt++;
-           lp->active++;
-           printk("%s: Using generic MII device control. If the board doesn't operate,\nplease mail the following dump to the author:\n", dev->name);
-           j = de4x5_debug;
-           de4x5_debug |= DEBUG_MII;
-           de4x5_dbg_mii(dev, k);
-           de4x5_debug = j;
-           printk("\n");
+           if (k < DE4X5_MAX_PHY) {
+               lp->phy[k].addr = i;
+               lp->phy[k].id = id;
+               lp->phy[k].spd.reg = GENERIC_REG;      /* ANLPA register         */
+               lp->phy[k].spd.mask = GENERIC_MASK;    /* 100Mb/s technologies   */
+               lp->phy[k].spd.value = GENERIC_VALUE;  /* TX & T4, H/F Duplex    */
+               lp->mii_cnt++;
+               lp->active++;
+               printk("%s: Using generic MII device control. If the board doesn't operate,\nplease mail the following dump to the author:\n", dev->name);
+               j = de4x5_debug;
+               de4x5_debug |= DEBUG_MII;
+               de4x5_dbg_mii(dev, k);
+               de4x5_debug = j;
+               printk("\n");
+           } else {
+               goto purgatory;
+           }
        }
     }
   purgatory:
index 714e961..6451c83 100644 (file)
@@ -4550,10 +4550,10 @@ static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev)
 
        fsl_mc_portal_free(priv->mc_io);
 
-       free_netdev(net_dev);
-
        dev_dbg(net_dev->dev.parent, "Removed interface %s\n", net_dev->name);
 
+       free_netdev(net_dev);
+
        return 0;
 }
 
index 23d9cbf..740850b 100644 (file)
@@ -400,6 +400,10 @@ static void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port,
                return;
 
        if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) {
+               /* DSAF_MAX_PORT_NUM is 6, but DSAF_GE_NUM is 8.
+                  We need check to prevent array overflow */
+               if (port >= DSAF_MAX_PORT_NUM)
+                       return;
                reg_val_1  = 0x1 << port;
                port_rst_off = dsaf_dev->mac_cb[port]->port_rst_off;
                /* there is difference between V1 and V2 in register.*/
index 5039a25..0bf3d47 100644 (file)
@@ -3003,9 +3003,10 @@ static void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake)
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct nic *nic = netdev_priv(netdev);
 
+       netif_device_detach(netdev);
+
        if (netif_running(netdev))
                e100_down(nic);
-       netif_device_detach(netdev);
 
        if ((nic->flags & wol_magic) | e100_asf(nic)) {
                /* enable reverse auto-negotiation */
@@ -3022,7 +3023,7 @@ static void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake)
                *enable_wake = false;
        }
 
-       pci_clear_master(pdev);
+       pci_disable_device(pdev);
 }
 
 static int __e100_power_off(struct pci_dev *pdev, bool wake)
@@ -3042,8 +3043,6 @@ static int __maybe_unused e100_suspend(struct device *dev_d)
 
        __e100_shutdown(to_pci_dev(dev_d), &wake);
 
-       device_wakeup_disable(dev_d);
-
        return 0;
 }
 
@@ -3051,6 +3050,14 @@ static int __maybe_unused e100_resume(struct device *dev_d)
 {
        struct net_device *netdev = dev_get_drvdata(dev_d);
        struct nic *nic = netdev_priv(netdev);
+       int err;
+
+       err = pci_enable_device(to_pci_dev(dev_d));
+       if (err) {
+               netdev_err(netdev, "Resume cannot enable PCI device, aborting\n");
+               return err;
+       }
+       pci_set_master(to_pci_dev(dev_d));
 
        /* disable reverse auto-negotiation */
        if (nic->phy == phy_82552_v) {
@@ -3062,10 +3069,11 @@ static int __maybe_unused e100_resume(struct device *dev_d)
                           smartspeed & ~(E100_82552_REV_ANEG));
        }
 
-       netif_device_attach(netdev);
        if (netif_running(netdev))
                e100_up(nic);
 
+       netif_device_attach(netdev);
+
        return 0;
 }
 
index 3d528fb..4d939af 100644 (file)
@@ -161,6 +161,7 @@ enum i40e_vsi_state_t {
        __I40E_VSI_OVERFLOW_PROMISC,
        __I40E_VSI_REINIT_REQUESTED,
        __I40E_VSI_DOWN_REQUESTED,
+       __I40E_VSI_RELEASING,
        /* This must be last as it determines the size of the BITMAP */
        __I40E_VSI_STATE_SIZE__,
 };
@@ -1247,6 +1248,7 @@ void i40e_ptp_restore_hw_time(struct i40e_pf *pf);
 void i40e_ptp_init(struct i40e_pf *pf);
 void i40e_ptp_stop(struct i40e_pf *pf);
 int i40e_ptp_alloc_pins(struct i40e_pf *pf);
+int i40e_update_adq_vsi_queues(struct i40e_vsi *vsi, int vsi_offset);
 int i40e_is_vsi_uplink_mode_veb(struct i40e_vsi *vsi);
 i40e_status i40e_get_partition_bw_setting(struct i40e_pf *pf);
 i40e_status i40e_set_partition_bw_setting(struct i40e_pf *pf);
index ba86213..e118cf9 100644 (file)
@@ -1790,6 +1790,7 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
                                     bool is_add)
 {
        struct i40e_pf *pf = vsi->back;
+       u16 num_tc_qps = 0;
        u16 sections = 0;
        u8 netdev_tc = 0;
        u16 numtc = 1;
@@ -1797,13 +1798,33 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
        u8 offset;
        u16 qmap;
        int i;
-       u16 num_tc_qps = 0;
 
        sections = I40E_AQ_VSI_PROP_QUEUE_MAP_VALID;
        offset = 0;
+       /* zero out queue mapping, it will get updated on the end of the function */
+       memset(ctxt->info.queue_mapping, 0, sizeof(ctxt->info.queue_mapping));
+
+       if (vsi->type == I40E_VSI_MAIN) {
+               /* This code helps add more queue to the VSI if we have
+                * more cores than RSS can support, the higher cores will
+                * be served by ATR or other filters. Furthermore, the
+                * non-zero req_queue_pairs says that user requested a new
+                * queue count via ethtool's set_channels, so use this
+                * value for queues distribution across traffic classes
+                */
+               if (vsi->req_queue_pairs > 0)
+                       vsi->num_queue_pairs = vsi->req_queue_pairs;
+               else if (pf->flags & I40E_FLAG_MSIX_ENABLED)
+                       vsi->num_queue_pairs = pf->num_lan_msix;
+       }
 
        /* Number of queues per enabled TC */
-       num_tc_qps = vsi->alloc_queue_pairs;
+       if (vsi->type == I40E_VSI_MAIN ||
+           (vsi->type == I40E_VSI_SRIOV && vsi->num_queue_pairs != 0))
+               num_tc_qps = vsi->num_queue_pairs;
+       else
+               num_tc_qps = vsi->alloc_queue_pairs;
+
        if (enabled_tc && (vsi->back->flags & I40E_FLAG_DCB_ENABLED)) {
                /* Find numtc from enabled TC bitmap */
                for (i = 0, numtc = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
@@ -1881,15 +1902,11 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
                }
                ctxt->info.tc_mapping[i] = cpu_to_le16(qmap);
        }
-
-       /* Set actual Tx/Rx queue pairs */
-       vsi->num_queue_pairs = offset;
-       if ((vsi->type == I40E_VSI_MAIN) && (numtc == 1)) {
-               if (vsi->req_queue_pairs > 0)
-                       vsi->num_queue_pairs = vsi->req_queue_pairs;
-               else if (pf->flags & I40E_FLAG_MSIX_ENABLED)
-                       vsi->num_queue_pairs = pf->num_lan_msix;
-       }
+       /* Do not change previously set num_queue_pairs for PFs and VFs*/
+       if ((vsi->type == I40E_VSI_MAIN && numtc != 1) ||
+           (vsi->type == I40E_VSI_SRIOV && vsi->num_queue_pairs == 0) ||
+           (vsi->type != I40E_VSI_MAIN && vsi->type != I40E_VSI_SRIOV))
+               vsi->num_queue_pairs = offset;
 
        /* Scheduler section valid can only be set for ADD VSI */
        if (is_add) {
@@ -2623,7 +2640,8 @@ static void i40e_sync_filters_subtask(struct i40e_pf *pf)
 
        for (v = 0; v < pf->num_alloc_vsi; v++) {
                if (pf->vsi[v] &&
-                   (pf->vsi[v]->flags & I40E_VSI_FLAG_FILTER_CHANGED)) {
+                   (pf->vsi[v]->flags & I40E_VSI_FLAG_FILTER_CHANGED) &&
+                   !test_bit(__I40E_VSI_RELEASING, pf->vsi[v]->state)) {
                        int ret = i40e_sync_vsi_filters(pf->vsi[v]);
 
                        if (ret) {
@@ -5427,6 +5445,58 @@ static void i40e_vsi_update_queue_map(struct i40e_vsi *vsi,
 }
 
 /**
+ * i40e_update_adq_vsi_queues - update queue mapping for ADq VSI
+ * @vsi: the VSI being reconfigured
+ * @vsi_offset: offset from main VF VSI
+ */
+int i40e_update_adq_vsi_queues(struct i40e_vsi *vsi, int vsi_offset)
+{
+       struct i40e_vsi_context ctxt = {};
+       struct i40e_pf *pf;
+       struct i40e_hw *hw;
+       int ret;
+
+       if (!vsi)
+               return I40E_ERR_PARAM;
+       pf = vsi->back;
+       hw = &pf->hw;
+
+       ctxt.seid = vsi->seid;
+       ctxt.pf_num = hw->pf_id;
+       ctxt.vf_num = vsi->vf_id + hw->func_caps.vf_base_id + vsi_offset;
+       ctxt.uplink_seid = vsi->uplink_seid;
+       ctxt.connection_type = I40E_AQ_VSI_CONN_TYPE_NORMAL;
+       ctxt.flags = I40E_AQ_VSI_TYPE_VF;
+       ctxt.info = vsi->info;
+
+       i40e_vsi_setup_queue_map(vsi, &ctxt, vsi->tc_config.enabled_tc,
+                                false);
+       if (vsi->reconfig_rss) {
+               vsi->rss_size = min_t(int, pf->alloc_rss_size,
+                                     vsi->num_queue_pairs);
+               ret = i40e_vsi_config_rss(vsi);
+               if (ret) {
+                       dev_info(&pf->pdev->dev, "Failed to reconfig rss for num_queues\n");
+                       return ret;
+               }
+               vsi->reconfig_rss = false;
+       }
+
+       ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+       if (ret) {
+               dev_info(&pf->pdev->dev, "Update vsi config failed, err %s aq_err %s\n",
+                        i40e_stat_str(hw, ret),
+                        i40e_aq_str(hw, hw->aq.asq_last_status));
+               return ret;
+       }
+       /* update the local VSI info with updated queue map */
+       i40e_vsi_update_queue_map(vsi, &ctxt);
+       vsi->info.valid_sections = 0;
+
+       return ret;
+}
+
+/**
  * i40e_vsi_config_tc - Configure VSI Tx Scheduler for given TC map
  * @vsi: VSI to be configured
  * @enabled_tc: TC bitmap
@@ -5717,24 +5787,6 @@ static void i40e_remove_queue_channels(struct i40e_vsi *vsi)
 }
 
 /**
- * i40e_is_any_channel - channel exist or not
- * @vsi: ptr to VSI to which channels are associated with
- *
- * Returns true or false if channel(s) exist for associated VSI or not
- **/
-static bool i40e_is_any_channel(struct i40e_vsi *vsi)
-{
-       struct i40e_channel *ch, *ch_tmp;
-
-       list_for_each_entry_safe(ch, ch_tmp, &vsi->ch_list, list) {
-               if (ch->initialized)
-                       return true;
-       }
-
-       return false;
-}
-
-/**
  * i40e_get_max_queues_for_channel
  * @vsi: ptr to VSI to which channels are associated with
  *
@@ -6240,26 +6292,15 @@ int i40e_create_queue_channel(struct i40e_vsi *vsi,
        /* By default we are in VEPA mode, if this is the first VF/VMDq
         * VSI to be added switch to VEB mode.
         */
-       if ((!(pf->flags & I40E_FLAG_VEB_MODE_ENABLED)) ||
-           (!i40e_is_any_channel(vsi))) {
-               if (!is_power_of_2(vsi->tc_config.tc_info[0].qcount)) {
-                       dev_dbg(&pf->pdev->dev,
-                               "Failed to create channel. Override queues (%u) not power of 2\n",
-                               vsi->tc_config.tc_info[0].qcount);
-                       return -EINVAL;
-               }
 
-               if (!(pf->flags & I40E_FLAG_VEB_MODE_ENABLED)) {
-                       pf->flags |= I40E_FLAG_VEB_MODE_ENABLED;
+       if (!(pf->flags & I40E_FLAG_VEB_MODE_ENABLED)) {
+               pf->flags |= I40E_FLAG_VEB_MODE_ENABLED;
 
-                       if (vsi->type == I40E_VSI_MAIN) {
-                               if (pf->flags & I40E_FLAG_TC_MQPRIO)
-                                       i40e_do_reset(pf, I40E_PF_RESET_FLAG,
-                                                     true);
-                               else
-                                       i40e_do_reset_safe(pf,
-                                                          I40E_PF_RESET_FLAG);
-                       }
+               if (vsi->type == I40E_VSI_MAIN) {
+                       if (pf->flags & I40E_FLAG_TC_MQPRIO)
+                               i40e_do_reset(pf, I40E_PF_RESET_FLAG, true);
+                       else
+                               i40e_do_reset_safe(pf, I40E_PF_RESET_FLAG);
                }
                /* now onwards for main VSI, number of queues will be value
                 * of TC0's queue count
@@ -7912,12 +7953,20 @@ config_tc:
                            vsi->seid);
                need_reset = true;
                goto exit;
-       } else {
-               dev_info(&vsi->back->pdev->dev,
-                        "Setup channel (id:%u) utilizing num_queues %d\n",
-                        vsi->seid, vsi->tc_config.tc_info[0].qcount);
+       } else if (enabled_tc &&
+                  (!is_power_of_2(vsi->tc_config.tc_info[0].qcount))) {
+               netdev_info(netdev,
+                           "Failed to create channel. Override queues (%u) not power of 2\n",
+                           vsi->tc_config.tc_info[0].qcount);
+               ret = -EINVAL;
+               need_reset = true;
+               goto exit;
        }
 
+       dev_info(&vsi->back->pdev->dev,
+                "Setup channel (id:%u) utilizing num_queues %d\n",
+                vsi->seid, vsi->tc_config.tc_info[0].qcount);
+
        if (pf->flags & I40E_FLAG_TC_MQPRIO) {
                if (vsi->mqprio_qopt.max_rate[0]) {
                        u64 max_tx_rate = vsi->mqprio_qopt.max_rate[0];
@@ -8482,9 +8531,8 @@ static int i40e_configure_clsflower(struct i40e_vsi *vsi,
                err = i40e_add_del_cloud_filter(vsi, filter, true);
 
        if (err) {
-               dev_err(&pf->pdev->dev,
-                       "Failed to add cloud filter, err %s\n",
-                       i40e_stat_str(&pf->hw, err));
+               dev_err(&pf->pdev->dev, "Failed to add cloud filter, err %d\n",
+                       err);
                goto err;
        }
 
@@ -13771,7 +13819,7 @@ int i40e_vsi_release(struct i40e_vsi *vsi)
                dev_info(&pf->pdev->dev, "Can't remove PF VSI\n");
                return -ENODEV;
        }
-
+       set_bit(__I40E_VSI_RELEASING, vsi->state);
        uplink_seid = vsi->uplink_seid;
        if (vsi->type != I40E_VSI_SRIOV) {
                if (vsi->netdev_registered) {
index 472f56b..80ae264 100644 (file)
@@ -183,17 +183,18 @@ void i40e_vc_notify_vf_reset(struct i40e_vf *vf)
 /***********************misc routines*****************************/
 
 /**
- * i40e_vc_disable_vf
+ * i40e_vc_reset_vf
  * @vf: pointer to the VF info
- *
- * Disable the VF through a SW reset.
+ * @notify_vf: notify vf about reset or not
+ * Reset VF handler.
  **/
-static inline void i40e_vc_disable_vf(struct i40e_vf *vf)
+static void i40e_vc_reset_vf(struct i40e_vf *vf, bool notify_vf)
 {
        struct i40e_pf *pf = vf->pf;
        int i;
 
-       i40e_vc_notify_vf_reset(vf);
+       if (notify_vf)
+               i40e_vc_notify_vf_reset(vf);
 
        /* We want to ensure that an actual reset occurs initiated after this
         * function was called. However, we do not want to wait forever, so
@@ -211,9 +212,14 @@ static inline void i40e_vc_disable_vf(struct i40e_vf *vf)
                usleep_range(10000, 20000);
        }
 
-       dev_warn(&vf->pf->pdev->dev,
-                "Failed to initiate reset for VF %d after 200 milliseconds\n",
-                vf->vf_id);
+       if (notify_vf)
+               dev_warn(&vf->pf->pdev->dev,
+                        "Failed to initiate reset for VF %d after 200 milliseconds\n",
+                        vf->vf_id);
+       else
+               dev_dbg(&vf->pf->pdev->dev,
+                       "Failed to initiate reset for VF %d after 200 milliseconds\n",
+                       vf->vf_id);
 }
 
 /**
@@ -674,14 +680,13 @@ static int i40e_config_vsi_rx_queue(struct i40e_vf *vf, u16 vsi_id,
                                    u16 vsi_queue_id,
                                    struct virtchnl_rxq_info *info)
 {
+       u16 pf_queue_id = i40e_vc_get_pf_queue_id(vf, vsi_id, vsi_queue_id);
        struct i40e_pf *pf = vf->pf;
+       struct i40e_vsi *vsi = pf->vsi[vf->lan_vsi_idx];
        struct i40e_hw *hw = &pf->hw;
        struct i40e_hmc_obj_rxq rx_ctx;
-       u16 pf_queue_id;
        int ret = 0;
 
-       pf_queue_id = i40e_vc_get_pf_queue_id(vf, vsi_id, vsi_queue_id);
-
        /* clear the context structure first */
        memset(&rx_ctx, 0, sizeof(struct i40e_hmc_obj_rxq));
 
@@ -719,6 +724,10 @@ static int i40e_config_vsi_rx_queue(struct i40e_vf *vf, u16 vsi_id,
        }
        rx_ctx.rxmax = info->max_pkt_size;
 
+       /* if port VLAN is configured increase the max packet size */
+       if (vsi->info.pvid)
+               rx_ctx.rxmax += VLAN_HLEN;
+
        /* enable 32bytes desc always */
        rx_ctx.dsize = 1;
 
@@ -2106,20 +2115,6 @@ err:
 }
 
 /**
- * i40e_vc_reset_vf_msg
- * @vf: pointer to the VF info
- *
- * called from the VF to reset itself,
- * unlike other virtchnl messages, PF driver
- * doesn't send the response back to the VF
- **/
-static void i40e_vc_reset_vf_msg(struct i40e_vf *vf)
-{
-       if (test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states))
-               i40e_reset_vf(vf, false);
-}
-
-/**
  * i40e_vc_config_promiscuous_mode_msg
  * @vf: pointer to the VF info
  * @msg: pointer to the msg buffer
@@ -2217,11 +2212,12 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg)
        struct virtchnl_vsi_queue_config_info *qci =
            (struct virtchnl_vsi_queue_config_info *)msg;
        struct virtchnl_queue_pair_info *qpi;
-       struct i40e_pf *pf = vf->pf;
        u16 vsi_id, vsi_queue_id = 0;
-       u16 num_qps_all = 0;
+       struct i40e_pf *pf = vf->pf;
        i40e_status aq_ret = 0;
        int i, j = 0, idx = 0;
+       struct i40e_vsi *vsi;
+       u16 num_qps_all = 0;
 
        if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
                aq_ret = I40E_ERR_PARAM;
@@ -2310,9 +2306,15 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg)
                pf->vsi[vf->lan_vsi_idx]->num_queue_pairs =
                        qci->num_queue_pairs;
        } else {
-               for (i = 0; i < vf->num_tc; i++)
-                       pf->vsi[vf->ch[i].vsi_idx]->num_queue_pairs =
-                              vf->ch[i].num_qps;
+               for (i = 0; i < vf->num_tc; i++) {
+                       vsi = pf->vsi[vf->ch[i].vsi_idx];
+                       vsi->num_queue_pairs = vf->ch[i].num_qps;
+
+                       if (i40e_update_adq_vsi_queues(vsi, i)) {
+                               aq_ret = I40E_ERR_CONFIG;
+                               goto error_param;
+                       }
+               }
        }
 
 error_param:
@@ -2607,8 +2609,7 @@ static int i40e_vc_request_queues_msg(struct i40e_vf *vf, u8 *msg)
        } else {
                /* successful request */
                vf->num_req_queues = req_pairs;
-               i40e_vc_notify_vf_reset(vf);
-               i40e_reset_vf(vf, false);
+               i40e_vc_reset_vf(vf, true);
                return 0;
        }
 
@@ -3803,8 +3804,7 @@ static int i40e_vc_add_qch_msg(struct i40e_vf *vf, u8 *msg)
        vf->num_req_queues = 0;
 
        /* reset the VF in order to allocate resources */
-       i40e_vc_notify_vf_reset(vf);
-       i40e_reset_vf(vf, false);
+       i40e_vc_reset_vf(vf, true);
 
        return I40E_SUCCESS;
 
@@ -3844,8 +3844,7 @@ static int i40e_vc_del_qch_msg(struct i40e_vf *vf, u8 *msg)
        }
 
        /* reset the VF in order to allocate resources */
-       i40e_vc_notify_vf_reset(vf);
-       i40e_reset_vf(vf, false);
+       i40e_vc_reset_vf(vf, true);
 
        return I40E_SUCCESS;
 
@@ -3907,7 +3906,7 @@ int i40e_vc_process_vf_msg(struct i40e_pf *pf, s16 vf_id, u32 v_opcode,
                i40e_vc_notify_vf_link_state(vf);
                break;
        case VIRTCHNL_OP_RESET_VF:
-               i40e_vc_reset_vf_msg(vf);
+               i40e_vc_reset_vf(vf, false);
                ret = 0;
                break;
        case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
@@ -4161,7 +4160,7 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
        /* Force the VF interface down so it has to bring up with new MAC
         * address
         */
-       i40e_vc_disable_vf(vf);
+       i40e_vc_reset_vf(vf, true);
        dev_info(&pf->pdev->dev, "Bring down and up the VF interface to make this change effective.\n");
 
 error_param:
@@ -4170,34 +4169,6 @@ error_param:
 }
 
 /**
- * i40e_vsi_has_vlans - True if VSI has configured VLANs
- * @vsi: pointer to the vsi
- *
- * Check if a VSI has configured any VLANs. False if we have a port VLAN or if
- * we have no configured VLANs. Do not call while holding the
- * mac_filter_hash_lock.
- */
-static bool i40e_vsi_has_vlans(struct i40e_vsi *vsi)
-{
-       bool have_vlans;
-
-       /* If we have a port VLAN, then the VSI cannot have any VLANs
-        * configured, as all MAC/VLAN filters will be assigned to the PVID.
-        */
-       if (vsi->info.pvid)
-               return false;
-
-       /* Since we don't have a PVID, we know that if the device is in VLAN
-        * mode it must be because of a VLAN filter configured on this VSI.
-        */
-       spin_lock_bh(&vsi->mac_filter_hash_lock);
-       have_vlans = i40e_is_vsi_in_vlan(vsi);
-       spin_unlock_bh(&vsi->mac_filter_hash_lock);
-
-       return have_vlans;
-}
-
-/**
  * i40e_ndo_set_vf_port_vlan
  * @netdev: network interface device structure
  * @vf_id: VF identifier
@@ -4253,19 +4224,9 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id,
                /* duplicate request, so just return success */
                goto error_pvid;
 
-       if (i40e_vsi_has_vlans(vsi)) {
-               dev_err(&pf->pdev->dev,
-                       "VF %d has already configured VLAN filters and the administrator is requesting a port VLAN override.\nPlease unload and reload the VF driver for this change to take effect.\n",
-                       vf_id);
-               /* Administrator Error - knock the VF offline until he does
-                * the right thing by reconfiguring his network correctly
-                * and then reloading the VF driver.
-                */
-               i40e_vc_disable_vf(vf);
-               /* During reset the VF got a new VSI, so refresh the pointer. */
-               vsi = pf->vsi[vf->lan_vsi_idx];
-       }
-
+       i40e_vc_reset_vf(vf, true);
+       /* During reset the VF got a new VSI, so refresh a pointer. */
+       vsi = pf->vsi[vf->lan_vsi_idx];
        /* Locked once because multiple functions below iterate list */
        spin_lock_bh(&vsi->mac_filter_hash_lock);
 
@@ -4641,7 +4602,7 @@ int i40e_ndo_set_vf_trust(struct net_device *netdev, int vf_id, bool setting)
                goto out;
 
        vf->trusted = setting;
-       i40e_vc_disable_vf(vf);
+       i40e_vc_reset_vf(vf, true);
        dev_info(&pf->pdev->dev, "VF %u is now %strusted\n",
                 vf_id, setting ? "" : "un");
 
index e6e7c1d..75635bd 100644 (file)
@@ -39,6 +39,7 @@
 #include "iavf_txrx.h"
 #include "iavf_fdir.h"
 #include "iavf_adv_rss.h"
+#include <linux/bitmap.h>
 
 #define DEFAULT_DEBUG_LEVEL_SHIFT 3
 #define PFX "iavf: "
index 5a359a0..144a776 100644 (file)
@@ -1776,6 +1776,7 @@ static int iavf_set_channels(struct net_device *netdev,
 {
        struct iavf_adapter *adapter = netdev_priv(netdev);
        u32 num_req = ch->combined_count;
+       int i;
 
        if ((adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ) &&
            adapter->num_tc) {
@@ -1786,7 +1787,7 @@ static int iavf_set_channels(struct net_device *netdev,
        /* All of these should have already been checked by ethtool before this
         * even gets to us, but just to be sure.
         */
-       if (num_req > adapter->vsi_res->num_queue_pairs)
+       if (num_req == 0 || num_req > adapter->vsi_res->num_queue_pairs)
                return -EINVAL;
 
        if (num_req == adapter->num_active_queues)
@@ -1798,6 +1799,20 @@ static int iavf_set_channels(struct net_device *netdev,
        adapter->num_req_queues = num_req;
        adapter->flags |= IAVF_FLAG_REINIT_ITR_NEEDED;
        iavf_schedule_reset(adapter);
+
+       /* wait for the reset is done */
+       for (i = 0; i < IAVF_RESET_WAIT_COMPLETE_COUNT; i++) {
+               msleep(IAVF_RESET_WAIT_MS);
+               if (adapter->flags & IAVF_FLAG_RESET_PENDING)
+                       continue;
+               break;
+       }
+       if (i == IAVF_RESET_WAIT_COMPLETE_COUNT) {
+               adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED;
+               adapter->num_active_queues = num_req;
+               return -EOPNOTSUPP;
+       }
+
        return 0;
 }
 
@@ -1844,14 +1859,13 @@ static int iavf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
 
        if (hfunc)
                *hfunc = ETH_RSS_HASH_TOP;
-       if (!indir)
-               return 0;
-
-       memcpy(key, adapter->rss_key, adapter->rss_key_size);
+       if (key)
+               memcpy(key, adapter->rss_key, adapter->rss_key_size);
 
-       /* Each 32 bits pointed by 'indir' is stored with a lut entry */
-       for (i = 0; i < adapter->rss_lut_size; i++)
-               indir[i] = (u32)adapter->rss_lut[i];
+       if (indir)
+               /* Each 32 bits pointed by 'indir' is stored with a lut entry */
+               for (i = 0; i < adapter->rss_lut_size; i++)
+                       indir[i] = (u32)adapter->rss_lut[i];
 
        return 0;
 }
index 847d67e..336e6bf 100644 (file)
@@ -697,6 +697,23 @@ static void iavf_del_vlan(struct iavf_adapter *adapter, u16 vlan)
 }
 
 /**
+ * iavf_restore_filters
+ * @adapter: board private structure
+ *
+ * Restore existing non MAC filters when VF netdev comes back up
+ **/
+static void iavf_restore_filters(struct iavf_adapter *adapter)
+{
+       /* re-add all VLAN filters */
+       if (VLAN_ALLOWED(adapter)) {
+               u16 vid;
+
+               for_each_set_bit(vid, adapter->vsi.active_vlans, VLAN_N_VID)
+                       iavf_add_vlan(adapter, vid);
+       }
+}
+
+/**
  * iavf_vlan_rx_add_vid - Add a VLAN filter to a device
  * @netdev: network device struct
  * @proto: unused protocol data
@@ -709,8 +726,11 @@ static int iavf_vlan_rx_add_vid(struct net_device *netdev,
 
        if (!VLAN_ALLOWED(adapter))
                return -EIO;
+
        if (iavf_add_vlan(adapter, vid) == NULL)
                return -ENOMEM;
+
+       set_bit(vid, adapter->vsi.active_vlans);
        return 0;
 }
 
@@ -725,11 +745,13 @@ static int iavf_vlan_rx_kill_vid(struct net_device *netdev,
 {
        struct iavf_adapter *adapter = netdev_priv(netdev);
 
-       if (VLAN_ALLOWED(adapter)) {
-               iavf_del_vlan(adapter, vid);
-               return 0;
-       }
-       return -EIO;
+       if (!VLAN_ALLOWED(adapter))
+               return -EIO;
+
+       iavf_del_vlan(adapter, vid);
+       clear_bit(vid, adapter->vsi.active_vlans);
+
+       return 0;
 }
 
 /**
@@ -1639,8 +1661,7 @@ static int iavf_process_aq_command(struct iavf_adapter *adapter)
                iavf_set_promiscuous(adapter, FLAG_VF_MULTICAST_PROMISC);
                return 0;
        }
-
-       if ((adapter->aq_required & IAVF_FLAG_AQ_RELEASE_PROMISC) &&
+       if ((adapter->aq_required & IAVF_FLAG_AQ_RELEASE_PROMISC) ||
            (adapter->aq_required & IAVF_FLAG_AQ_RELEASE_ALLMULTI)) {
                iavf_set_promiscuous(adapter, 0);
                return 0;
@@ -2123,8 +2144,8 @@ static void iavf_disable_vf(struct iavf_adapter *adapter)
 
        iavf_free_misc_irq(adapter);
        iavf_reset_interrupt_capability(adapter);
-       iavf_free_queues(adapter);
        iavf_free_q_vectors(adapter);
+       iavf_free_queues(adapter);
        memset(adapter->vf_res, 0, IAVF_VIRTCHNL_VF_RESOURCE_SIZE);
        iavf_shutdown_adminq(&adapter->hw);
        adapter->netdev->flags &= ~IFF_UP;
@@ -2410,7 +2431,7 @@ static void iavf_adminq_task(struct work_struct *work)
 
        /* check for error indications */
        val = rd32(hw, hw->aq.arq.len);
-       if (val == 0xdeadbeef) /* indicates device in reset */
+       if (val == 0xdeadbeef || val == 0xffffffff) /* device in reset */
                goto freedom;
        oldval = val;
        if (val & IAVF_VF_ARQLEN1_ARQVFE_MASK) {
@@ -3095,8 +3116,10 @@ static int iavf_configure_clsflower(struct iavf_adapter *adapter,
                return -ENOMEM;
 
        while (!mutex_trylock(&adapter->crit_lock)) {
-               if (--count == 0)
-                       goto err;
+               if (--count == 0) {
+                       kfree(filter);
+                       return err;
+               }
                udelay(1);
        }
 
@@ -3107,11 +3130,11 @@ static int iavf_configure_clsflower(struct iavf_adapter *adapter,
        /* start out with flow type and eth type IPv4 to begin with */
        filter->f.flow_type = VIRTCHNL_TCP_V4_FLOW;
        err = iavf_parse_cls_flower(adapter, cls_flower, filter);
-       if (err < 0)
+       if (err)
                goto err;
 
        err = iavf_handle_tclass(adapter, tc, filter);
-       if (err < 0)
+       if (err)
                goto err;
 
        /* add filter to the list */
@@ -3308,6 +3331,9 @@ static int iavf_open(struct net_device *netdev)
 
        spin_unlock_bh(&adapter->mac_vlan_list_lock);
 
+       /* Restore VLAN filters that were removed with IFF_DOWN */
+       iavf_restore_filters(adapter);
+
        iavf_configure(adapter);
 
        iavf_up_complete(adapter);
@@ -3503,7 +3529,8 @@ static netdev_features_t iavf_fix_features(struct net_device *netdev,
 {
        struct iavf_adapter *adapter = netdev_priv(netdev);
 
-       if (!(adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN))
+       if (adapter->vf_res &&
+           !(adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN))
                features &= ~(NETIF_F_HW_VLAN_CTAG_TX |
                              NETIF_F_HW_VLAN_CTAG_RX |
                              NETIF_F_HW_VLAN_CTAG_FILTER);
index 6433c90..072391c 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/io.h>
 #include <linux/dma-mapping.h>
 #include <linux/module.h>
+#include <linux/property.h>
 
 #include <asm/checksum.h>
 
@@ -239,6 +240,7 @@ ltq_etop_hw_init(struct net_device *dev)
 {
        struct ltq_etop_priv *priv = netdev_priv(dev);
        int i;
+       int err;
 
        ltq_pmu_enable(PMU_PPE);
 
@@ -273,7 +275,13 @@ ltq_etop_hw_init(struct net_device *dev)
 
                if (IS_TX(i)) {
                        ltq_dma_alloc_tx(&ch->dma);
-                       request_irq(irq, ltq_etop_dma_irq, 0, "etop_tx", priv);
+                       err = request_irq(irq, ltq_etop_dma_irq, 0, "etop_tx", priv);
+                       if (err) {
+                               netdev_err(dev,
+                                          "Unable to get Tx DMA IRQ %d\n",
+                                          irq);
+                               return err;
+                       }
                } else if (IS_RX(i)) {
                        ltq_dma_alloc_rx(&ch->dma);
                        for (ch->dma.desc = 0; ch->dma.desc < LTQ_DESC_NUM;
@@ -281,7 +289,13 @@ ltq_etop_hw_init(struct net_device *dev)
                                if (ltq_etop_alloc_skb(ch))
                                        return -ENOMEM;
                        ch->dma.desc = 0;
-                       request_irq(irq, ltq_etop_dma_irq, 0, "etop_rx", priv);
+                       err = request_irq(irq, ltq_etop_dma_irq, 0, "etop_rx", priv);
+                       if (err) {
+                               netdev_err(dev,
+                                          "Unable to get Rx DMA IRQ %d\n",
+                                          irq);
+                               return err;
+                       }
                }
                ch->dma.irq = irq;
        }
@@ -726,7 +740,7 @@ static struct platform_driver ltq_mii_driver = {
        },
 };
 
-int __init
+static int __init
 init_ltq_etop(void)
 {
        int ret = platform_driver_probe(&ltq_mii_driver, ltq_etop_probe);
index 62a97c4..ef87897 100644 (file)
@@ -429,12 +429,14 @@ static const struct of_device_id orion_mdio_match[] = {
 };
 MODULE_DEVICE_TABLE(of, orion_mdio_match);
 
+#ifdef CONFIG_ACPI
 static const struct acpi_device_id orion_mdio_acpi_match[] = {
        { "MRVL0100", BUS_TYPE_SMI },
        { "MRVL0101", BUS_TYPE_XSMI },
        { },
 };
 MODULE_DEVICE_TABLE(acpi, orion_mdio_acpi_match);
+#endif
 
 static struct platform_driver orion_mdio_driver = {
        .probe = orion_mdio_probe,
index c7fd466..a09a507 100644 (file)
@@ -236,10 +236,11 @@ static ssize_t rvu_dbg_lmtst_map_table_display(struct file *filp,
        u64 lmt_addr, val, tbl_base;
        int pf, vf, num_vfs, hw_vfs;
        void __iomem *lmt_map_base;
-       int index = 0, off = 0;
-       int bytes_not_copied;
        int buf_size = 10240;
+       size_t off = 0;
+       int index = 0;
        char *buf;
+       int ret;
 
        /* don't allow partial reads */
        if (*ppos != 0)
@@ -303,15 +304,17 @@ static ssize_t rvu_dbg_lmtst_map_table_display(struct file *filp,
        }
        off +=  scnprintf(&buf[off], buf_size - 1 - off, "\n");
 
-       bytes_not_copied = copy_to_user(buffer, buf, off);
+       ret = min(off, count);
+       if (copy_to_user(buffer, buf, ret))
+               ret = -EFAULT;
        kfree(buf);
 
        iounmap(lmt_map_base);
-       if (bytes_not_copied)
-               return -EFAULT;
+       if (ret < 0)
+               return ret;
 
-       *ppos = off;
-       return off;
+       *ppos = ret;
+       return ret;
 }
 
 RVU_DEBUG_FOPS(lmtst_map_table, lmtst_map_table_display, NULL);
index f71ec4d..8eaa24d 100644 (file)
@@ -339,6 +339,8 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
        case MLX5_CMD_OP_PAGE_FAULT_RESUME:
        case MLX5_CMD_OP_QUERY_ESW_FUNCTIONS:
        case MLX5_CMD_OP_DEALLOC_SF:
+       case MLX5_CMD_OP_DESTROY_UCTX:
+       case MLX5_CMD_OP_DESTROY_UMEM:
                return MLX5_CMD_STAT_OK;
 
        case MLX5_CMD_OP_QUERY_HCA_CAP:
@@ -464,9 +466,7 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
        case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT:
        case MLX5_CMD_OP_QUERY_GENERAL_OBJECT:
        case MLX5_CMD_OP_CREATE_UCTX:
-       case MLX5_CMD_OP_DESTROY_UCTX:
        case MLX5_CMD_OP_CREATE_UMEM:
-       case MLX5_CMD_OP_DESTROY_UMEM:
        case MLX5_CMD_OP_ALLOC_MEMIC:
        case MLX5_CMD_OP_MODIFY_XRQ:
        case MLX5_CMD_OP_RELEASE_XRQ_ERROR:
index 02e77ff..5371ad0 100644 (file)
@@ -164,13 +164,14 @@ int mlx5_core_destroy_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq)
        MLX5_SET(destroy_cq_in, in, cqn, cq->cqn);
        MLX5_SET(destroy_cq_in, in, uid, cq->uid);
        err = mlx5_cmd_exec_in(dev, destroy_cq, in);
+       if (err)
+               return err;
 
        synchronize_irq(cq->irqn);
-
        mlx5_cq_put(cq);
        wait_for_completion(&cq->free);
 
-       return err;
+       return 0;
 }
 EXPORT_SYMBOL(mlx5_core_destroy_cq);
 
index 07c8d98..10d1950 100644 (file)
@@ -507,6 +507,8 @@ void mlx5_debug_cq_remove(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq)
        if (!mlx5_debugfs_root)
                return;
 
-       if (cq->dbg)
+       if (cq->dbg) {
                rem_res_tree(cq->dbg);
+               cq->dbg = NULL;
+       }
 }
index c1c6e74..2445e2a 100644 (file)
@@ -1356,9 +1356,13 @@ mlx5_tc_ct_match_add(struct mlx5_tc_ct_priv *priv,
 int
 mlx5_tc_ct_parse_action(struct mlx5_tc_ct_priv *priv,
                        struct mlx5_flow_attr *attr,
+                       struct mlx5e_tc_mod_hdr_acts *mod_acts,
                        const struct flow_action_entry *act,
                        struct netlink_ext_ack *extack)
 {
+       bool clear_action = act->ct.action & TCA_CT_ACT_CLEAR;
+       int err;
+
        if (!priv) {
                NL_SET_ERR_MSG_MOD(extack,
                                   "offload of ct action isn't available");
@@ -1369,6 +1373,17 @@ mlx5_tc_ct_parse_action(struct mlx5_tc_ct_priv *priv,
        attr->ct_attr.ct_action = act->ct.action;
        attr->ct_attr.nf_ft = act->ct.flow_table;
 
+       if (!clear_action)
+               goto out;
+
+       err = mlx5_tc_ct_entry_set_registers(priv, mod_acts, 0, 0, 0, 0);
+       if (err) {
+               NL_SET_ERR_MSG_MOD(extack, "Failed to set registers for ct clear");
+               return err;
+       }
+       attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
+
+out:
        return 0;
 }
 
@@ -1898,23 +1913,16 @@ __mlx5_tc_ct_flow_offload_clear(struct mlx5_tc_ct_priv *ct_priv,
 
        memcpy(pre_ct_attr, attr, attr_sz);
 
-       err = mlx5_tc_ct_entry_set_registers(ct_priv, mod_acts, 0, 0, 0, 0);
-       if (err) {
-               ct_dbg("Failed to set register for ct clear");
-               goto err_set_registers;
-       }
-
        mod_hdr = mlx5_modify_header_alloc(priv->mdev, ct_priv->ns_type,
                                           mod_acts->num_actions,
                                           mod_acts->actions);
        if (IS_ERR(mod_hdr)) {
                err = PTR_ERR(mod_hdr);
                ct_dbg("Failed to add create ct clear mod hdr");
-               goto err_set_registers;
+               goto err_mod_hdr;
        }
 
        pre_ct_attr->modify_hdr = mod_hdr;
-       pre_ct_attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
 
        rule = mlx5_tc_rule_insert(priv, orig_spec, pre_ct_attr);
        if (IS_ERR(rule)) {
@@ -1930,7 +1938,7 @@ __mlx5_tc_ct_flow_offload_clear(struct mlx5_tc_ct_priv *ct_priv,
 
 err_insert:
        mlx5_modify_header_dealloc(priv->mdev, mod_hdr);
-err_set_registers:
+err_mod_hdr:
        netdev_warn(priv->netdev,
                    "Failed to offload ct clear flow, err %d\n", err);
        kfree(pre_ct_attr);
index 363329f..99662af 100644 (file)
@@ -110,6 +110,7 @@ int mlx5_tc_ct_add_no_trk_match(struct mlx5_flow_spec *spec);
 int
 mlx5_tc_ct_parse_action(struct mlx5_tc_ct_priv *priv,
                        struct mlx5_flow_attr *attr,
+                       struct mlx5e_tc_mod_hdr_acts *mod_acts,
                        const struct flow_action_entry *act,
                        struct netlink_ext_ack *extack);
 
@@ -172,6 +173,7 @@ mlx5_tc_ct_add_no_trk_match(struct mlx5_flow_spec *spec)
 static inline int
 mlx5_tc_ct_parse_action(struct mlx5_tc_ct_priv *priv,
                        struct mlx5_flow_attr *attr,
+                       struct mlx5e_tc_mod_hdr_acts *mod_acts,
                        const struct flow_action_entry *act,
                        struct netlink_ext_ack *extack)
 {
index 8f64f2c..b689701 100644 (file)
@@ -102,6 +102,7 @@ struct mlx5e_tc_flow {
        refcount_t refcnt;
        struct rcu_head rcu_head;
        struct completion init_done;
+       struct completion del_hw_done;
        int tunnel_id; /* the mapped tunnel id of this flow */
        struct mlx5_flow_attr *attr;
 };
index 660cca7..042b1ab 100644 (file)
@@ -245,8 +245,14 @@ static void mlx5e_take_tmp_flow(struct mlx5e_tc_flow *flow,
                                struct list_head *flow_list,
                                int index)
 {
-       if (IS_ERR(mlx5e_flow_get(flow)))
+       if (IS_ERR(mlx5e_flow_get(flow))) {
+               /* Flow is being deleted concurrently. Wait for it to be
+                * unoffloaded from hardware, otherwise deleting encap will
+                * fail.
+                */
+               wait_for_completion(&flow->del_hw_done);
                return;
+       }
        wait_for_completion(&flow->init_done);
 
        flow->tmp_entry_index = index;
index 62abce0..a2a9f68 100644 (file)
@@ -55,6 +55,7 @@ struct mlx5e_ktls_offload_context_rx {
        DECLARE_BITMAP(flags, MLX5E_NUM_PRIV_RX_FLAGS);
 
        /* resync */
+       spinlock_t lock; /* protects resync fields */
        struct mlx5e_ktls_rx_resync_ctx resync;
        struct list_head list;
 };
@@ -386,14 +387,18 @@ static void resync_handle_seq_match(struct mlx5e_ktls_offload_context_rx *priv_r
        struct mlx5e_icosq *sq;
        bool trigger_poll;
 
-       memcpy(info->rec_seq, &priv_rx->resync.sw_rcd_sn_be, sizeof(info->rec_seq));
-
        sq = &c->async_icosq;
        ktls_resync = sq->ktls_resync;
+       trigger_poll = false;
 
        spin_lock_bh(&ktls_resync->lock);
-       list_add_tail(&priv_rx->list, &ktls_resync->list);
-       trigger_poll = !test_and_set_bit(MLX5E_SQ_STATE_PENDING_TLS_RX_RESYNC, &sq->state);
+       spin_lock_bh(&priv_rx->lock);
+       memcpy(info->rec_seq, &priv_rx->resync.sw_rcd_sn_be, sizeof(info->rec_seq));
+       if (list_empty(&priv_rx->list)) {
+               list_add_tail(&priv_rx->list, &ktls_resync->list);
+               trigger_poll = !test_and_set_bit(MLX5E_SQ_STATE_PENDING_TLS_RX_RESYNC, &sq->state);
+       }
+       spin_unlock_bh(&priv_rx->lock);
        spin_unlock_bh(&ktls_resync->lock);
 
        if (!trigger_poll)
@@ -617,6 +622,8 @@ int mlx5e_ktls_add_rx(struct net_device *netdev, struct sock *sk,
        if (err)
                goto err_create_key;
 
+       INIT_LIST_HEAD(&priv_rx->list);
+       spin_lock_init(&priv_rx->lock);
        priv_rx->crypto_info  =
                *(struct tls12_crypto_info_aes_gcm_128 *)crypto_info;
 
@@ -730,10 +737,14 @@ bool mlx5e_ktls_rx_handle_resync_list(struct mlx5e_channel *c, int budget)
                priv_rx = list_first_entry(&local_list,
                                           struct mlx5e_ktls_offload_context_rx,
                                           list);
+               spin_lock(&priv_rx->lock);
                cseg = post_static_params(sq, priv_rx);
-               if (IS_ERR(cseg))
+               if (IS_ERR(cseg)) {
+                       spin_unlock(&priv_rx->lock);
                        break;
-               list_del(&priv_rx->list);
+               }
+               list_del_init(&priv_rx->list);
+               spin_unlock(&priv_rx->lock);
                db_cseg = cseg;
        }
        if (db_cseg)
index 835caa1..3d45f4a 100644 (file)
@@ -1600,6 +1600,7 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
                else
                        mlx5e_tc_unoffload_fdb_rules(esw, flow, attr);
        }
+       complete_all(&flow->del_hw_done);
 
        if (mlx5_flow_has_geneve_opt(flow))
                mlx5_geneve_tlv_option_del(priv->mdev->geneve);
@@ -3607,7 +3608,9 @@ parse_tc_nic_actions(struct mlx5e_priv *priv,
                        attr->dest_chain = act->chain_index;
                        break;
                case FLOW_ACTION_CT:
-                       err = mlx5_tc_ct_parse_action(get_ct_priv(priv), attr, act, extack);
+                       err = mlx5_tc_ct_parse_action(get_ct_priv(priv), attr,
+                                                     &parse_attr->mod_hdr_acts,
+                                                     act, extack);
                        if (err)
                                return err;
 
@@ -4276,7 +4279,9 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
                                NL_SET_ERR_MSG_MOD(extack, "Sample action with connection tracking is not supported");
                                return -EOPNOTSUPP;
                        }
-                       err = mlx5_tc_ct_parse_action(get_ct_priv(priv), attr, act, extack);
+                       err = mlx5_tc_ct_parse_action(get_ct_priv(priv), attr,
+                                                     &parse_attr->mod_hdr_acts,
+                                                     act, extack);
                        if (err)
                                return err;
 
@@ -4465,6 +4470,7 @@ mlx5e_alloc_flow(struct mlx5e_priv *priv, int attr_size,
        INIT_LIST_HEAD(&flow->l3_to_l2_reformat);
        refcount_set(&flow->refcnt, 1);
        init_completion(&flow->init_done);
+       init_completion(&flow->del_hw_done);
 
        *__flow = flow;
        *__parse_attr = parse_attr;
index ec136b4..51a8cec 100644 (file)
@@ -1305,12 +1305,17 @@ abort:
  */
 int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs)
 {
+       bool toggle_lag;
        int ret;
 
        if (!mlx5_esw_allowed(esw))
                return 0;
 
-       mlx5_lag_disable_change(esw->dev);
+       toggle_lag = esw->mode == MLX5_ESWITCH_NONE;
+
+       if (toggle_lag)
+               mlx5_lag_disable_change(esw->dev);
+
        down_write(&esw->mode_lock);
        if (esw->mode == MLX5_ESWITCH_NONE) {
                ret = mlx5_eswitch_enable_locked(esw, MLX5_ESWITCH_LEGACY, num_vfs);
@@ -1324,7 +1329,10 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs)
                        esw->esw_funcs.num_vfs = num_vfs;
        }
        up_write(&esw->mode_lock);
-       mlx5_lag_enable_change(esw->dev);
+
+       if (toggle_lag)
+               mlx5_lag_enable_change(esw->dev);
+
        return ret;
 }
 
@@ -1572,6 +1580,11 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
        esw->enabled_vports = 0;
        esw->mode = MLX5_ESWITCH_NONE;
        esw->offloads.inline_mode = MLX5_INLINE_MODE_NONE;
+       if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, reformat) &&
+           MLX5_CAP_ESW_FLOWTABLE_FDB(dev, decap))
+               esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_BASIC;
+       else
+               esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE;
 
        dev->priv.eswitch = esw;
        BLOCKING_INIT_NOTIFIER_HEAD(&esw->n_head);
@@ -1934,7 +1947,7 @@ free_out:
        return err;
 }
 
-u8 mlx5_eswitch_mode(struct mlx5_core_dev *dev)
+u8 mlx5_eswitch_mode(const struct mlx5_core_dev *dev)
 {
        struct mlx5_eswitch *esw = dev->priv.eswitch;
 
@@ -1948,7 +1961,7 @@ mlx5_eswitch_get_encap_mode(const struct mlx5_core_dev *dev)
        struct mlx5_eswitch *esw;
 
        esw = dev->priv.eswitch;
-       return mlx5_esw_allowed(esw) ? esw->offloads.encap :
+       return (mlx5_eswitch_mode(dev) == MLX5_ESWITCH_OFFLOADS)  ? esw->offloads.encap :
                DEVLINK_ESWITCH_ENCAP_MODE_NONE;
 }
 EXPORT_SYMBOL(mlx5_eswitch_get_encap_mode);
index f4eaa58..a464556 100644 (file)
@@ -3183,12 +3183,6 @@ int esw_offloads_enable(struct mlx5_eswitch *esw)
        u64 mapping_id;
        int err;
 
-       if (MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, reformat) &&
-           MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, decap))
-               esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_BASIC;
-       else
-               esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE;
-
        mutex_init(&esw->offloads.termtbl_mutex);
        mlx5_rdma_enable_roce(esw->dev);
 
@@ -3286,7 +3280,6 @@ void esw_offloads_disable(struct mlx5_eswitch *esw)
        esw_offloads_metadata_uninit(esw);
        mlx5_rdma_disable_roce(esw->dev);
        mutex_destroy(&esw->offloads.termtbl_mutex);
-       esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE;
 }
 
 static int esw_mode_from_devlink(u16 mode, u16 *mlx5_mode)
@@ -3630,7 +3623,7 @@ int mlx5_devlink_eswitch_encap_mode_get(struct devlink *devlink,
        *encap = esw->offloads.encap;
 unlock:
        up_write(&esw->mode_lock);
-       return 0;
+       return err;
 }
 
 static bool
index 31c99d5..7e0e04c 100644 (file)
@@ -40,7 +40,7 @@
 #define MLX5_FC_STATS_PERIOD msecs_to_jiffies(1000)
 /* Max number of counters to query in bulk read is 32K */
 #define MLX5_SW_MAX_COUNTERS_BULK BIT(15)
-#define MLX5_SF_NUM_COUNTERS_BULK 6
+#define MLX5_SF_NUM_COUNTERS_BULK 8
 #define MLX5_FC_POOL_MAX_THRESHOLD BIT(18)
 #define MLX5_FC_POOL_USED_BUFF_RATIO 10
 
index 48d2ea6..4ddf6b3 100644 (file)
@@ -615,6 +615,7 @@ static int mlx5_handle_changeupper_event(struct mlx5_lag *ldev,
        bool is_bonded, is_in_lag, mode_supported;
        int bond_status = 0;
        int num_slaves = 0;
+       int changed = 0;
        int idx;
 
        if (!netif_is_lag_master(upper))
@@ -653,27 +654,27 @@ static int mlx5_handle_changeupper_event(struct mlx5_lag *ldev,
         */
        is_in_lag = num_slaves == MLX5_MAX_PORTS && bond_status == 0x3;
 
-       if (!mlx5_lag_is_ready(ldev) && is_in_lag) {
-               NL_SET_ERR_MSG_MOD(info->info.extack,
-                                  "Can't activate LAG offload, PF is configured with more than 64 VFs");
-               return 0;
-       }
-
        /* Lag mode must be activebackup or hash. */
        mode_supported = tracker->tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP ||
                         tracker->tx_type == NETDEV_LAG_TX_TYPE_HASH;
 
-       if (is_in_lag && !mode_supported)
-               NL_SET_ERR_MSG_MOD(info->info.extack,
-                                  "Can't activate LAG offload, TX type isn't supported");
-
        is_bonded = is_in_lag && mode_supported;
        if (tracker->is_bonded != is_bonded) {
                tracker->is_bonded = is_bonded;
-               return 1;
+               changed = 1;
        }
 
-       return 0;
+       if (!is_in_lag)
+               return changed;
+
+       if (!mlx5_lag_is_ready(ldev))
+               NL_SET_ERR_MSG_MOD(info->info.extack,
+                                  "Can't activate LAG offload, PF is configured with more than 64 VFs");
+       else if (!mode_supported)
+               NL_SET_ERR_MSG_MOD(info->info.extack,
+                                  "Can't activate LAG offload, TX type isn't supported");
+
+       return changed;
 }
 
 static int mlx5_handle_changelowerstate_event(struct mlx5_lag *ldev,
@@ -716,9 +717,6 @@ static int mlx5_lag_netdev_event(struct notifier_block *this,
 
        ldev    = container_of(this, struct mlx5_lag, nb);
 
-       if (!mlx5_lag_is_ready(ldev) && event == NETDEV_CHANGELOWERSTATE)
-               return NOTIFY_DONE;
-
        tracker = ldev->tracker;
 
        switch (event) {
index 49089cb..8cbd36c 100644 (file)
@@ -135,25 +135,14 @@ static void dr_domain_fill_uplink_caps(struct mlx5dr_domain *dmn,
 
 static int dr_domain_query_vport(struct mlx5dr_domain *dmn,
                                 u16 vport_number,
+                                bool other_vport,
                                 struct mlx5dr_cmd_vport_cap *vport_caps)
 {
-       u16 cmd_vport = vport_number;
-       bool other_vport = true;
        int ret;
 
-       if (vport_number == MLX5_VPORT_UPLINK) {
-               dr_domain_fill_uplink_caps(dmn, vport_caps);
-               return 0;
-       }
-
-       if (dmn->info.caps.is_ecpf && vport_number == MLX5_VPORT_ECPF) {
-               other_vport = false;
-               cmd_vport = 0;
-       }
-
        ret = mlx5dr_cmd_query_esw_vport_context(dmn->mdev,
                                                 other_vport,
-                                                cmd_vport,
+                                                vport_number,
                                                 &vport_caps->icm_address_rx,
                                                 &vport_caps->icm_address_tx);
        if (ret)
@@ -161,7 +150,7 @@ static int dr_domain_query_vport(struct mlx5dr_domain *dmn,
 
        ret = mlx5dr_cmd_query_gvmi(dmn->mdev,
                                    other_vport,
-                                   cmd_vport,
+                                   vport_number,
                                    &vport_caps->vport_gvmi);
        if (ret)
                return ret;
@@ -176,9 +165,15 @@ static int dr_domain_query_esw_mngr(struct mlx5dr_domain *dmn)
 {
        return dr_domain_query_vport(dmn,
                                     dmn->info.caps.is_ecpf ? MLX5_VPORT_ECPF : 0,
+                                    false,
                                     &dmn->info.caps.vports.esw_manager_caps);
 }
 
+static void dr_domain_query_uplink(struct mlx5dr_domain *dmn)
+{
+       dr_domain_fill_uplink_caps(dmn, &dmn->info.caps.vports.uplink_caps);
+}
+
 static struct mlx5dr_cmd_vport_cap *
 dr_domain_add_vport_cap(struct mlx5dr_domain *dmn, u16 vport)
 {
@@ -190,7 +185,7 @@ dr_domain_add_vport_cap(struct mlx5dr_domain *dmn, u16 vport)
        if (!vport_caps)
                return NULL;
 
-       ret = dr_domain_query_vport(dmn, vport, vport_caps);
+       ret = dr_domain_query_vport(dmn, vport, true, vport_caps);
        if (ret) {
                kvfree(vport_caps);
                return NULL;
@@ -207,16 +202,26 @@ dr_domain_add_vport_cap(struct mlx5dr_domain *dmn, u16 vport)
        return vport_caps;
 }
 
+static bool dr_domain_is_esw_mgr_vport(struct mlx5dr_domain *dmn, u16 vport)
+{
+       struct mlx5dr_cmd_caps *caps = &dmn->info.caps;
+
+       return (caps->is_ecpf && vport == MLX5_VPORT_ECPF) ||
+              (!caps->is_ecpf && vport == 0);
+}
+
 struct mlx5dr_cmd_vport_cap *
 mlx5dr_domain_get_vport_cap(struct mlx5dr_domain *dmn, u16 vport)
 {
        struct mlx5dr_cmd_caps *caps = &dmn->info.caps;
        struct mlx5dr_cmd_vport_cap *vport_caps;
 
-       if ((caps->is_ecpf && vport == MLX5_VPORT_ECPF) ||
-           (!caps->is_ecpf && vport == 0))
+       if (dr_domain_is_esw_mgr_vport(dmn, vport))
                return &caps->vports.esw_manager_caps;
 
+       if (vport == MLX5_VPORT_UPLINK)
+               return &caps->vports.uplink_caps;
+
 vport_load:
        vport_caps = xa_load(&caps->vports.vports_caps_xa, vport);
        if (vport_caps)
@@ -241,17 +246,6 @@ static void dr_domain_clear_vports(struct mlx5dr_domain *dmn)
        }
 }
 
-static int dr_domain_query_uplink(struct mlx5dr_domain *dmn)
-{
-       struct mlx5dr_cmd_vport_cap *vport_caps;
-
-       vport_caps = mlx5dr_domain_get_vport_cap(dmn, MLX5_VPORT_UPLINK);
-       if (!vport_caps)
-               return -EINVAL;
-
-       return 0;
-}
-
 static int dr_domain_query_fdb_caps(struct mlx5_core_dev *mdev,
                                    struct mlx5dr_domain *dmn)
 {
@@ -281,11 +275,7 @@ static int dr_domain_query_fdb_caps(struct mlx5_core_dev *mdev,
                goto free_vports_caps_xa;
        }
 
-       ret = dr_domain_query_uplink(dmn);
-       if (ret) {
-               mlx5dr_err(dmn, "Failed to query uplink vport caps (err: %d)", ret);
-               goto free_vports_caps_xa;
-       }
+       dr_domain_query_uplink(dmn);
 
        return 0;
 
index 75c775b..7933652 100644 (file)
@@ -924,11 +924,12 @@ static int dr_matcher_init(struct mlx5dr_matcher *matcher,
 
        /* Check that all mask data was consumed */
        for (i = 0; i < consumed_mask.match_sz; i++) {
-               if (consumed_mask.match_buf[i]) {
-                       mlx5dr_dbg(dmn, "Match param mask contains unsupported parameters\n");
-                       ret = -EOPNOTSUPP;
-                       goto free_consumed_mask;
-               }
+               if (!((u8 *)consumed_mask.match_buf)[i])
+                       continue;
+
+               mlx5dr_dbg(dmn, "Match param mask contains unsupported parameters\n");
+               ret = -EOPNOTSUPP;
+               goto free_consumed_mask;
        }
 
        ret =  0;
index 3028b77..2333c24 100644 (file)
@@ -764,6 +764,7 @@ struct mlx5dr_roce_cap {
 
 struct mlx5dr_vports {
        struct mlx5dr_cmd_vport_cap esw_manager_caps;
+       struct mlx5dr_cmd_vport_cap uplink_caps;
        struct xarray vports_caps_xa;
 };
 
index cc2d907..23a336c 100644 (file)
@@ -392,7 +392,7 @@ static int sis96x_get_mac_addr(struct pci_dev *pci_dev,
                        /* get MAC address from EEPROM */
                        for (i = 0; i < 3; i++)
                                addr[i] = read_eeprom(ioaddr, i + EEPROMMACAddr);
-                        eth_hw_addr_set(net_dev, (u8 *)addr);
+                       eth_hw_addr_set(net_dev, (u8 *)addr);
 
                        rc = 1;
                        break;
index 8520812..b7c2579 100644 (file)
@@ -485,8 +485,28 @@ static int socfpga_dwmac_resume(struct device *dev)
 }
 #endif /* CONFIG_PM_SLEEP */
 
-static SIMPLE_DEV_PM_OPS(socfpga_dwmac_pm_ops, stmmac_suspend,
-                                              socfpga_dwmac_resume);
+static int __maybe_unused socfpga_dwmac_runtime_suspend(struct device *dev)
+{
+       struct net_device *ndev = dev_get_drvdata(dev);
+       struct stmmac_priv *priv = netdev_priv(ndev);
+
+       stmmac_bus_clks_config(priv, false);
+
+       return 0;
+}
+
+static int __maybe_unused socfpga_dwmac_runtime_resume(struct device *dev)
+{
+       struct net_device *ndev = dev_get_drvdata(dev);
+       struct stmmac_priv *priv = netdev_priv(ndev);
+
+       return stmmac_bus_clks_config(priv, true);
+}
+
+static const struct dev_pm_ops socfpga_dwmac_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(stmmac_suspend, socfpga_dwmac_resume)
+       SET_RUNTIME_PM_OPS(socfpga_dwmac_runtime_suspend, socfpga_dwmac_runtime_resume, NULL)
+};
 
 static const struct socfpga_dwmac_ops socfpga_gen5_ops = {
        .set_phy_mode = socfpga_gen5_set_phy_mode,
index d3f350c..2eb2845 100644 (file)
@@ -511,6 +511,14 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
        return true;
 }
 
+static inline u32 stmmac_cdc_adjust(struct stmmac_priv *priv)
+{
+       /* Correct the clk domain crossing(CDC) error */
+       if (priv->plat->has_gmac4 && priv->plat->clk_ptp_rate)
+               return (2 * NSEC_PER_SEC) / priv->plat->clk_ptp_rate;
+       return 0;
+}
+
 /* stmmac_get_tx_hwtstamp - get HW TX timestamps
  * @priv: driver private structure
  * @p : descriptor pointer
@@ -524,7 +532,6 @@ static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv,
 {
        struct skb_shared_hwtstamps shhwtstamp;
        bool found = false;
-       s64 adjust = 0;
        u64 ns = 0;
 
        if (!priv->hwts_tx_en)
@@ -543,12 +550,7 @@ static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv,
        }
 
        if (found) {
-               /* Correct the clk domain crossing(CDC) error */
-               if (priv->plat->has_gmac4 && priv->plat->clk_ptp_rate) {
-                       adjust += -(2 * (NSEC_PER_SEC /
-                                        priv->plat->clk_ptp_rate));
-                       ns += adjust;
-               }
+               ns -= stmmac_cdc_adjust(priv);
 
                memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
                shhwtstamp.hwtstamp = ns_to_ktime(ns);
@@ -573,7 +575,6 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p,
 {
        struct skb_shared_hwtstamps *shhwtstamp = NULL;
        struct dma_desc *desc = p;
-       u64 adjust = 0;
        u64 ns = 0;
 
        if (!priv->hwts_rx_en)
@@ -586,11 +587,7 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p,
        if (stmmac_get_rx_timestamp_status(priv, p, np, priv->adv_ts)) {
                stmmac_get_timestamp(priv, desc, priv->adv_ts, &ns);
 
-               /* Correct the clk domain crossing(CDC) error */
-               if (priv->plat->has_gmac4 && priv->plat->clk_ptp_rate) {
-                       adjust += 2 * (NSEC_PER_SEC / priv->plat->clk_ptp_rate);
-                       ns -= adjust;
-               }
+               ns -= stmmac_cdc_adjust(priv);
 
                netdev_dbg(priv->dev, "get valid RX hw timestamp %llu\n", ns);
                shhwtstamp = skb_hwtstamps(skb);
index bfdf89e..8a19a06 100644 (file)
@@ -306,7 +306,6 @@ static void sp_setup(struct net_device *dev)
 {
        /* Finish setting up the DEVICE info. */
        dev->netdev_ops         = &sp_netdev_ops;
-       dev->needs_free_netdev  = true;
        dev->mtu                = SIXP_MTU;
        dev->hard_header_len    = AX25_MAX_HEADER_LEN;
        dev->header_ops         = &ax25_header_ops;
index 5528d97..ef790fd 100644 (file)
@@ -853,6 +853,7 @@ static void ipa_endpoint_init_hol_block_timer(struct ipa_endpoint *endpoint,
        u32 offset;
        u32 val;
 
+       /* This should only be changed when HOL_BLOCK_EN is disabled */
        offset = IPA_REG_ENDP_INIT_HOL_BLOCK_TIMER_N_OFFSET(endpoint_id);
        val = hol_block_timer_val(ipa, microseconds);
        iowrite32(val, ipa->reg_virt + offset);
@@ -868,6 +869,9 @@ ipa_endpoint_init_hol_block_enable(struct ipa_endpoint *endpoint, bool enable)
        val = enable ? HOL_BLOCK_EN_FMASK : 0;
        offset = IPA_REG_ENDP_INIT_HOL_BLOCK_EN_N_OFFSET(endpoint_id);
        iowrite32(val, endpoint->ipa->reg_virt + offset);
+       /* When enabling, the register must be written twice for IPA v4.5+ */
+       if (enable && endpoint->ipa->version >= IPA_VERSION_4_5)
+               iowrite32(val, endpoint->ipa->reg_virt + offset);
 }
 
 void ipa_endpoint_modem_hol_block_clear_all(struct ipa *ipa)
@@ -880,6 +884,7 @@ void ipa_endpoint_modem_hol_block_clear_all(struct ipa *ipa)
                if (endpoint->toward_ipa || endpoint->ee_id != GSI_EE_MODEM)
                        continue;
 
+               ipa_endpoint_init_hol_block_enable(endpoint, false);
                ipa_endpoint_init_hol_block_timer(endpoint, 0);
                ipa_endpoint_init_hol_block_enable(endpoint, true);
        }
index e3da95d..06cec71 100644 (file)
@@ -52,7 +52,7 @@ static bool ipa_resource_limits_valid(struct ipa *ipa,
                                return false;
        }
 
-       group_count = data->rsrc_group_src_count;
+       group_count = data->rsrc_group_dst_count;
        if (!group_count || group_count > IPA_RESOURCE_GROUP_MAX)
                return false;
 
index fecc9a1..1572878 100644 (file)
@@ -1010,6 +1010,7 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct tun_struct *tun = netdev_priv(dev);
        int txq = skb->queue_mapping;
+       struct netdev_queue *queue;
        struct tun_file *tfile;
        int len = skb->len;
 
@@ -1054,6 +1055,10 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
        if (ptr_ring_produce(&tfile->tx_ring, skb))
                goto drop;
 
+       /* NETIF_F_LLTX requires to do our own update of trans_start */
+       queue = netdev_get_tx_queue(dev, txq);
+       queue->trans_start = jiffies;
+
        /* Notify and wake up reader process */
        if (tfile->flags & TUN_FASYNC)
                kill_fasync(&tfile->fasync, SIGIO, POLL_IN);
index 4a02f33..f9877a3 100644 (file)
@@ -9603,12 +9603,9 @@ static int rtl8152_probe(struct usb_interface *intf,
                netdev->hw_features &= ~NETIF_F_RXCSUM;
        }
 
-       if (le16_to_cpu(udev->descriptor.idVendor) == VENDOR_ID_LENOVO) {
-               switch (le16_to_cpu(udev->descriptor.idProduct)) {
-               case DEVICE_ID_THINKPAD_THUNDERBOLT3_DOCK_GEN2:
-               case DEVICE_ID_THINKPAD_USB_C_DOCK_GEN2:
-                       tp->lenovo_macpassthru = 1;
-               }
+       if (udev->parent &&
+                       le16_to_cpu(udev->parent->descriptor.idVendor) == VENDOR_ID_LENOVO) {
+               tp->lenovo_macpassthru = 1;
        }
 
        if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x3011 && udev->serial &&
index bae9d42..ecab906 100644 (file)
@@ -598,14 +598,14 @@ static struct irq_chip amd_gpio_irqchip = {
 
 #define PIN_IRQ_PENDING        (BIT(INTERRUPT_STS_OFF) | BIT(WAKE_STS_OFF))
 
-static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id)
+static bool do_amd_gpio_irq_handler(int irq, void *dev_id)
 {
        struct amd_gpio *gpio_dev = dev_id;
        struct gpio_chip *gc = &gpio_dev->gc;
-       irqreturn_t ret = IRQ_NONE;
        unsigned int i, irqnr;
        unsigned long flags;
        u32 __iomem *regs;
+       bool ret = false;
        u32  regval;
        u64 status, mask;
 
@@ -627,6 +627,14 @@ static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id)
                /* Each status bit covers four pins */
                for (i = 0; i < 4; i++) {
                        regval = readl(regs + i);
+                       /* caused wake on resume context for shared IRQ */
+                       if (irq < 0 && (regval & BIT(WAKE_STS_OFF))) {
+                               dev_dbg(&gpio_dev->pdev->dev,
+                                       "Waking due to GPIO %d: 0x%x",
+                                       irqnr + i, regval);
+                               return true;
+                       }
+
                        if (!(regval & PIN_IRQ_PENDING) ||
                            !(regval & BIT(INTERRUPT_MASK_OFF)))
                                continue;
@@ -650,9 +658,12 @@ static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id)
                        }
                        writel(regval, regs + i);
                        raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
-                       ret = IRQ_HANDLED;
+                       ret = true;
                }
        }
+       /* did not cause wake on resume context for shared IRQ */
+       if (irq < 0)
+               return false;
 
        /* Signal EOI to the GPIO unit */
        raw_spin_lock_irqsave(&gpio_dev->lock, flags);
@@ -664,6 +675,16 @@ static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id)
        return ret;
 }
 
+static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id)
+{
+       return IRQ_RETVAL(do_amd_gpio_irq_handler(irq, dev_id));
+}
+
+static bool __maybe_unused amd_gpio_check_wake(void *dev_id)
+{
+       return do_amd_gpio_irq_handler(-1, dev_id);
+}
+
 static int amd_get_groups_count(struct pinctrl_dev *pctldev)
 {
        struct amd_gpio *gpio_dev = pinctrl_dev_get_drvdata(pctldev);
@@ -1033,6 +1054,7 @@ static int amd_gpio_probe(struct platform_device *pdev)
                goto out2;
 
        platform_set_drvdata(pdev, gpio_dev);
+       acpi_register_wakeup_handler(gpio_dev->irq, amd_gpio_check_wake, gpio_dev);
 
        dev_dbg(&pdev->dev, "amd gpio driver loaded\n");
        return ret;
@@ -1050,6 +1072,7 @@ static int amd_gpio_remove(struct platform_device *pdev)
        gpio_dev = platform_get_drvdata(pdev);
 
        gpiochip_remove(&gpio_dev->gc);
+       acpi_unregister_wakeup_handler(amd_gpio_check_wake, gpio_dev);
 
        return 0;
 }
index 0cc346b..a786107 100644 (file)
@@ -258,7 +258,7 @@ static void apple_gpio_irq_ack(struct irq_data *data)
               pctl->base + REG_IRQ(irqgrp, data->hwirq));
 }
 
-static int apple_gpio_irq_type(unsigned int type)
+static unsigned int apple_gpio_irq_type(unsigned int type)
 {
        switch (type & IRQ_TYPE_SENSE_MASK) {
        case IRQ_TYPE_EDGE_RISING:
@@ -272,7 +272,7 @@ static int apple_gpio_irq_type(unsigned int type)
        case IRQ_TYPE_LEVEL_LOW:
                return REG_GPIOx_IN_IRQ_LO;
        default:
-               return -EINVAL;
+               return REG_GPIOx_IN_IRQ_OFF;
        }
 }
 
@@ -288,7 +288,7 @@ static void apple_gpio_irq_unmask(struct irq_data *data)
 {
        struct apple_gpio_pinctrl *pctl =
                gpiochip_get_data(irq_data_get_irq_chip_data(data));
-       int irqtype = apple_gpio_irq_type(irqd_get_trigger_type(data));
+       unsigned int irqtype = apple_gpio_irq_type(irqd_get_trigger_type(data));
 
        apple_gpio_set_reg(pctl, data->hwirq, REG_GPIOx_MODE,
                           FIELD_PREP(REG_GPIOx_MODE, irqtype));
@@ -313,10 +313,10 @@ static int apple_gpio_irq_set_type(struct irq_data *data,
 {
        struct apple_gpio_pinctrl *pctl =
                gpiochip_get_data(irq_data_get_irq_chip_data(data));
-       int irqtype = apple_gpio_irq_type(type);
+       unsigned int irqtype = apple_gpio_irq_type(type);
 
-       if (irqtype < 0)
-               return irqtype;
+       if (irqtype == REG_GPIOx_IN_IRQ_OFF)
+               return -EINVAL;
 
        apple_gpio_set_reg(pctl, data->hwirq, REG_GPIOx_MODE,
                           FIELD_PREP(REG_GPIOx_MODE, irqtype));
index b9191f1..3e0c007 100644 (file)
@@ -197,6 +197,7 @@ config PINCTRL_QCOM_SPMI_PMIC
        select PINMUX
        select PINCONF
        select GENERIC_PINCONF
+  select GPIOLIB
        select GPIOLIB_IRQCHIP
        select IRQ_DOMAIN_HIERARCHY
        help
@@ -211,6 +212,7 @@ config PINCTRL_QCOM_SSBI_PMIC
        select PINMUX
        select PINCONF
        select GENERIC_PINCONF
+  select GPIOLIB
        select GPIOLIB_IRQCHIP
        select IRQ_DOMAIN_HIERARCHY
        help
index c51793f..fdfd7b8 100644 (file)
@@ -1310,6 +1310,7 @@ static const struct msm_pinctrl_soc_data sdm845_pinctrl = {
        .ngpios = 151,
        .wakeirq_map = sdm845_pdc_map,
        .nwakeirq_map = ARRAY_SIZE(sdm845_pdc_map),
+       .wakeirq_dual_edge_errata = true,
 };
 
 static const struct msm_pinctrl_soc_data sdm845_acpi_pinctrl = {
index 4d8f863..1c042d3 100644 (file)
@@ -1597,10 +1597,10 @@ static const struct msm_pingroup sm8350_groups[] = {
        [200] = PINGROUP(200, qdss_gpio, _, _, _, _, _, _, _, _),
        [201] = PINGROUP(201, _, _, _, _, _, _, _, _, _),
        [202] = PINGROUP(202, _, _, _, _, _, _, _, _, _),
-       [203] = UFS_RESET(ufs_reset, 0x1d8000),
-       [204] = SDC_PINGROUP(sdc2_clk, 0x1cf000, 14, 6),
-       [205] = SDC_PINGROUP(sdc2_cmd, 0x1cf000, 11, 3),
-       [206] = SDC_PINGROUP(sdc2_data, 0x1cf000, 9, 0),
+       [203] = UFS_RESET(ufs_reset, 0xd8000),
+       [204] = SDC_PINGROUP(sdc2_clk, 0xcf000, 14, 6),
+       [205] = SDC_PINGROUP(sdc2_cmd, 0xcf000, 11, 3),
+       [206] = SDC_PINGROUP(sdc2_data, 0xcf000, 9, 0),
 };
 
 static const struct msm_gpio_wakeirq_map sm8350_pdc_map[] = {
index 425d55a..6853b5b 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 
+#include <asm/mach-ralink/ralink_regs.h>
 #include <asm/mach-ralink/mt7620.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
index 8d734bf..50bd26a 100644 (file)
@@ -275,7 +275,7 @@ static int tegra_pinctrl_set_mux(struct pinctrl_dev *pctldev,
        return 0;
 }
 
-static struct tegra_pingroup *tegra_pinctrl_get_group(struct pinctrl_dev *pctldev,
+static const struct tegra_pingroup *tegra_pinctrl_get_group(struct pinctrl_dev *pctldev,
                                        unsigned int offset)
 {
        struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
@@ -289,7 +289,7 @@ static struct tegra_pingroup *tegra_pinctrl_get_group(struct pinctrl_dev *pctlde
                        continue;
                for (j = 0; j < num_pins; j++) {
                        if (offset == pins[j])
-                               return (struct tegra_pingroup *)&pmx->soc->groups[group];
+                               return &pmx->soc->groups[group];
                }
        }
 
index b4fef91..5c1dfcb 100644 (file)
@@ -1387,7 +1387,6 @@ static struct tegra_function tegra194_functions[] = {
                .schmitt_bit = schmitt_b,                       \
                .drvtype_bit = 13,                              \
                .lpdr_bit = e_lpdr,                             \
-               .drv_reg = -1,                                  \
 
 #define drive_touch_clk_pcc4            DRV_PINGROUP_ENTRY_Y(0x2004,   12,     5,      20,     5,      -1,     -1,     -1,     -1,     1)
 #define drive_uart3_rx_pcc6             DRV_PINGROUP_ENTRY_Y(0x200c,   12,     5,      20,     5,      -1,     -1,     -1,     -1,     1)
index 0b7f58f..c897a2f 100644 (file)
@@ -413,7 +413,7 @@ mlxreg_lc_create_static_devices(struct mlxreg_lc *mlxreg_lc, struct mlxreg_hotpl
                                int size)
 {
        struct mlxreg_hotplug_device *dev = devs;
-       int i;
+       int i, ret;
 
        /* Create static I2C device feeding by auxiliary or main power. */
        for (i = 0; i < size; i++, dev++) {
@@ -423,6 +423,7 @@ mlxreg_lc_create_static_devices(struct mlxreg_lc *mlxreg_lc, struct mlxreg_hotpl
                                dev->brdinfo->type, dev->nr, dev->brdinfo->addr);
 
                        dev->adapter = NULL;
+                       ret = PTR_ERR(dev->client);
                        goto fail_create_static_devices;
                }
        }
@@ -435,7 +436,7 @@ fail_create_static_devices:
                i2c_unregister_device(dev->client);
                dev->client = NULL;
        }
-       return IS_ERR(dev->client);
+       return ret;
 }
 
 static void
index d4c079f..7400bc5 100644 (file)
@@ -185,7 +185,7 @@ config ACER_WMI
 
 config AMD_PMC
        tristate "AMD SoC PMC driver"
-       depends on ACPI && PCI
+       depends on ACPI && PCI && RTC_CLASS
        help
          The driver provides support for AMD Power Management Controller
          primarily responsible for S2Idle transactions that are driven from
index 2fffa57..fe224a5 100644 (file)
@@ -187,7 +187,7 @@ config DELL_WMI_AIO
 
 config DELL_WMI_DESCRIPTOR
        tristate
-       default m
+       default n
        depends on ACPI_WMI
 
 config DELL_WMI_LED
index b183967..435a91f 100644 (file)
@@ -331,9 +331,11 @@ static int lis3lv02d_probe(struct platform_device *device)
        INIT_WORK(&hpled_led.work, delayed_set_status_worker);
        ret = led_classdev_register(NULL, &hpled_led.led_classdev);
        if (ret) {
+               i8042_remove_filter(hp_accel_i8042_filter);
                lis3lv02d_joystick_disable(&lis3_dev);
                lis3lv02d_poweroff(&lis3_dev);
                flush_work(&hpled_led.work);
+               lis3lv02d_remove_fs(&lis3_dev);
                return ret;
        }
 
index 7ee010a..c1d9ed9 100644 (file)
@@ -152,7 +152,7 @@ struct sabi_config {
 
 static const struct sabi_config sabi_configs[] = {
        {
-               /* I don't know if it is really 2, but it it is
+               /* I don't know if it is really 2, but it is
                 * less than 3 anyway */
                .sabi_version = 2,
 
index 9472aae..c4d9c45 100644 (file)
@@ -888,8 +888,10 @@ static int tlmi_analyze(void)
                        break;
                if (!item)
                        break;
-               if (!*item)
+               if (!*item) {
+                       kfree(item);
                        continue;
+               }
 
                /* It is not allowed to have '/' for file name. Convert it into '\'. */
                strreplace(item, '/', '\\');
@@ -902,6 +904,7 @@ static int tlmi_analyze(void)
                setting = kzalloc(sizeof(*setting), GFP_KERNEL);
                if (!setting) {
                        ret = -ENOMEM;
+                       kfree(item);
                        goto fail_clear_attr;
                }
                setting->index = i;
@@ -916,7 +919,6 @@ static int tlmi_analyze(void)
                }
                kobject_init(&setting->kobj, &tlmi_attr_setting_ktype);
                tlmi_priv.setting[i] = setting;
-               tlmi_priv.settings_count++;
                kfree(item);
        }
 
@@ -983,7 +985,12 @@ static void tlmi_remove(struct wmi_device *wdev)
 
 static int tlmi_probe(struct wmi_device *wdev, const void *context)
 {
-       tlmi_analyze();
+       int ret;
+
+       ret = tlmi_analyze();
+       if (ret)
+               return ret;
+
        return tlmi_sysfs_init();
 }
 
index f8e2682..2ce5086 100644 (file)
@@ -55,7 +55,6 @@ struct tlmi_attr_setting {
 struct think_lmi {
        struct wmi_device *wmi_device;
 
-       int settings_count;
        bool can_set_bios_settings;
        bool can_get_bios_selections;
        bool can_set_bios_password;
index 9c632df..b3ac9c3 100644 (file)
@@ -1105,15 +1105,6 @@ static int tpacpi_rfk_update_swstate(const struct tpacpi_rfk *tp_rfk)
        return status;
 }
 
-/* Query FW and update rfkill sw state for all rfkill switches */
-static void tpacpi_rfk_update_swstate_all(void)
-{
-       unsigned int i;
-
-       for (i = 0; i < TPACPI_RFK_SW_MAX; i++)
-               tpacpi_rfk_update_swstate(tpacpi_rfkill_switches[i]);
-}
-
 /*
  * Sync the HW-blocking state of all rfkill switches,
  * do notice it causes the rfkill core to schedule uevents
@@ -3074,9 +3065,6 @@ static void tpacpi_send_radiosw_update(void)
        if (wlsw == TPACPI_RFK_RADIO_OFF)
                tpacpi_rfk_update_hwblock_state(true);
 
-       /* Sync sw blocking state */
-       tpacpi_rfk_update_swstate_all();
-
        /* Sync hw blocking state last if it is hw-unblocked */
        if (wlsw == TPACPI_RFK_RADIO_ON)
                tpacpi_rfk_update_hwblock_state(false);
@@ -8766,6 +8754,7 @@ static const struct tpacpi_quirk fan_quirk_table[] __initconst = {
        TPACPI_Q_LNV3('N', '2', 'E', TPACPI_FAN_2CTL),  /* P1 / X1 Extreme (1st gen) */
        TPACPI_Q_LNV3('N', '2', 'O', TPACPI_FAN_2CTL),  /* P1 / X1 Extreme (2nd gen) */
        TPACPI_Q_LNV3('N', '2', 'V', TPACPI_FAN_2CTL),  /* P1 / X1 Extreme (3nd gen) */
+       TPACPI_Q_LNV3('N', '4', '0', TPACPI_FAN_2CTL),  /* P1 / X1 Extreme (4nd gen) */
        TPACPI_Q_LNV3('N', '3', '0', TPACPI_FAN_2CTL),  /* P15 (1st gen) / P15v (1st gen) */
        TPACPI_Q_LNV3('N', '3', '2', TPACPI_FAN_2CTL),  /* X1 Carbon (9th gen) */
 };
index 44faa3a..b740866 100644 (file)
@@ -166,16 +166,13 @@ static struct dtpm_ops dtpm_ops = {
 
 static int cpuhp_dtpm_cpu_offline(unsigned int cpu)
 {
-       struct em_perf_domain *pd;
        struct dtpm_cpu *dtpm_cpu;
 
-       pd = em_cpu_get(cpu);
-       if (!pd)
-               return -EINVAL;
-
        dtpm_cpu = per_cpu(dtpm_per_cpu, cpu);
+       if (dtpm_cpu)
+               dtpm_update_power(&dtpm_cpu->dtpm);
 
-       return dtpm_update_power(&dtpm_cpu->dtpm);
+       return 0;
 }
 
 static int cpuhp_dtpm_cpu_online(unsigned int cpu)
index 6bc5791..08e429a 100644 (file)
@@ -1699,12 +1699,9 @@ static int initialize_dco_operating_mode(struct idtcm_channel *channel)
 
 /* PTP Hardware Clock interface */
 
-/**
+/*
  * Maximum absolute value for write phase offset in picoseconds
  *
- * @channel:  channel
- * @delta_ns: delta in nanoseconds
- *
  * Destination signed register is 32-bit register in resolution of 50ps
  *
  * 0x7fffffff * 50 =  2147483647 * 50 = 107374182350
index 34f943c..0f1b5a7 100644 (file)
@@ -1304,10 +1304,11 @@ ptp_ocp_register_ext(struct ptp_ocp *bp, struct ocp_resource *r)
        if (!ext)
                return -ENOMEM;
 
-       err = -EINVAL;
        ext->mem = ptp_ocp_get_mem(bp, r);
-       if (!ext->mem)
+       if (IS_ERR(ext->mem)) {
+               err = PTR_ERR(ext->mem);
                goto out;
+       }
 
        ext->bp = bp;
        ext->info = r->extra;
@@ -1371,8 +1372,8 @@ ptp_ocp_register_mem(struct ptp_ocp *bp, struct ocp_resource *r)
        void __iomem *mem;
 
        mem = ptp_ocp_get_mem(bp, r);
-       if (!mem)
-               return -EINVAL;
+       if (IS_ERR(mem))
+               return PTR_ERR(mem);
 
        bp_assign_entry(bp, r, mem);
 
index 2c40fe1..6043c83 100644 (file)
@@ -731,7 +731,7 @@ static ssize_t dasd_ff_show(struct device *dev, struct device_attribute *attr,
                ff_flag = (devmap->features & DASD_FEATURE_FAILFAST) != 0;
        else
                ff_flag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_FAILFAST) != 0;
-       return snprintf(buf, PAGE_SIZE, ff_flag ? "1\n" : "0\n");
+       return sysfs_emit(buf, ff_flag ? "1\n" : "0\n");
 }
 
 static ssize_t dasd_ff_store(struct device *dev, struct device_attribute *attr,
@@ -773,7 +773,7 @@ dasd_ro_show(struct device *dev, struct device_attribute *attr, char *buf)
        spin_unlock(&dasd_devmap_lock);
 
 out:
-       return snprintf(buf, PAGE_SIZE, ro_flag ? "1\n" : "0\n");
+       return sysfs_emit(buf, ro_flag ? "1\n" : "0\n");
 }
 
 static ssize_t
@@ -834,7 +834,7 @@ dasd_erplog_show(struct device *dev, struct device_attribute *attr, char *buf)
                erplog = (devmap->features & DASD_FEATURE_ERPLOG) != 0;
        else
                erplog = (DASD_FEATURE_DEFAULT & DASD_FEATURE_ERPLOG) != 0;
-       return snprintf(buf, PAGE_SIZE, erplog ? "1\n" : "0\n");
+       return sysfs_emit(buf, erplog ? "1\n" : "0\n");
 }
 
 static ssize_t
@@ -1033,13 +1033,13 @@ dasd_discipline_show(struct device *dev, struct device_attribute *attr,
                dasd_put_device(device);
                goto out;
        } else {
-               len = snprintf(buf, PAGE_SIZE, "%s\n",
-                              device->discipline->name);
+               len = sysfs_emit(buf, "%s\n",
+                                device->discipline->name);
                dasd_put_device(device);
                return len;
        }
 out:
-       len = snprintf(buf, PAGE_SIZE, "none\n");
+       len = sysfs_emit(buf, "none\n");
        return len;
 }
 
@@ -1056,30 +1056,30 @@ dasd_device_status_show(struct device *dev, struct device_attribute *attr,
        if (!IS_ERR(device)) {
                switch (device->state) {
                case DASD_STATE_NEW:
-                       len = snprintf(buf, PAGE_SIZE, "new\n");
+                       len = sysfs_emit(buf, "new\n");
                        break;
                case DASD_STATE_KNOWN:
-                       len = snprintf(buf, PAGE_SIZE, "detected\n");
+                       len = sysfs_emit(buf, "detected\n");
                        break;
                case DASD_STATE_BASIC:
-                       len = snprintf(buf, PAGE_SIZE, "basic\n");
+                       len = sysfs_emit(buf, "basic\n");
                        break;
                case DASD_STATE_UNFMT:
-                       len = snprintf(buf, PAGE_SIZE, "unformatted\n");
+                       len = sysfs_emit(buf, "unformatted\n");
                        break;
                case DASD_STATE_READY:
-                       len = snprintf(buf, PAGE_SIZE, "ready\n");
+                       len = sysfs_emit(buf, "ready\n");
                        break;
                case DASD_STATE_ONLINE:
-                       len = snprintf(buf, PAGE_SIZE, "online\n");
+                       len = sysfs_emit(buf, "online\n");
                        break;
                default:
-                       len = snprintf(buf, PAGE_SIZE, "no stat\n");
+                       len = sysfs_emit(buf, "no stat\n");
                        break;
                }
                dasd_put_device(device);
        } else
-               len = snprintf(buf, PAGE_SIZE, "unknown\n");
+               len = sysfs_emit(buf, "unknown\n");
        return len;
 }
 
@@ -1120,7 +1120,7 @@ static ssize_t dasd_vendor_show(struct device *dev,
        device = dasd_device_from_cdev(to_ccwdev(dev));
        vendor = "";
        if (IS_ERR(device))
-               return snprintf(buf, PAGE_SIZE, "%s\n", vendor);
+               return sysfs_emit(buf, "%s\n", vendor);
 
        if (device->discipline && device->discipline->get_uid &&
            !device->discipline->get_uid(device, &uid))
@@ -1128,7 +1128,7 @@ static ssize_t dasd_vendor_show(struct device *dev,
 
        dasd_put_device(device);
 
-       return snprintf(buf, PAGE_SIZE, "%s\n", vendor);
+       return sysfs_emit(buf, "%s\n", vendor);
 }
 
 static DEVICE_ATTR(vendor, 0444, dasd_vendor_show, NULL);
@@ -1148,7 +1148,7 @@ dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf)
        device = dasd_device_from_cdev(to_ccwdev(dev));
        uid_string[0] = 0;
        if (IS_ERR(device))
-               return snprintf(buf, PAGE_SIZE, "%s\n", uid_string);
+               return sysfs_emit(buf, "%s\n", uid_string);
 
        if (device->discipline && device->discipline->get_uid &&
            !device->discipline->get_uid(device, &uid)) {
@@ -1183,7 +1183,7 @@ dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf)
        }
        dasd_put_device(device);
 
-       return snprintf(buf, PAGE_SIZE, "%s\n", uid_string);
+       return sysfs_emit(buf, "%s\n", uid_string);
 }
 static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL);
 
@@ -1201,7 +1201,7 @@ dasd_eer_show(struct device *dev, struct device_attribute *attr, char *buf)
                eer_flag = dasd_eer_enabled(devmap->device);
        else
                eer_flag = 0;
-       return snprintf(buf, PAGE_SIZE, eer_flag ? "1\n" : "0\n");
+       return sysfs_emit(buf, eer_flag ? "1\n" : "0\n");
 }
 
 static ssize_t
@@ -1243,7 +1243,7 @@ dasd_expires_show(struct device *dev, struct device_attribute *attr, char *buf)
        device = dasd_device_from_cdev(to_ccwdev(dev));
        if (IS_ERR(device))
                return -ENODEV;
-       len = snprintf(buf, PAGE_SIZE, "%lu\n", device->default_expires);
+       len = sysfs_emit(buf, "%lu\n", device->default_expires);
        dasd_put_device(device);
        return len;
 }
@@ -1283,7 +1283,7 @@ dasd_retries_show(struct device *dev, struct device_attribute *attr, char *buf)
        device = dasd_device_from_cdev(to_ccwdev(dev));
        if (IS_ERR(device))
                return -ENODEV;
-       len = snprintf(buf, PAGE_SIZE, "%lu\n", device->default_retries);
+       len = sysfs_emit(buf, "%lu\n", device->default_retries);
        dasd_put_device(device);
        return len;
 }
@@ -1324,7 +1324,7 @@ dasd_timeout_show(struct device *dev, struct device_attribute *attr,
        device = dasd_device_from_cdev(to_ccwdev(dev));
        if (IS_ERR(device))
                return -ENODEV;
-       len = snprintf(buf, PAGE_SIZE, "%lu\n", device->blk_timeout);
+       len = sysfs_emit(buf, "%lu\n", device->blk_timeout);
        dasd_put_device(device);
        return len;
 }
@@ -1398,11 +1398,11 @@ static ssize_t dasd_hpf_show(struct device *dev, struct device_attribute *attr,
                return -ENODEV;
        if (!device->discipline || !device->discipline->hpf_enabled) {
                dasd_put_device(device);
-               return snprintf(buf, PAGE_SIZE, "%d\n", dasd_nofcx);
+               return sysfs_emit(buf, "%d\n", dasd_nofcx);
        }
        hpf = device->discipline->hpf_enabled(device);
        dasd_put_device(device);
-       return snprintf(buf, PAGE_SIZE, "%d\n", hpf);
+       return sysfs_emit(buf, "%d\n", hpf);
 }
 
 static DEVICE_ATTR(hpf, 0444, dasd_hpf_show, NULL);
@@ -1416,13 +1416,13 @@ static ssize_t dasd_reservation_policy_show(struct device *dev,
 
        devmap = dasd_find_busid(dev_name(dev));
        if (IS_ERR(devmap)) {
-               rc = snprintf(buf, PAGE_SIZE, "ignore\n");
+               rc = sysfs_emit(buf, "ignore\n");
        } else {
                spin_lock(&dasd_devmap_lock);
                if (devmap->features & DASD_FEATURE_FAILONSLCK)
-                       rc = snprintf(buf, PAGE_SIZE, "fail\n");
+                       rc = sysfs_emit(buf, "fail\n");
                else
-                       rc = snprintf(buf, PAGE_SIZE, "ignore\n");
+                       rc = sysfs_emit(buf, "ignore\n");
                spin_unlock(&dasd_devmap_lock);
        }
        return rc;
@@ -1457,14 +1457,14 @@ static ssize_t dasd_reservation_state_show(struct device *dev,
 
        device = dasd_device_from_cdev(to_ccwdev(dev));
        if (IS_ERR(device))
-               return snprintf(buf, PAGE_SIZE, "none\n");
+               return sysfs_emit(buf, "none\n");
 
        if (test_bit(DASD_FLAG_IS_RESERVED, &device->flags))
-               rc = snprintf(buf, PAGE_SIZE, "reserved\n");
+               rc = sysfs_emit(buf, "reserved\n");
        else if (test_bit(DASD_FLAG_LOCK_STOLEN, &device->flags))
-               rc = snprintf(buf, PAGE_SIZE, "lost\n");
+               rc = sysfs_emit(buf, "lost\n");
        else
-               rc = snprintf(buf, PAGE_SIZE, "none\n");
+               rc = sysfs_emit(buf, "none\n");
        dasd_put_device(device);
        return rc;
 }
@@ -1531,7 +1531,7 @@ dasd_path_threshold_show(struct device *dev,
        device = dasd_device_from_cdev(to_ccwdev(dev));
        if (IS_ERR(device))
                return -ENODEV;
-       len = snprintf(buf, PAGE_SIZE, "%lu\n", device->path_thrhld);
+       len = sysfs_emit(buf, "%lu\n", device->path_thrhld);
        dasd_put_device(device);
        return len;
 }
@@ -1578,7 +1578,7 @@ dasd_path_autodisable_show(struct device *dev,
        else
                flag = (DASD_FEATURE_DEFAULT &
                        DASD_FEATURE_PATH_AUTODISABLE) != 0;
-       return snprintf(buf, PAGE_SIZE, flag ? "1\n" : "0\n");
+       return sysfs_emit(buf, flag ? "1\n" : "0\n");
 }
 
 static ssize_t
@@ -1616,7 +1616,7 @@ dasd_path_interval_show(struct device *dev,
        device = dasd_device_from_cdev(to_ccwdev(dev));
        if (IS_ERR(device))
                return -ENODEV;
-       len = snprintf(buf, PAGE_SIZE, "%lu\n", device->path_interval);
+       len = sysfs_emit(buf, "%lu\n", device->path_interval);
        dasd_put_device(device);
        return len;
 }
@@ -1662,9 +1662,9 @@ dasd_device_fcs_show(struct device *dev, struct device_attribute *attr,
                return -ENODEV;
        fc_sec = dasd_path_get_fcs_device(device);
        if (fc_sec == -EINVAL)
-               rc = snprintf(buf, PAGE_SIZE, "Inconsistent\n");
+               rc = sysfs_emit(buf, "Inconsistent\n");
        else
-               rc = snprintf(buf, PAGE_SIZE, "%s\n", dasd_path_get_fcs_str(fc_sec));
+               rc = sysfs_emit(buf, "%s\n", dasd_path_get_fcs_str(fc_sec));
        dasd_put_device(device);
 
        return rc;
@@ -1677,7 +1677,7 @@ dasd_path_fcs_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
        struct dasd_path *path = to_dasd_path(kobj);
        unsigned int fc_sec = path->fc_security;
 
-       return snprintf(buf, PAGE_SIZE, "%s\n", dasd_path_get_fcs_str(fc_sec));
+       return sysfs_emit(buf, "%s\n", dasd_path_get_fcs_str(fc_sec));
 }
 
 static struct kobj_attribute path_fcs_attribute =
@@ -1698,7 +1698,7 @@ static ssize_t dasd_##_name##_show(struct device *dev,                    \
                val = _func(device);                                    \
        dasd_put_device(device);                                        \
                                                                        \
-       return snprintf(buf, PAGE_SIZE, "%d\n", val);                   \
+       return sysfs_emit(buf, "%d\n", val);                    \
 }                                                                      \
 static DEVICE_ATTR(_name, 0444, dasd_##_name##_show, NULL);            \
 
index 646ec79..dfde0d9 100644 (file)
@@ -1047,24 +1047,24 @@ raw3270_probe (struct ccw_device *cdev)
 static ssize_t
 raw3270_model_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       return snprintf(buf, PAGE_SIZE, "%i\n",
-                       ((struct raw3270 *) dev_get_drvdata(dev))->model);
+       return sysfs_emit(buf, "%i\n",
+                         ((struct raw3270 *)dev_get_drvdata(dev))->model);
 }
 static DEVICE_ATTR(model, 0444, raw3270_model_show, NULL);
 
 static ssize_t
 raw3270_rows_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       return snprintf(buf, PAGE_SIZE, "%i\n",
-                       ((struct raw3270 *) dev_get_drvdata(dev))->rows);
+       return sysfs_emit(buf, "%i\n",
+                         ((struct raw3270 *)dev_get_drvdata(dev))->rows);
 }
 static DEVICE_ATTR(rows, 0444, raw3270_rows_show, NULL);
 
 static ssize_t
 raw3270_columns_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       return snprintf(buf, PAGE_SIZE, "%i\n",
-                       ((struct raw3270 *) dev_get_drvdata(dev))->cols);
+       return sysfs_emit(buf, "%i\n",
+                         ((struct raw3270 *)dev_get_drvdata(dev))->cols);
 }
 static DEVICE_ATTR(columns, 0444, raw3270_columns_show, NULL);
 
index 1097e76..5440f28 100644 (file)
@@ -285,7 +285,7 @@ static ssize_t chp_configure_show(struct device *dev,
        if (status < 0)
                return status;
 
-       return snprintf(buf, PAGE_SIZE, "%d\n", status);
+       return sysfs_emit(buf, "%d\n", status);
 }
 
 static int cfg_wait_idle(void);
index 73a3531..10d2655 100644 (file)
@@ -1695,10 +1695,8 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa,
                mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10;
        if (IS_FWI2_CAPABLE(vha->hw))
                mcp->in_mb |= MBX_19|MBX_18|MBX_17|MBX_16;
-       if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw)) {
-               mcp->in_mb |= MBX_15;
-               mcp->out_mb |= MBX_7|MBX_21|MBX_22|MBX_23;
-       }
+       if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw))
+               mcp->in_mb |= MBX_15|MBX_21|MBX_22|MBX_23;
 
        mcp->tov = MBX_TOV_SECONDS;
        mcp->flags = 0;
index 55addd7..7afcec2 100644 (file)
@@ -792,6 +792,7 @@ store_state_field(struct device *dev, struct device_attribute *attr,
        int i, ret;
        struct scsi_device *sdev = to_scsi_device(dev);
        enum scsi_device_state state = 0;
+       bool rescan_dev = false;
 
        for (i = 0; i < ARRAY_SIZE(sdev_states); i++) {
                const int len = strlen(sdev_states[i].name);
@@ -810,20 +811,27 @@ store_state_field(struct device *dev, struct device_attribute *attr,
        }
 
        mutex_lock(&sdev->state_mutex);
-       ret = scsi_device_set_state(sdev, state);
-       /*
-        * If the device state changes to SDEV_RUNNING, we need to
-        * run the queue to avoid I/O hang, and rescan the device
-        * to revalidate it. Running the queue first is necessary
-        * because another thread may be waiting inside
-        * blk_mq_freeze_queue_wait() and because that call may be
-        * waiting for pending I/O to finish.
-        */
-       if (ret == 0 && state == SDEV_RUNNING) {
+       if (sdev->sdev_state == SDEV_RUNNING && state == SDEV_RUNNING) {
+               ret = count;
+       } else {
+               ret = scsi_device_set_state(sdev, state);
+               if (ret == 0 && state == SDEV_RUNNING)
+                       rescan_dev = true;
+       }
+       mutex_unlock(&sdev->state_mutex);
+
+       if (rescan_dev) {
+               /*
+                * If the device state changes to SDEV_RUNNING, we need to
+                * run the queue to avoid I/O hang, and rescan the device
+                * to revalidate it. Running the queue first is necessary
+                * because another thread may be waiting inside
+                * blk_mq_freeze_queue_wait() and because that call may be
+                * waiting for pending I/O to finish.
+                */
                blk_mq_run_hw_queues(sdev->request_queue, true);
                scsi_rescan_device(dev);
        }
-       mutex_unlock(&sdev->state_mutex);
 
        return ret == 0 ? count : -EINVAL;
 }
index 78343d3..554b6f7 100644 (file)
@@ -1899,12 +1899,12 @@ static void session_recovery_timedout(struct work_struct *work)
        }
        spin_unlock_irqrestore(&session->lock, flags);
 
-       if (session->transport->session_recovery_timedout)
-               session->transport->session_recovery_timedout(session);
-
        ISCSI_DBG_TRANS_SESSION(session, "Unblocking SCSI target\n");
        scsi_target_unblock(&session->dev, SDEV_TRANSPORT_OFFLINE);
        ISCSI_DBG_TRANS_SESSION(session, "Completed unblocking SCSI target\n");
+
+       if (session->transport->session_recovery_timedout)
+               session->transport->session_recovery_timedout(session);
 }
 
 static void __iscsi_unblock_session(struct work_struct *work)
index afd3814..13c09db 100644 (file)
@@ -6453,9 +6453,8 @@ static irqreturn_t ufshcd_tmc_handler(struct ufs_hba *hba)
        irqreturn_t ret = IRQ_NONE;
        int tag;
 
-       pending = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL);
-
        spin_lock_irqsave(hba->host->host_lock, flags);
+       pending = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL);
        issued = hba->outstanding_tasks & ~pending;
        for_each_set_bit(tag, &issued, hba->nutmrs) {
                struct request *req = hba->tmf_rqs[tag];
@@ -6616,11 +6615,6 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
        err = wait_for_completion_io_timeout(&wait,
                        msecs_to_jiffies(TM_CMD_TIMEOUT));
        if (!err) {
-               /*
-                * Make sure that ufshcd_compl_tm() does not trigger a
-                * use-after-free.
-                */
-               req->end_io_data = NULL;
                ufshcd_add_tm_upiu_trace(hba, task_tag, UFS_TM_ERR);
                dev_err(hba->dev, "%s: task management cmd 0x%.2x timed-out\n",
                                __func__, tm_function);
@@ -7116,6 +7110,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
                goto release;
        }
 
+       lrbp->cmd = NULL;
        err = SUCCESS;
 
 release:
index 8b3d268..b808c94 100644 (file)
@@ -37,6 +37,7 @@
 #define CQSPI_NEEDS_WR_DELAY           BIT(0)
 #define CQSPI_DISABLE_DAC_MODE         BIT(1)
 #define CQSPI_SUPPORT_EXTERNAL_DMA     BIT(2)
+#define CQSPI_NO_SUPPORT_WR_COMPLETION BIT(3)
 
 /* Capabilities */
 #define CQSPI_SUPPORTS_OCTAL           BIT(0)
@@ -86,6 +87,7 @@ struct cqspi_st {
        struct cqspi_flash_pdata f_pdata[CQSPI_MAX_CHIPSELECT];
        bool                    use_dma_read;
        u32                     pd_dev_id;
+       bool                    wr_completion;
 };
 
 struct cqspi_driver_platdata {
@@ -996,9 +998,11 @@ static int cqspi_write_setup(struct cqspi_flash_pdata *f_pdata,
         * polling on the controller's side. spinand and spi-nor will take
         * care of polling the status register.
         */
-       reg = readl(reg_base + CQSPI_REG_WR_COMPLETION_CTRL);
-       reg |= CQSPI_REG_WR_DISABLE_AUTO_POLL;
-       writel(reg, reg_base + CQSPI_REG_WR_COMPLETION_CTRL);
+       if (cqspi->wr_completion) {
+               reg = readl(reg_base + CQSPI_REG_WR_COMPLETION_CTRL);
+               reg |= CQSPI_REG_WR_DISABLE_AUTO_POLL;
+               writel(reg, reg_base + CQSPI_REG_WR_COMPLETION_CTRL);
+       }
 
        reg = readl(reg_base + CQSPI_REG_SIZE);
        reg &= ~CQSPI_REG_SIZE_ADDRESS_MASK;
@@ -1736,6 +1740,10 @@ static int cqspi_probe(struct platform_device *pdev)
 
        cqspi->master_ref_clk_hz = clk_get_rate(cqspi->clk);
        master->max_speed_hz = cqspi->master_ref_clk_hz;
+
+       /* write completion is supported by default */
+       cqspi->wr_completion = true;
+
        ddata  = of_device_get_match_data(dev);
        if (ddata) {
                if (ddata->quirks & CQSPI_NEEDS_WR_DELAY)
@@ -1747,6 +1755,8 @@ static int cqspi_probe(struct platform_device *pdev)
                        cqspi->use_direct_mode = true;
                if (ddata->quirks & CQSPI_SUPPORT_EXTERNAL_DMA)
                        cqspi->use_dma_read = true;
+               if (ddata->quirks & CQSPI_NO_SUPPORT_WR_COMPLETION)
+                       cqspi->wr_completion = false;
 
                if (of_device_is_compatible(pdev->dev.of_node,
                                            "xlnx,versal-ospi-1.0"))
@@ -1859,6 +1869,10 @@ static const struct cqspi_driver_platdata intel_lgm_qspi = {
        .quirks = CQSPI_DISABLE_DAC_MODE,
 };
 
+static const struct cqspi_driver_platdata socfpga_qspi = {
+       .quirks = CQSPI_NO_SUPPORT_WR_COMPLETION,
+};
+
 static const struct cqspi_driver_platdata versal_ospi = {
        .hwcaps_mask = CQSPI_SUPPORTS_OCTAL,
        .quirks = CQSPI_DISABLE_DAC_MODE | CQSPI_SUPPORT_EXTERNAL_DMA,
@@ -1887,6 +1901,10 @@ static const struct of_device_id cqspi_dt_ids[] = {
                .compatible = "xlnx,versal-ospi-1.0",
                .data = (void *)&versal_ospi,
        },
+       {
+               .compatible = "intel,socfpga-qspi",
+               .data = (void *)&socfpga_qspi,
+       },
        { /* end of table */ }
 };
 
index 5d98611..c72e501 100644 (file)
@@ -912,7 +912,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
 
        ret = devm_spi_register_controller(&pdev->dev, controller);
        if (ret < 0) {
-               dev_err(&pdev->dev, "spi_register_controller error.\n");
+               dev_err_probe(&pdev->dev, ret, "spi_register_controller error: %i\n", ret);
                goto out_pm_get;
        }
 
index 27a446f..e2affae 100644 (file)
@@ -491,22 +491,26 @@ static int spi_geni_grab_gpi_chan(struct spi_geni_master *mas)
        int ret;
 
        mas->tx = dma_request_chan(mas->dev, "tx");
-       ret = dev_err_probe(mas->dev, IS_ERR(mas->tx), "Failed to get tx DMA ch\n");
-       if (ret < 0)
+       if (IS_ERR(mas->tx)) {
+               ret = dev_err_probe(mas->dev, PTR_ERR(mas->tx),
+                                   "Failed to get tx DMA ch\n");
                goto err_tx;
+       }
 
        mas->rx = dma_request_chan(mas->dev, "rx");
-       ret = dev_err_probe(mas->dev, IS_ERR(mas->rx), "Failed to get rx DMA ch\n");
-       if (ret < 0)
+       if (IS_ERR(mas->rx)) {
+               ret = dev_err_probe(mas->dev, PTR_ERR(mas->rx),
+                                   "Failed to get rx DMA ch\n");
                goto err_rx;
+       }
 
        return 0;
 
 err_rx:
+       mas->rx = NULL;
        dma_release_channel(mas->tx);
-       mas->tx = NULL;
 err_tx:
-       mas->rx = NULL;
+       mas->tx = NULL;
        return ret;
 }
 
index b23e675..fdd530b 100644 (file)
@@ -3099,12 +3099,6 @@ void spi_unregister_controller(struct spi_controller *ctlr)
 
        device_del(&ctlr->dev);
 
-       /* Release the last reference on the controller if its driver
-        * has not yet been converted to devm_spi_alloc_master/slave().
-        */
-       if (!ctlr->devm_allocated)
-               put_device(&ctlr->dev);
-
        /* free bus id */
        mutex_lock(&board_lock);
        if (found == ctlr)
@@ -3113,6 +3107,12 @@ void spi_unregister_controller(struct spi_controller *ctlr)
 
        if (IS_ENABLED(CONFIG_SPI_DYNAMIC))
                mutex_unlock(&ctlr->add_lock);
+
+       /* Release the last reference on the controller if its driver
+        * has not yet been converted to devm_spi_alloc_master/slave().
+        */
+       if (!ctlr->devm_allocated)
+               put_device(&ctlr->dev);
 }
 EXPORT_SYMBOL_GPL(spi_unregister_controller);
 
index 45c31f3..5d046de 100644 (file)
@@ -5,12 +5,12 @@
 
 config INT340X_THERMAL
        tristate "ACPI INT340X thermal drivers"
-       depends on X86 && ACPI && PCI
+       depends on X86_64 && ACPI && PCI
        select THERMAL_GOV_USER_SPACE
        select ACPI_THERMAL_REL
        select ACPI_FAN
        select INTEL_SOC_DTS_IOSF_CORE
-       select PROC_THERMAL_MMIO_RAPL if X86_64 && POWERCAP
+       select PROC_THERMAL_MMIO_RAPL if POWERCAP
        help
          Newer laptops and tablets that use ACPI may have thermal sensors and
          other devices with thermal control capabilities outside the core
index 648829a..82654dc 100644 (file)
@@ -421,6 +421,8 @@ static void thermal_zone_device_init(struct thermal_zone_device *tz)
 {
        struct thermal_instance *pos;
        tz->temperature = THERMAL_TEMP_INVALID;
+       tz->prev_low_trip = -INT_MAX;
+       tz->prev_high_trip = INT_MAX;
        list_for_each_entry(pos, &tz->thermal_instances, tz_node)
                pos->initialized = false;
 }
index 1b45116..40496e9 100644 (file)
@@ -332,13 +332,13 @@ static u8 sticon_build_attr(struct vc_data *conp, u8 color,
                            bool blink, bool underline, bool reverse,
                            bool italic)
 {
-    u8 attr = ((color & 0x70) >> 1) | ((color & 7));
+       u8 fg = color & 7;
+       u8 bg = (color & 0x70) >> 4;
 
-    if (reverse) {
-       color = ((color >> 3) & 0x7) | ((color & 0x7) << 3);
-    }
-
-    return attr;
+       if (reverse)
+               return (fg << 3) | bg;
+       else
+               return (bg << 3) | fg;
 }
 
 static void sticon_invert_region(struct vc_data *conp, u16 *p, int count)
index edca370..ea42ba6 100644 (file)
@@ -351,6 +351,17 @@ static int efifb_probe(struct platform_device *dev)
        char *option = NULL;
        efi_memory_desc_t md;
 
+       /*
+        * Generic drivers must not be registered if a framebuffer exists.
+        * If a native driver was probed, the display hardware was already
+        * taken and attempting to use the system framebuffer is dangerous.
+        */
+       if (num_registered_fb > 0) {
+               dev_err(&dev->dev,
+                       "efifb: a framebuffer is already registered\n");
+               return -EINVAL;
+       }
+
        if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI || pci_dev_disabled)
                return -ENODEV;
 
index 62f0ded..b63074f 100644 (file)
@@ -407,6 +407,17 @@ static int simplefb_probe(struct platform_device *pdev)
        struct simplefb_par *par;
        struct resource *mem;
 
+       /*
+        * Generic drivers must not be registered if a framebuffer exists.
+        * If a native driver was probed, the display hardware was already
+        * taken and attempting to use the system framebuffer is dangerous.
+        */
+       if (num_registered_fb > 0) {
+               dev_err(&pdev->dev,
+                       "simplefb: a framebuffer is already registered\n");
+               return -EINVAL;
+       }
+
        if (fb_get_options("simplefb", NULL))
                return -ENODEV;
 
index 473d21b..66899b6 100644 (file)
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -35,7 +35,7 @@ static bool chown_ok(struct user_namespace *mnt_userns,
                     kuid_t uid)
 {
        kuid_t kuid = i_uid_into_mnt(mnt_userns, inode);
-       if (uid_eq(current_fsuid(), kuid) && uid_eq(uid, kuid))
+       if (uid_eq(current_fsuid(), kuid) && uid_eq(uid, inode->i_uid))
                return true;
        if (capable_wrt_inode_uidgid(mnt_userns, inode, CAP_CHOWN))
                return true;
@@ -62,7 +62,7 @@ static bool chgrp_ok(struct user_namespace *mnt_userns,
 {
        kgid_t kgid = i_gid_into_mnt(mnt_userns, inode);
        if (uid_eq(current_fsuid(), i_uid_into_mnt(mnt_userns, inode)) &&
-           (in_group_p(gid) || gid_eq(gid, kgid)))
+           (in_group_p(gid) || gid_eq(gid, inode->i_gid)))
                return true;
        if (capable_wrt_inode_uidgid(mnt_userns, inode, CAP_CHOWN))
                return true;
index 309516e..43c8995 100644 (file)
@@ -234,6 +234,13 @@ static void run_ordered_work(struct __btrfs_workqueue *wq,
                                  ordered_list);
                if (!test_bit(WORK_DONE_BIT, &work->flags))
                        break;
+               /*
+                * Orders all subsequent loads after reading WORK_DONE_BIT,
+                * paired with the smp_mb__before_atomic in btrfs_work_helper
+                * this guarantees that the ordered function will see all
+                * updates from ordinary work function.
+                */
+               smp_rmb();
 
                /*
                 * we are going to call the ordered done function, but
@@ -317,6 +324,13 @@ static void btrfs_work_helper(struct work_struct *normal_work)
        thresh_exec_hook(wq);
        work->func(work);
        if (need_order) {
+               /*
+                * Ensures all memory accesses done in the work function are
+                * ordered before setting the WORK_DONE_BIT. Ensuring the thread
+                * which is going to executed the ordered work sees them.
+                * Pairs with the smp_rmb in run_ordered_work.
+                */
+               smp_mb__before_atomic();
                set_bit(WORK_DONE_BIT, &work->flags);
                run_ordered_work(wq, work);
        } else {
index 59c3be8..514ead6 100644 (file)
@@ -3978,11 +3978,23 @@ static void btrfs_end_empty_barrier(struct bio *bio)
  */
 static void write_dev_flush(struct btrfs_device *device)
 {
-       struct request_queue *q = bdev_get_queue(device->bdev);
        struct bio *bio = device->flush_bio;
 
+#ifndef CONFIG_BTRFS_FS_CHECK_INTEGRITY
+       /*
+        * When a disk has write caching disabled, we skip submission of a bio
+        * with flush and sync requests before writing the superblock, since
+        * it's not needed. However when the integrity checker is enabled, this
+        * results in reports that there are metadata blocks referred by a
+        * superblock that were not properly flushed. So don't skip the bio
+        * submission only when the integrity checker is enabled for the sake
+        * of simplicity, since this is a debug tool and not meant for use in
+        * non-debug builds.
+        */
+       struct request_queue *q = bdev_get_queue(device->bdev);
        if (!test_bit(QUEUE_FLAG_WC, &q->queue_flags))
                return;
+#endif
 
        bio_reset(bio);
        bio->bi_end_io = btrfs_end_empty_barrier;
index fb8cc96..92138ac 100644 (file)
@@ -3985,6 +3985,10 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg)
        bool need_unlock; /* for mut. excl. ops lock */
        int ret;
 
+       if (!arg)
+               btrfs_warn(fs_info,
+       "IOC_BALANCE ioctl (v1) is deprecated and will be removed in kernel 5.18");
+
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
index 65cb076..9febb80 100644 (file)
@@ -125,6 +125,7 @@ static inline size_t read_compress_length(const char *buf)
 static int copy_compressed_data_to_page(char *compressed_data,
                                        size_t compressed_size,
                                        struct page **out_pages,
+                                       unsigned long max_nr_page,
                                        u32 *cur_out,
                                        const u32 sectorsize)
 {
@@ -133,6 +134,9 @@ static int copy_compressed_data_to_page(char *compressed_data,
        struct page *cur_page;
        char *kaddr;
 
+       if ((*cur_out / PAGE_SIZE) >= max_nr_page)
+               return -E2BIG;
+
        /*
         * We never allow a segment header crossing sector boundary, previous
         * run should ensure we have enough space left inside the sector.
@@ -161,6 +165,10 @@ static int copy_compressed_data_to_page(char *compressed_data,
                                     orig_out + compressed_size - *cur_out);
 
                kunmap(cur_page);
+
+               if ((*cur_out / PAGE_SIZE) >= max_nr_page)
+                       return -E2BIG;
+
                cur_page = out_pages[*cur_out / PAGE_SIZE];
                /* Allocate a new page */
                if (!cur_page) {
@@ -203,6 +211,7 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping,
        const u32 sectorsize = btrfs_sb(mapping->host->i_sb)->sectorsize;
        struct page *page_in = NULL;
        char *sizes_ptr;
+       const unsigned long max_nr_page = *out_pages;
        int ret = 0;
        /* Points to the file offset of input data */
        u64 cur_in = start;
@@ -210,6 +219,7 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping,
        u32 cur_out = 0;
        u32 len = *total_out;
 
+       ASSERT(max_nr_page > 0);
        *out_pages = 0;
        *total_out = 0;
        *total_in = 0;
@@ -248,7 +258,8 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping,
                }
 
                ret = copy_compressed_data_to_page(workspace->cbuf, out_len,
-                                                  pages, &cur_out, sectorsize);
+                                                  pages, max_nr_page,
+                                                  &cur_out, sectorsize);
                if (ret < 0)
                        goto out;
 
index cf82ea6..8f6ceea 100644 (file)
@@ -73,8 +73,8 @@ struct scrub_page {
        u64                     physical_for_dev_replace;
        atomic_t                refs;
        u8                      mirror_num;
-       int                     have_csum:1;
-       int                     io_error:1;
+       unsigned int            have_csum:1;
+       unsigned int            io_error:1;
        u8                      csum[BTRFS_CSUM_SIZE];
 
        struct scrub_recover    *recover;
index 61ac57b..0997e3c 100644 (file)
@@ -7559,6 +7559,19 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info)
        fs_info->fs_devices->total_rw_bytes = 0;
 
        /*
+        * Lockdep complains about possible circular locking dependency between
+        * a disk's open_mutex (struct gendisk.open_mutex), the rw semaphores
+        * used for freeze procection of a fs (struct super_block.s_writers),
+        * which we take when starting a transaction, and extent buffers of the
+        * chunk tree if we call read_one_dev() while holding a lock on an
+        * extent buffer of the chunk tree. Since we are mounting the filesystem
+        * and at this point there can't be any concurrent task modifying the
+        * chunk tree, to keep it simple, just skip locking on the chunk tree.
+        */
+       ASSERT(!test_bit(BTRFS_FS_OPEN, &fs_info->flags));
+       path->skip_locking = 1;
+
+       /*
         * Read all device items, and then all the chunk items. All
         * device items are found before any chunk item (their object id
         * is smaller than the lowest possible object id for a chunk
@@ -7583,10 +7596,6 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info)
                                goto error;
                        break;
                }
-               /*
-                * The nodes on level 1 are not locked but we don't need to do
-                * that during mount time as nothing else can access the tree
-                */
                node = path->nodes[1];
                if (node) {
                        if (last_ra_node != node->start) {
@@ -7614,7 +7623,6 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info)
                         * requirement for chunk allocation, see the comment on
                         * top of btrfs_chunk_alloc() for details.
                         */
-                       ASSERT(!test_bit(BTRFS_FS_OPEN, &fs_info->flags));
                        chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk);
                        ret = read_one_chunk(&found_key, leaf, chunk);
                        if (ret)
index 12bde7b..23a1ed2 100644 (file)
@@ -393,26 +393,14 @@ static void cifs_put_swn_reg(struct cifs_swn_reg *swnreg)
 
 static int cifs_swn_resource_state_changed(struct cifs_swn_reg *swnreg, const char *name, int state)
 {
-       int i;
-
        switch (state) {
        case CIFS_SWN_RESOURCE_STATE_UNAVAILABLE:
                cifs_dbg(FYI, "%s: resource name '%s' become unavailable\n", __func__, name);
-               for (i = 0; i < swnreg->tcon->ses->chan_count; i++) {
-                       spin_lock(&GlobalMid_Lock);
-                       if (swnreg->tcon->ses->chans[i].server->tcpStatus != CifsExiting)
-                               swnreg->tcon->ses->chans[i].server->tcpStatus = CifsNeedReconnect;
-                       spin_unlock(&GlobalMid_Lock);
-               }
+               cifs_ses_mark_for_reconnect(swnreg->tcon->ses);
                break;
        case CIFS_SWN_RESOURCE_STATE_AVAILABLE:
                cifs_dbg(FYI, "%s: resource name '%s' become available\n", __func__, name);
-               for (i = 0; i < swnreg->tcon->ses->chan_count; i++) {
-                       spin_lock(&GlobalMid_Lock);
-                       if (swnreg->tcon->ses->chans[i].server->tcpStatus != CifsExiting)
-                               swnreg->tcon->ses->chans[i].server->tcpStatus = CifsNeedReconnect;
-                       spin_unlock(&GlobalMid_Lock);
-               }
+               cifs_ses_mark_for_reconnect(swnreg->tcon->ses);
                break;
        case CIFS_SWN_RESOURCE_STATE_UNKNOWN:
                cifs_dbg(FYI, "%s: resource name '%s' changed to unknown state\n", __func__, name);
index f3073a6..4f5a3e8 100644 (file)
@@ -599,6 +599,7 @@ int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
 bool is_server_using_iface(struct TCP_Server_Info *server,
                           struct cifs_server_iface *iface);
 bool is_ses_using_iface(struct cifs_ses *ses, struct cifs_server_iface *iface);
+void cifs_ses_mark_for_reconnect(struct cifs_ses *ses);
 
 void extract_unc_hostname(const char *unc, const char **h, size_t *len);
 int copy_path_name(char *dst, const char *src);
index 82577a7..67e4c55 100644 (file)
@@ -1452,8 +1452,10 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
        tcp_ses->max_in_flight = 0;
        tcp_ses->credits = 1;
        if (primary_server) {
+               spin_lock(&cifs_tcp_ses_lock);
                ++primary_server->srv_count;
                tcp_ses->primary_server = primary_server;
+               spin_unlock(&cifs_tcp_ses_lock);
        }
        init_waitqueue_head(&tcp_ses->response_q);
        init_waitqueue_head(&tcp_ses->request_q);
@@ -4111,18 +4113,6 @@ cifs_prune_tlinks(struct work_struct *work)
 }
 
 #ifdef CONFIG_CIFS_DFS_UPCALL
-static void mark_tcon_tcp_ses_for_reconnect(struct cifs_tcon *tcon)
-{
-       int i;
-
-       for (i = 0; i < tcon->ses->chan_count; i++) {
-               spin_lock(&GlobalMid_Lock);
-               if (tcon->ses->chans[i].server->tcpStatus != CifsExiting)
-                       tcon->ses->chans[i].server->tcpStatus = CifsNeedReconnect;
-               spin_unlock(&GlobalMid_Lock);
-       }
-}
-
 /* Update dfs referral path of superblock */
 static int update_server_fullpath(struct TCP_Server_Info *server, struct cifs_sb_info *cifs_sb,
                                  const char *target)
@@ -4299,7 +4289,7 @@ static int tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *tco
         */
        if (rc && server->current_fullpath != server->origin_fullpath) {
                server->current_fullpath = server->origin_fullpath;
-               mark_tcon_tcp_ses_for_reconnect(tcon);
+               cifs_ses_mark_for_reconnect(tcon->ses);
        }
 
        dfs_cache_free_tgts(tl);
index 5c1259d..e9b0fa2 100644 (file)
@@ -1355,12 +1355,7 @@ static void mark_for_reconnect_if_needed(struct cifs_tcon *tcon, struct dfs_cach
        }
 
        cifs_dbg(FYI, "%s: no cached or matched targets. mark dfs share for reconnect.\n", __func__);
-       for (i = 0; i < tcon->ses->chan_count; i++) {
-               spin_lock(&GlobalMid_Lock);
-               if (tcon->ses->chans[i].server->tcpStatus != CifsExiting)
-                       tcon->ses->chans[i].server->tcpStatus = CifsNeedReconnect;
-               spin_unlock(&GlobalMid_Lock);
-       }
+       cifs_ses_mark_for_reconnect(tcon->ses);
 }
 
 /* Refresh dfs referral of tcon and mark it for reconnect if needed */
index 2c10b18..8ad2993 100644 (file)
@@ -95,9 +95,9 @@ int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
        }
 
        if (!(ses->server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) {
-               cifs_dbg(VFS, "server %s does not support multichannel\n", ses->server->hostname);
                ses->chan_max = 1;
                spin_unlock(&ses->chan_lock);
+               cifs_dbg(VFS, "server %s does not support multichannel\n", ses->server->hostname);
                return 0;
        }
        spin_unlock(&ses->chan_lock);
@@ -318,6 +318,19 @@ out:
        return rc;
 }
 
+/* Mark all session channels for reconnect */
+void cifs_ses_mark_for_reconnect(struct cifs_ses *ses)
+{
+       int i;
+
+       for (i = 0; i < ses->chan_count; i++) {
+               spin_lock(&GlobalMid_Lock);
+               if (ses->chans[i].server->tcpStatus != CifsExiting)
+                       ses->chans[i].server->tcpStatus = CifsNeedReconnect;
+               spin_unlock(&GlobalMid_Lock);
+       }
+}
+
 static __u32 cifs_ssetup_hdr(struct cifs_ses *ses, SESSION_SETUP_ANDX *pSMB)
 {
        __u32 capabilities = 0;
index 7235d53..d671084 100644 (file)
@@ -940,7 +940,7 @@ do_alloc:
                else if (height == ip->i_height)
                        ret = gfs2_hole_size(inode, lblock, len, mp, iomap);
                else
-                       iomap->length = size - pos;
+                       iomap->length = size - iomap->offset;
        } else if (flags & IOMAP_WRITE) {
                u64 alloc_size;
 
index adafaaf..3e718cf 100644 (file)
@@ -773,8 +773,8 @@ static inline bool should_fault_in_pages(ssize_t ret, struct iov_iter *i,
                                         size_t *prev_count,
                                         size_t *window_size)
 {
-       char __user *p = i->iov[0].iov_base + i->iov_offset;
        size_t count = iov_iter_count(i);
+       char __user *p;
        int pages = 1;
 
        if (likely(!count))
@@ -787,14 +787,14 @@ static inline bool should_fault_in_pages(ssize_t ret, struct iov_iter *i,
        if (*prev_count != count || !*window_size) {
                int pages, nr_dirtied;
 
-               pages = min_t(int, BIO_MAX_VECS,
-                             DIV_ROUND_UP(iov_iter_count(i), PAGE_SIZE));
+               pages = min_t(int, BIO_MAX_VECS, DIV_ROUND_UP(count, PAGE_SIZE));
                nr_dirtied = max(current->nr_dirtied_pause -
                                 current->nr_dirtied, 1);
                pages = min(pages, nr_dirtied);
        }
 
        *prev_count = count;
+       p = i->iov[0].iov_base + i->iov_offset;
        *window_size = (size_t)PAGE_SIZE * pages - offset_in_page(p);
        return true;
 }
@@ -1013,6 +1013,7 @@ static ssize_t gfs2_file_buffered_write(struct kiocb *iocb,
        struct gfs2_sbd *sdp = GFS2_SB(inode);
        struct gfs2_holder *statfs_gh = NULL;
        size_t prev_count = 0, window_size = 0;
+       size_t orig_count = iov_iter_count(from);
        size_t read = 0;
        ssize_t ret;
 
@@ -1057,6 +1058,7 @@ retry_under_glock:
        if (inode == sdp->sd_rindex)
                gfs2_glock_dq_uninit(statfs_gh);
 
+       from->count = orig_count - read;
        if (should_fault_in_pages(ret, from, &prev_count, &window_size)) {
                size_t leftover;
 
@@ -1064,6 +1066,7 @@ retry_under_glock:
                leftover = fault_in_iov_iter_readable(from, window_size);
                gfs2_holder_disallow_demote(gh);
                if (leftover != window_size) {
+                       from->count = min(from->count, window_size - leftover);
                        if (!gfs2_holder_queued(gh)) {
                                if (read)
                                        goto out_uninit;
index 19f38ae..8dbd6fe 100644 (file)
@@ -411,14 +411,14 @@ static void do_error(struct gfs2_glock *gl, const int ret)
 static void demote_incompat_holders(struct gfs2_glock *gl,
                                    struct gfs2_holder *new_gh)
 {
-       struct gfs2_holder *gh;
+       struct gfs2_holder *gh, *tmp;
 
        /*
         * Demote incompatible holders before we make ourselves eligible.
         * (This holder may or may not allow auto-demoting, but we don't want
         * to demote the new holder before it's even granted.)
         */
-       list_for_each_entry(gh, &gl->gl_holders, gh_list) {
+       list_for_each_entry_safe(gh, tmp, &gl->gl_holders, gh_list) {
                /*
                 * Since holders are at the front of the list, we stop when we
                 * find the first non-holder.
@@ -496,7 +496,7 @@ again:
         * Since we unlock the lockref lock, we set a flag to indicate
         * instantiate is in progress.
         */
-       if (test_bit(GLF_INSTANTIATE_IN_PROG, &gl->gl_flags)) {
+       if (test_and_set_bit(GLF_INSTANTIATE_IN_PROG, &gl->gl_flags)) {
                wait_on_bit(&gl->gl_flags, GLF_INSTANTIATE_IN_PROG,
                            TASK_UNINTERRUPTIBLE);
                /*
@@ -509,14 +509,10 @@ again:
                goto again;
        }
 
-       set_bit(GLF_INSTANTIATE_IN_PROG, &gl->gl_flags);
-
        ret = glops->go_instantiate(gh);
        if (!ret)
                clear_bit(GLF_INSTANTIATE_NEEDED, &gl->gl_flags);
-       clear_bit(GLF_INSTANTIATE_IN_PROG, &gl->gl_flags);
-       smp_mb__after_atomic();
-       wake_up_bit(&gl->gl_flags, GLF_INSTANTIATE_IN_PROG);
+       clear_and_wake_up_bit(GLF_INSTANTIATE_IN_PROG, &gl->gl_flags);
        return ret;
 }
 
index 5b12137..0f93e8b 100644 (file)
@@ -1402,13 +1402,6 @@ out:
        gfs2_ordered_del_inode(ip);
        clear_inode(inode);
        gfs2_dir_hash_inval(ip);
-       if (ip->i_gl) {
-               glock_clear_object(ip->i_gl, ip);
-               wait_on_bit_io(&ip->i_flags, GIF_GLOP_PENDING, TASK_UNINTERRUPTIBLE);
-               gfs2_glock_add_to_lru(ip->i_gl);
-               gfs2_glock_put_eventually(ip->i_gl);
-               ip->i_gl = NULL;
-       }
        if (gfs2_holder_initialized(&ip->i_iopen_gh)) {
                struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl;
 
@@ -1421,6 +1414,13 @@ out:
                gfs2_holder_uninit(&ip->i_iopen_gh);
                gfs2_glock_put_eventually(gl);
        }
+       if (ip->i_gl) {
+               glock_clear_object(ip->i_gl, ip);
+               wait_on_bit_io(&ip->i_flags, GIF_GLOP_PENDING, TASK_UNINTERRUPTIBLE);
+               gfs2_glock_add_to_lru(ip->i_gl);
+               gfs2_glock_put_eventually(ip->i_gl);
+               ip->i_gl = NULL;
+       }
 }
 
 static struct inode *gfs2_alloc_inode(struct super_block *sb)
index b2a1d96..5a93a5d 100644 (file)
@@ -288,11 +288,8 @@ nfsd4_decode_bitmap4(struct nfsd4_compoundargs *argp, u32 *bmval, u32 bmlen)
        p = xdr_inline_decode(argp->xdr, count << 2);
        if (!p)
                return nfserr_bad_xdr;
-       i = 0;
-       while (i < count)
-               bmval[i++] = be32_to_cpup(p++);
-       while (i < bmlen)
-               bmval[i++] = 0;
+       for (i = 0; i < bmlen; i++)
+               bmval[i] = (i < count) ? be32_to_cpup(p++) : 0;
 
        return nfs_ok;
 }
index 70abdfa..42e3e55 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/bio.h>
+#include <linux/iversion.h>
 
 #include "udf_i.h"
 #include "udf_sb.h"
@@ -43,7 +44,7 @@ static int udf_readdir(struct file *file, struct dir_context *ctx)
        struct fileIdentDesc *fi = NULL;
        struct fileIdentDesc cfi;
        udf_pblk_t block, iblock;
-       loff_t nf_pos;
+       loff_t nf_pos, emit_pos = 0;
        int flen;
        unsigned char *fname = NULL, *copy_name = NULL;
        unsigned char *nameptr;
@@ -57,6 +58,7 @@ static int udf_readdir(struct file *file, struct dir_context *ctx)
        int i, num, ret = 0;
        struct extent_position epos = { NULL, 0, {0, 0} };
        struct super_block *sb = dir->i_sb;
+       bool pos_valid = false;
 
        if (ctx->pos == 0) {
                if (!dir_emit_dot(file, ctx))
@@ -67,6 +69,21 @@ static int udf_readdir(struct file *file, struct dir_context *ctx)
        if (nf_pos >= size)
                goto out;
 
+       /*
+        * Something changed since last readdir (either lseek was called or dir
+        * changed)?  We need to verify the position correctly points at the
+        * beginning of some dir entry so that the directory parsing code does
+        * not get confused. Since UDF does not have any reliable way of
+        * identifying beginning of dir entry (names are under user control),
+        * we need to scan the directory from the beginning.
+        */
+       if (!inode_eq_iversion(dir, file->f_version)) {
+               emit_pos = nf_pos;
+               nf_pos = 0;
+       } else {
+               pos_valid = true;
+       }
+
        fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
        if (!fname) {
                ret = -ENOMEM;
@@ -122,13 +139,21 @@ static int udf_readdir(struct file *file, struct dir_context *ctx)
 
        while (nf_pos < size) {
                struct kernel_lb_addr tloc;
+               loff_t cur_pos = nf_pos;
 
-               ctx->pos = (nf_pos >> 2) + 1;
+               /* Update file position only if we got past the current one */
+               if (nf_pos >= emit_pos) {
+                       ctx->pos = (nf_pos >> 2) + 1;
+                       pos_valid = true;
+               }
 
                fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc,
                                        &elen, &offset);
                if (!fi)
                        goto out;
+               /* Still not at offset where user asked us to read from? */
+               if (cur_pos < emit_pos)
+                       continue;
 
                liu = le16_to_cpu(cfi.lengthOfImpUse);
                lfi = cfi.lengthFileIdent;
@@ -186,8 +211,11 @@ static int udf_readdir(struct file *file, struct dir_context *ctx)
        } /* end while */
 
        ctx->pos = (nf_pos >> 2) + 1;
+       pos_valid = true;
 
 out:
+       if (pos_valid)
+               file->f_version = inode_query_iversion(dir);
        if (fibh.sbh != fibh.ebh)
                brelse(fibh.ebh);
        brelse(fibh.sbh);
index caeef08..0ed4861 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/sched.h>
 #include <linux/crc-itu-t.h>
 #include <linux/exportfs.h>
+#include <linux/iversion.h>
 
 static inline int udf_match(int len1, const unsigned char *name1, int len2,
                            const unsigned char *name2)
@@ -134,6 +135,8 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
                        mark_buffer_dirty_inode(fibh->ebh, inode);
                mark_buffer_dirty_inode(fibh->sbh, inode);
        }
+       inode_inc_iversion(inode);
+
        return 0;
 }
 
index 34247fb..f26b5e0 100644 (file)
@@ -57,6 +57,7 @@
 #include <linux/crc-itu-t.h>
 #include <linux/log2.h>
 #include <asm/byteorder.h>
+#include <linux/iversion.h>
 
 #include "udf_sb.h"
 #include "udf_i.h"
@@ -149,6 +150,7 @@ static struct inode *udf_alloc_inode(struct super_block *sb)
        init_rwsem(&ei->i_data_sem);
        ei->cached_extent.lstart = -1;
        spin_lock_init(&ei->i_extent_cache_lock);
+       inode_set_iversion(&ei->vfs_inode, 1);
 
        return &ei->vfs_inode;
 }
index 143ce7e..668d007 100644 (file)
@@ -974,6 +974,15 @@ static inline int acpi_get_local_address(acpi_handle handle, u32 *addr)
        return -ENODEV;
 }
 
+static inline int acpi_register_wakeup_handler(int wake_irq,
+       bool (*wakeup)(void *context), void *context)
+{
+       return -ENXIO;
+}
+
+static inline void acpi_unregister_wakeup_handler(
+       bool (*wakeup)(void *context), void *context) { }
+
 #endif /* !CONFIG_ACPI */
 
 #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
index f715e88..e7a163a 100644 (file)
@@ -193,7 +193,7 @@ struct bpf_map {
        atomic64_t usercnt;
        struct work_struct work;
        struct mutex freeze_mutex;
-       u64 writecnt; /* writable mmap cnt; protected by freeze_mutex */
+       atomic64_t writecnt;
 };
 
 static inline bool map_value_has_spin_lock(const struct bpf_map *map)
@@ -1419,6 +1419,7 @@ void bpf_map_put(struct bpf_map *map);
 void *bpf_map_area_alloc(u64 size, int numa_node);
 void *bpf_map_area_mmapable_alloc(u64 size, int numa_node);
 void bpf_map_area_free(void *base);
+bool bpf_map_write_active(const struct bpf_map *map);
 void bpf_map_init_from_attr(struct bpf_map *map, union bpf_attr *attr);
 int  generic_map_lookup_batch(struct bpf_map *map,
                              const union bpf_attr *attr,
index 9e0667e..c310648 100644 (file)
@@ -874,7 +874,7 @@ void kvm_release_pfn_dirty(kvm_pfn_t pfn);
 void kvm_set_pfn_dirty(kvm_pfn_t pfn);
 void kvm_set_pfn_accessed(kvm_pfn_t pfn);
 
-void kvm_release_pfn(kvm_pfn_t pfn, bool dirty, struct gfn_to_pfn_cache *cache);
+void kvm_release_pfn(kvm_pfn_t pfn, bool dirty);
 int kvm_read_guest_page(struct kvm *kvm, gfn_t gfn, void *data, int offset,
                        int len);
 int kvm_read_guest(struct kvm *kvm, gpa_t gpa, void *data, unsigned long len);
@@ -950,12 +950,8 @@ struct kvm_memory_slot *kvm_vcpu_gfn_to_memslot(struct kvm_vcpu *vcpu, gfn_t gfn
 kvm_pfn_t kvm_vcpu_gfn_to_pfn_atomic(struct kvm_vcpu *vcpu, gfn_t gfn);
 kvm_pfn_t kvm_vcpu_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn);
 int kvm_vcpu_map(struct kvm_vcpu *vcpu, gpa_t gpa, struct kvm_host_map *map);
-int kvm_map_gfn(struct kvm_vcpu *vcpu, gfn_t gfn, struct kvm_host_map *map,
-               struct gfn_to_pfn_cache *cache, bool atomic);
 struct page *kvm_vcpu_gfn_to_page(struct kvm_vcpu *vcpu, gfn_t gfn);
 void kvm_vcpu_unmap(struct kvm_vcpu *vcpu, struct kvm_host_map *map, bool dirty);
-int kvm_unmap_gfn(struct kvm_vcpu *vcpu, struct kvm_host_map *map,
-                 struct gfn_to_pfn_cache *cache, bool dirty, bool atomic);
 unsigned long kvm_vcpu_gfn_to_hva(struct kvm_vcpu *vcpu, gfn_t gfn);
 unsigned long kvm_vcpu_gfn_to_hva_prot(struct kvm_vcpu *vcpu, gfn_t gfn, bool *writable);
 int kvm_vcpu_read_guest_page(struct kvm_vcpu *vcpu, gfn_t gfn, void *data, int offset,
index 2237abb..234eab0 100644 (file)
@@ -53,13 +53,6 @@ struct gfn_to_hva_cache {
        struct kvm_memory_slot *memslot;
 };
 
-struct gfn_to_pfn_cache {
-       u64 generation;
-       gfn_t gfn;
-       kvm_pfn_t pfn;
-       bool dirty;
-};
-
 #ifdef KVM_ARCH_NR_OBJS_PER_MEMORY_CACHE
 /*
  * Memory caches are used to preallocate memory ahead of various MMU flows,
index 97afcea..8b18fe9 100644 (file)
@@ -145,13 +145,13 @@ u32 mlx5_eswitch_get_vport_metadata_for_set(struct mlx5_eswitch *esw,
        GENMASK(31 - ESW_TUN_ID_BITS - ESW_RESERVED_BITS, \
                ESW_TUN_OPTS_OFFSET + 1)
 
-u8 mlx5_eswitch_mode(struct mlx5_core_dev *dev);
+u8 mlx5_eswitch_mode(const struct mlx5_core_dev *dev);
 u16 mlx5_eswitch_get_total_vports(const struct mlx5_core_dev *dev);
 struct mlx5_core_dev *mlx5_eswitch_get_core_dev(struct mlx5_eswitch *esw);
 
 #else  /* CONFIG_MLX5_ESWITCH */
 
-static inline u8 mlx5_eswitch_mode(struct mlx5_core_dev *dev)
+static inline u8 mlx5_eswitch_mode(const struct mlx5_core_dev *dev)
 {
        return MLX5_ESWITCH_NONE;
 }
index bb8c6f5..c3a6e62 100644 (file)
@@ -105,7 +105,18 @@ struct page {
                        struct page_pool *pp;
                        unsigned long _pp_mapping_pad;
                        unsigned long dma_addr;
-                       atomic_long_t pp_frag_count;
+                       union {
+                               /**
+                                * dma_addr_upper: might require a 64-bit
+                                * value on 32-bit architectures.
+                                */
+                               unsigned long dma_addr_upper;
+                               /**
+                                * For frag page support, not supported in
+                                * 32-bit architectures with 64-bit DMA.
+                                */
+                               atomic_long_t pp_frag_count;
+                       };
                };
                struct {        /* slab, slob and slub */
                        union {
index 98a9371..ae4004e 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/preempt.h>
 #include <linux/smp.h>
 #include <linux/cpumask.h>
-#include <linux/printk.h>
 #include <linux/pfn.h>
 #include <linux/init.h>
 
index 85b656f..9497f6b 100644 (file)
@@ -198,6 +198,7 @@ void dump_stack_print_info(const char *log_lvl);
 void show_regs_print_info(const char *log_lvl);
 extern asmlinkage void dump_stack_lvl(const char *log_lvl) __cold;
 extern asmlinkage void dump_stack(void) __cold;
+void printk_trigger_flush(void);
 #else
 static inline __printf(1, 0)
 int vprintk(const char *s, va_list args)
@@ -274,6 +275,9 @@ static inline void dump_stack_lvl(const char *log_lvl)
 static inline void dump_stack(void)
 {
 }
+static inline void printk_trigger_flush(void)
+{
+}
 #endif
 
 #ifdef CONFIG_SMP
index 2350539..33a5064 100644 (file)
@@ -352,6 +352,7 @@ extern __must_check bool do_notify_parent(struct task_struct *, int);
 extern void __wake_up_parent(struct task_struct *p, struct task_struct *parent);
 extern void force_sig(int);
 extern void force_fatal_sig(int);
+extern void force_exit_sig(int);
 extern int send_sig(int, struct task_struct *, int);
 extern int zap_other_threads(struct task_struct *p);
 extern struct sigqueue *sigqueue_alloc(void);
diff --git a/include/linux/sdb.h b/include/linux/sdb.h
deleted file mode 100644 (file)
index a2404a2..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * This is the official version 1.1 of sdb.h
- */
-#ifndef __SDB_H__
-#define __SDB_H__
-#ifdef __KERNEL__
-#include <linux/types.h>
-#else
-#include <stdint.h>
-#endif
-
-/*
- * All structures are 64 bytes long and are expected
- * to live in an array, one for each interconnect.
- * Most fields of the structures are shared among the
- * various types, and most-specific fields are at the
- * beginning (for alignment reasons, and to keep the
- * magic number at the head of the interconnect record
- */
-
-/* Product, 40 bytes at offset 24, 8-byte aligned
- *
- * device_id is vendor-assigned; version is device-specific,
- * date is hex (e.g 0x20120501), name is UTF-8, blank-filled
- * and not terminated with a 0 byte.
- */
-struct sdb_product {
-       uint64_t                vendor_id;      /* 0x18..0x1f */
-       uint32_t                device_id;      /* 0x20..0x23 */
-       uint32_t                version;        /* 0x24..0x27 */
-       uint32_t                date;           /* 0x28..0x2b */
-       uint8_t                 name[19];       /* 0x2c..0x3e */
-       uint8_t                 record_type;    /* 0x3f */
-};
-
-/*
- * Component, 56 bytes at offset 8, 8-byte aligned
- *
- * The address range is first to last, inclusive
- * (for example 0x100000 - 0x10ffff)
- */
-struct sdb_component {
-       uint64_t                addr_first;     /* 0x08..0x0f */
-       uint64_t                addr_last;      /* 0x10..0x17 */
-       struct sdb_product      product;        /* 0x18..0x3f */
-};
-
-/* Type of the SDB record */
-enum sdb_record_type {
-       sdb_type_interconnect   = 0x00,
-       sdb_type_device         = 0x01,
-       sdb_type_bridge         = 0x02,
-       sdb_type_integration    = 0x80,
-       sdb_type_repo_url       = 0x81,
-       sdb_type_synthesis      = 0x82,
-       sdb_type_empty          = 0xFF,
-};
-
-/* Type 0: interconnect (first of the array)
- *
- * sdb_records is the length of the table including this first
- * record, version is 1. The bus type is enumerated later.
- */
-#define                                SDB_MAGIC       0x5344422d /* "SDB-" */
-struct sdb_interconnect {
-       uint32_t                sdb_magic;      /* 0x00-0x03 */
-       uint16_t                sdb_records;    /* 0x04-0x05 */
-       uint8_t                 sdb_version;    /* 0x06 */
-       uint8_t                 sdb_bus_type;   /* 0x07 */
-       struct sdb_component    sdb_component;  /* 0x08-0x3f */
-};
-
-/* Type 1: device
- *
- * class is 0 for "custom device", other values are
- * to be standardized; ABI version is for the driver,
- * bus-specific bits are defined by each bus (see below)
- */
-struct sdb_device {
-       uint16_t                abi_class;      /* 0x00-0x01 */
-       uint8_t                 abi_ver_major;  /* 0x02 */
-       uint8_t                 abi_ver_minor;  /* 0x03 */
-       uint32_t                bus_specific;   /* 0x04-0x07 */
-       struct sdb_component    sdb_component;  /* 0x08-0x3f */
-};
-
-/* Type 2: bridge
- *
- * child is the address of the nested SDB table
- */
-struct sdb_bridge {
-       uint64_t                sdb_child;      /* 0x00-0x07 */
-       struct sdb_component    sdb_component;  /* 0x08-0x3f */
-};
-
-/* Type 0x80: integration
- *
- * all types with bit 7 set are meta-information, so
- * software can ignore the types it doesn't know. Here we
- * just provide product information for an aggregate device
- */
-struct sdb_integration {
-       uint8_t                 reserved[24];   /* 0x00-0x17 */
-       struct sdb_product      product;        /* 0x08-0x3f */
-};
-
-/* Type 0x81: Top module repository url
- *
- * again, an informative field that software can ignore
- */
-struct sdb_repo_url {
-       uint8_t                 repo_url[63];   /* 0x00-0x3e */
-       uint8_t                 record_type;    /* 0x3f */
-};
-
-/* Type 0x82: Synthesis tool information
- *
- * this informative record
- */
-struct sdb_synthesis {
-       uint8_t                 syn_name[16];   /* 0x00-0x0f */
-       uint8_t                 commit_id[16];  /* 0x10-0x1f */
-       uint8_t                 tool_name[8];   /* 0x20-0x27 */
-       uint32_t                tool_version;   /* 0x28-0x2b */
-       uint32_t                date;           /* 0x2c-0x2f */
-       uint8_t                 user_name[15];  /* 0x30-0x3e */
-       uint8_t                 record_type;    /* 0x3f */
-};
-
-/* Type 0xff: empty
- *
- * this allows keeping empty slots during development,
- * so they can be filled later with minimal efforts and
- * no misleading description is ever shipped -- hopefully.
- * It can also be used to pad a table to a desired length.
- */
-struct sdb_empty {
-       uint8_t                 reserved[63];   /* 0x00-0x3e */
-       uint8_t                 record_type;    /* 0x3f */
-};
-
-/* The type of bus, for bus-specific flags */
-enum sdb_bus_type {
-       sdb_wishbone = 0x00,
-       sdb_data     = 0x01,
-};
-
-#define SDB_WB_WIDTH_MASK      0x0f
-#define SDB_WB_ACCESS8                 0x01
-#define SDB_WB_ACCESS16                        0x02
-#define SDB_WB_ACCESS32                        0x04
-#define SDB_WB_ACCESS64                        0x08
-#define SDB_WB_LITTLE_ENDIAN   0x80
-
-#define SDB_DATA_READ          0x04
-#define SDB_DATA_WRITE         0x02
-#define SDB_DATA_EXEC          0x01
-
-#endif /* __SDB_H__ */
index 686a666..c8cb7e6 100644 (file)
@@ -4226,7 +4226,7 @@ static inline void skb_remcsum_process(struct sk_buff *skb, void *ptr,
                return;
        }
 
-        if (unlikely(skb->ip_summed != CHECKSUM_COMPLETE)) {
+       if (unlikely(skb->ip_summed != CHECKSUM_COMPLETE)) {
                __skb_checksum_complete(skb);
                skb_postpull_rcsum(skb, skb->data, ptr - (void *)skb->data);
        }
index 50453b2..2d167ac 100644 (file)
@@ -673,7 +673,7 @@ struct trace_event_file {
 
 #define PERF_MAX_TRACE_SIZE    8192
 
-#define MAX_FILTER_STR_VAL     256     /* Should handle KSYM_SYMBOL_LEN */
+#define MAX_FILTER_STR_VAL     256U    /* Should handle KSYM_SYMBOL_LEN */
 
 enum event_trigger_type {
        ETT_NONE                = (0),
index b465f8f..04e87f4 100644 (file)
@@ -120,10 +120,15 @@ retry:
 
        if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) {
                u16 gso_size = __virtio16_to_cpu(little_endian, hdr->gso_size);
+               unsigned int nh_off = p_off;
                struct skb_shared_info *shinfo = skb_shinfo(skb);
 
+               /* UFO may not include transport header in gso_size. */
+               if (gso_type & SKB_GSO_UDP)
+                       nh_off -= thlen;
+
                /* Too small packets are not really GSO ones. */
-               if (skb->len - p_off > gso_size) {
+               if (skb->len - nh_off > gso_size) {
                        shinfo->gso_size = gso_size;
                        shinfo->gso_type = gso_type;
 
index a964dae..ea85956 100644 (file)
@@ -30,6 +30,7 @@ enum nci_flag {
        NCI_UP,
        NCI_DATA_EXCHANGE,
        NCI_DATA_EXCHANGE_TO,
+       NCI_UNREG,
 };
 
 /* NCI device states */
index 3855f06..a408240 100644 (file)
@@ -216,14 +216,24 @@ static inline void page_pool_recycle_direct(struct page_pool *pool,
        page_pool_put_full_page(pool, page, true);
 }
 
+#define PAGE_POOL_DMA_USE_PP_FRAG_COUNT        \
+               (sizeof(dma_addr_t) > sizeof(unsigned long))
+
 static inline dma_addr_t page_pool_get_dma_addr(struct page *page)
 {
-       return page->dma_addr;
+       dma_addr_t ret = page->dma_addr;
+
+       if (PAGE_POOL_DMA_USE_PP_FRAG_COUNT)
+               ret |= (dma_addr_t)page->dma_addr_upper << 16 << 16;
+
+       return ret;
 }
 
 static inline void page_pool_set_dma_addr(struct page *page, dma_addr_t addr)
 {
        page->dma_addr = addr;
+       if (PAGE_POOL_DMA_USE_PP_FRAG_COUNT)
+               page->dma_addr_upper = upper_32_bits(addr);
 }
 
 static inline void page_pool_set_frag_count(struct page *page, long nr)
index 2758d9d..c2a79ae 100644 (file)
@@ -30,7 +30,7 @@ enum rdma_nl_flags {
  * constant as well and the compiler checks they are the same.
  */
 #define MODULE_ALIAS_RDMA_NETLINK(_index, _val)                                \
-       static inline void __chk_##_index(void)                                \
+       static inline void __maybe_unused __chk_##_index(void)                 \
        {                                                                      \
                BUILD_BUG_ON(_index != _val);                                  \
        }                                                                      \
index 036b750..4b7bac1 100644 (file)
@@ -887,7 +887,7 @@ config CC_HAS_INT128
 
 config CC_IMPLICIT_FALLTHROUGH
        string
-       default "-Wimplicit-fallthrough=5" if CC_IS_GCC
+       default "-Wimplicit-fallthrough=5" if CC_IS_GCC && $(cc-option,-Wimplicit-fallthrough=5)
        default "-Wimplicit-fallthrough" if CC_IS_CLANG && $(cc-option,-Wunreachable-code-fallthrough)
 
 #
index 2ca643a..43eb350 100644 (file)
@@ -1809,6 +1809,8 @@ sysctl_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
                return &bpf_sysctl_get_new_value_proto;
        case BPF_FUNC_sysctl_set_new_value:
                return &bpf_sysctl_set_new_value_proto;
+       case BPF_FUNC_ktime_get_coarse_ns:
+               return &bpf_ktime_get_coarse_ns_proto;
        default:
                return cgroup_base_func_proto(func_id, prog);
        }
index 1ffd469..649f076 100644 (file)
@@ -1364,8 +1364,6 @@ bpf_base_func_proto(enum bpf_func_id func_id)
                return &bpf_ktime_get_ns_proto;
        case BPF_FUNC_ktime_get_boot_ns:
                return &bpf_ktime_get_boot_ns_proto;
-       case BPF_FUNC_ktime_get_coarse_ns:
-               return &bpf_ktime_get_coarse_ns_proto;
        case BPF_FUNC_ringbuf_output:
                return &bpf_ringbuf_output_proto;
        case BPF_FUNC_ringbuf_reserve:
index 50f96ea..1033ee8 100644 (file)
@@ -132,6 +132,21 @@ static struct bpf_map *find_and_alloc_map(union bpf_attr *attr)
        return map;
 }
 
+static void bpf_map_write_active_inc(struct bpf_map *map)
+{
+       atomic64_inc(&map->writecnt);
+}
+
+static void bpf_map_write_active_dec(struct bpf_map *map)
+{
+       atomic64_dec(&map->writecnt);
+}
+
+bool bpf_map_write_active(const struct bpf_map *map)
+{
+       return atomic64_read(&map->writecnt) != 0;
+}
+
 static u32 bpf_map_value_size(const struct bpf_map *map)
 {
        if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
@@ -601,11 +616,8 @@ static void bpf_map_mmap_open(struct vm_area_struct *vma)
 {
        struct bpf_map *map = vma->vm_file->private_data;
 
-       if (vma->vm_flags & VM_MAYWRITE) {
-               mutex_lock(&map->freeze_mutex);
-               map->writecnt++;
-               mutex_unlock(&map->freeze_mutex);
-       }
+       if (vma->vm_flags & VM_MAYWRITE)
+               bpf_map_write_active_inc(map);
 }
 
 /* called for all unmapped memory region (including initial) */
@@ -613,11 +625,8 @@ static void bpf_map_mmap_close(struct vm_area_struct *vma)
 {
        struct bpf_map *map = vma->vm_file->private_data;
 
-       if (vma->vm_flags & VM_MAYWRITE) {
-               mutex_lock(&map->freeze_mutex);
-               map->writecnt--;
-               mutex_unlock(&map->freeze_mutex);
-       }
+       if (vma->vm_flags & VM_MAYWRITE)
+               bpf_map_write_active_dec(map);
 }
 
 static const struct vm_operations_struct bpf_map_default_vmops = {
@@ -668,7 +677,7 @@ static int bpf_map_mmap(struct file *filp, struct vm_area_struct *vma)
                goto out;
 
        if (vma->vm_flags & VM_MAYWRITE)
-               map->writecnt++;
+               bpf_map_write_active_inc(map);
 out:
        mutex_unlock(&map->freeze_mutex);
        return err;
@@ -1139,6 +1148,7 @@ static int map_update_elem(union bpf_attr *attr, bpfptr_t uattr)
        map = __bpf_map_get(f);
        if (IS_ERR(map))
                return PTR_ERR(map);
+       bpf_map_write_active_inc(map);
        if (!(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) {
                err = -EPERM;
                goto err_put;
@@ -1174,6 +1184,7 @@ free_value:
 free_key:
        kvfree(key);
 err_put:
+       bpf_map_write_active_dec(map);
        fdput(f);
        return err;
 }
@@ -1196,6 +1207,7 @@ static int map_delete_elem(union bpf_attr *attr)
        map = __bpf_map_get(f);
        if (IS_ERR(map))
                return PTR_ERR(map);
+       bpf_map_write_active_inc(map);
        if (!(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) {
                err = -EPERM;
                goto err_put;
@@ -1226,6 +1238,7 @@ static int map_delete_elem(union bpf_attr *attr)
 out:
        kvfree(key);
 err_put:
+       bpf_map_write_active_dec(map);
        fdput(f);
        return err;
 }
@@ -1533,6 +1546,7 @@ static int map_lookup_and_delete_elem(union bpf_attr *attr)
        map = __bpf_map_get(f);
        if (IS_ERR(map))
                return PTR_ERR(map);
+       bpf_map_write_active_inc(map);
        if (!(map_get_sys_perms(map, f) & FMODE_CAN_READ) ||
            !(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) {
                err = -EPERM;
@@ -1597,6 +1611,7 @@ free_value:
 free_key:
        kvfree(key);
 err_put:
+       bpf_map_write_active_dec(map);
        fdput(f);
        return err;
 }
@@ -1624,8 +1639,7 @@ static int map_freeze(const union bpf_attr *attr)
        }
 
        mutex_lock(&map->freeze_mutex);
-
-       if (map->writecnt) {
+       if (bpf_map_write_active(map)) {
                err = -EBUSY;
                goto err_put;
        }
@@ -4171,6 +4185,9 @@ static int bpf_map_do_batch(const union bpf_attr *attr,
                            union bpf_attr __user *uattr,
                            int cmd)
 {
+       bool has_read  = cmd == BPF_MAP_LOOKUP_BATCH ||
+                        cmd == BPF_MAP_LOOKUP_AND_DELETE_BATCH;
+       bool has_write = cmd != BPF_MAP_LOOKUP_BATCH;
        struct bpf_map *map;
        int err, ufd;
        struct fd f;
@@ -4183,16 +4200,13 @@ static int bpf_map_do_batch(const union bpf_attr *attr,
        map = __bpf_map_get(f);
        if (IS_ERR(map))
                return PTR_ERR(map);
-
-       if ((cmd == BPF_MAP_LOOKUP_BATCH ||
-            cmd == BPF_MAP_LOOKUP_AND_DELETE_BATCH) &&
-           !(map_get_sys_perms(map, f) & FMODE_CAN_READ)) {
+       if (has_write)
+               bpf_map_write_active_inc(map);
+       if (has_read && !(map_get_sys_perms(map, f) & FMODE_CAN_READ)) {
                err = -EPERM;
                goto err_put;
        }
-
-       if (cmd != BPF_MAP_LOOKUP_BATCH &&
-           !(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) {
+       if (has_write && !(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) {
                err = -EPERM;
                goto err_put;
        }
@@ -4205,8 +4219,9 @@ static int bpf_map_do_batch(const union bpf_attr *attr,
                BPF_DO_BATCH(map->ops->map_update_batch);
        else
                BPF_DO_BATCH(map->ops->map_delete_batch);
-
 err_put:
+       if (has_write)
+               bpf_map_write_active_dec(map);
        fdput(f);
        return err;
 }
index 890b3ec..50efda5 100644 (file)
@@ -1151,7 +1151,8 @@ static void mark_ptr_not_null_reg(struct bpf_reg_state *reg)
                        /* transfer reg's id which is unique for every map_lookup_elem
                         * as UID of the inner map.
                         */
-                       reg->map_uid = reg->id;
+                       if (map_value_has_timer(map->inner_map_meta))
+                               reg->map_uid = reg->id;
                } else if (map->map_type == BPF_MAP_TYPE_XSKMAP) {
                        reg->type = PTR_TO_XDP_SOCK;
                } else if (map->map_type == BPF_MAP_TYPE_SOCKMAP ||
@@ -4055,7 +4056,22 @@ static void coerce_reg_to_size(struct bpf_reg_state *reg, int size)
 
 static bool bpf_map_is_rdonly(const struct bpf_map *map)
 {
-       return (map->map_flags & BPF_F_RDONLY_PROG) && map->frozen;
+       /* A map is considered read-only if the following condition are true:
+        *
+        * 1) BPF program side cannot change any of the map content. The
+        *    BPF_F_RDONLY_PROG flag is throughout the lifetime of a map
+        *    and was set at map creation time.
+        * 2) The map value(s) have been initialized from user space by a
+        *    loader and then "frozen", such that no new map update/delete
+        *    operations from syscall side are possible for the rest of
+        *    the map's lifetime from that point onwards.
+        * 3) Any parallel/pending map update/delete operations from syscall
+        *    side have been completed. Only after that point, it's safe to
+        *    assume that map value(s) are immutable.
+        */
+       return (map->map_flags & BPF_F_RDONLY_PROG) &&
+              READ_ONCE(map->frozen) &&
+              !bpf_map_write_active(map);
 }
 
 static int bpf_map_direct_read(struct bpf_map *map, int off, int size, u64 *val)
@@ -11631,6 +11647,13 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
                }
        }
 
+       if (map_value_has_timer(map)) {
+               if (is_tracing_prog_type(prog_type)) {
+                       verbose(env, "tracing progs cannot use bpf_timer yet\n");
+                       return -EINVAL;
+               }
+       }
+
        if ((bpf_prog_is_dev_bound(prog->aux) || bpf_map_is_dev_bound(map)) &&
            !bpf_offload_prog_map_match(prog, map)) {
                verbose(env, "offload device mismatch between prog and map\n");
index 4508201..0b6379a 100644 (file)
@@ -48,7 +48,7 @@ bool syscall_user_dispatch(struct pt_regs *regs)
                 * the selector is loaded by userspace.
                 */
                if (unlikely(__get_user(state, sd->selector))) {
-                       force_fatal_sig(SIGSEGV);
+                       force_exit_sig(SIGSEGV);
                        return true;
                }
 
@@ -56,7 +56,7 @@ bool syscall_user_dispatch(struct pt_regs *regs)
                        return false;
 
                if (state != SYSCALL_DISPATCH_FILTER_BLOCK) {
-                       force_fatal_sig(SIGSYS);
+                       force_exit_sig(SIGSYS);
                        return true;
                }
        }
index 013bfd6..57b132b 100644 (file)
@@ -3253,6 +3253,11 @@ void defer_console_output(void)
        preempt_enable();
 }
 
+void printk_trigger_flush(void)
+{
+       defer_console_output();
+}
+
 int vprintk_deferred(const char *fmt, va_list args)
 {
        int r;
index 7c4b7ae..a629b11 100644 (file)
@@ -1298,6 +1298,12 @@ int do_send_sig_info(int sig, struct kernel_siginfo *info, struct task_struct *p
        return ret;
 }
 
+enum sig_handler {
+       HANDLER_CURRENT, /* If reachable use the current handler */
+       HANDLER_SIG_DFL, /* Always use SIG_DFL handler semantics */
+       HANDLER_EXIT,    /* Only visible as the process exit code */
+};
+
 /*
  * Force a signal that the process can't ignore: if necessary
  * we unblock the signal and change any SIG_IGN to SIG_DFL.
@@ -1310,7 +1316,8 @@ int do_send_sig_info(int sig, struct kernel_siginfo *info, struct task_struct *p
  * that is why we also clear SIGNAL_UNKILLABLE.
  */
 static int
-force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t, bool sigdfl)
+force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t,
+       enum sig_handler handler)
 {
        unsigned long int flags;
        int ret, blocked, ignored;
@@ -1321,9 +1328,10 @@ force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t, bool
        action = &t->sighand->action[sig-1];
        ignored = action->sa.sa_handler == SIG_IGN;
        blocked = sigismember(&t->blocked, sig);
-       if (blocked || ignored || sigdfl) {
+       if (blocked || ignored || (handler != HANDLER_CURRENT)) {
                action->sa.sa_handler = SIG_DFL;
-               action->sa.sa_flags |= SA_IMMUTABLE;
+               if (handler == HANDLER_EXIT)
+                       action->sa.sa_flags |= SA_IMMUTABLE;
                if (blocked) {
                        sigdelset(&t->blocked, sig);
                        recalc_sigpending_and_wake(t);
@@ -1343,7 +1351,7 @@ force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t, bool
 
 int force_sig_info(struct kernel_siginfo *info)
 {
-       return force_sig_info_to_task(info, current, false);
+       return force_sig_info_to_task(info, current, HANDLER_CURRENT);
 }
 
 /*
@@ -1660,7 +1668,20 @@ void force_fatal_sig(int sig)
        info.si_code = SI_KERNEL;
        info.si_pid = 0;
        info.si_uid = 0;
-       force_sig_info_to_task(&info, current, true);
+       force_sig_info_to_task(&info, current, HANDLER_SIG_DFL);
+}
+
+void force_exit_sig(int sig)
+{
+       struct kernel_siginfo info;
+
+       clear_siginfo(&info);
+       info.si_signo = sig;
+       info.si_errno = 0;
+       info.si_code = SI_KERNEL;
+       info.si_pid = 0;
+       info.si_uid = 0;
+       force_sig_info_to_task(&info, current, HANDLER_EXIT);
 }
 
 /*
@@ -1693,7 +1714,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
        info.si_flags = flags;
        info.si_isr = isr;
 #endif
-       return force_sig_info_to_task(&info, t, false);
+       return force_sig_info_to_task(&info, t, HANDLER_CURRENT);
 }
 
 int force_sig_fault(int sig, int code, void __user *addr
@@ -1813,7 +1834,8 @@ int force_sig_seccomp(int syscall, int reason, bool force_coredump)
        info.si_errno = reason;
        info.si_arch = syscall_get_arch(current);
        info.si_syscall = syscall;
-       return force_sig_info_to_task(&info, current, force_coredump);
+       return force_sig_info_to_task(&info, current,
+               force_coredump ? HANDLER_EXIT : HANDLER_CURRENT);
 }
 
 /* For the crazy architectures that include trap information in
index 7396488..ae97550 100644 (file)
@@ -1111,8 +1111,6 @@ bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
                return &bpf_ktime_get_ns_proto;
        case BPF_FUNC_ktime_get_boot_ns:
                return &bpf_ktime_get_boot_ns_proto;
-       case BPF_FUNC_ktime_get_coarse_ns:
-               return &bpf_ktime_get_coarse_ns_proto;
        case BPF_FUNC_tail_call:
                return &bpf_tail_call_proto;
        case BPF_FUNC_get_current_pid_tgid:
index f9139dc..88de94d 100644 (file)
@@ -3812,6 +3812,18 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt,
                iter->fmt[i] = '\0';
                trace_seq_vprintf(&iter->seq, iter->fmt, ap);
 
+               /*
+                * If iter->seq is full, the above call no longer guarantees
+                * that ap is in sync with fmt processing, and further calls
+                * to va_arg() can return wrong positional arguments.
+                *
+                * Ensure that ap is no longer used in this case.
+                */
+               if (iter->seq.full) {
+                       p = "";
+                       break;
+               }
+
                if (star)
                        len = va_arg(ap, int);
 
@@ -6706,9 +6718,7 @@ waitagain:
                cnt = PAGE_SIZE - 1;
 
        /* reset all but tr, trace, and overruns */
-       memset(&iter->seq, 0,
-              sizeof(struct trace_iterator) -
-              offsetof(struct trace_iterator, seq));
+       memset_startat(iter, 0, seq);
        cpumask_clear(iter->started);
        trace_seq_init(&iter->seq);
        iter->pos = -1;
index 8a10046..9555b8e 100644 (file)
@@ -2576,28 +2576,27 @@ static struct hist_field *parse_expr(struct hist_trigger_data *hist_data,
 
        /* Split the expression string at the root operator */
        if (!sep)
-               goto free;
+               return ERR_PTR(-EINVAL);
+
        *sep = '\0';
        operand1_str = str;
        str = sep+1;
 
        /* Binary operator requires both operands */
        if (*operand1_str == '\0' || *str == '\0')
-               goto free;
+               return ERR_PTR(-EINVAL);
 
        operand_flags = 0;
 
        /* LHS of string is an expression e.g. a+b in a+b+c */
        operand1 = parse_expr(hist_data, file, operand1_str, operand_flags, NULL, n_subexprs);
-       if (IS_ERR(operand1)) {
-               ret = PTR_ERR(operand1);
-               operand1 = NULL;
-               goto free;
-       }
+       if (IS_ERR(operand1))
+               return ERR_CAST(operand1);
+
        if (operand1->flags & HIST_FIELD_FL_STRING) {
                hist_err(file->tr, HIST_ERR_INVALID_STR_OPERAND, errpos(operand1_str));
                ret = -EINVAL;
-               goto free;
+               goto free_op1;
        }
 
        /* RHS of string is another expression e.g. c in a+b+c */
@@ -2605,13 +2604,12 @@ static struct hist_field *parse_expr(struct hist_trigger_data *hist_data,
        operand2 = parse_expr(hist_data, file, str, operand_flags, NULL, n_subexprs);
        if (IS_ERR(operand2)) {
                ret = PTR_ERR(operand2);
-               operand2 = NULL;
-               goto free;
+               goto free_op1;
        }
        if (operand2->flags & HIST_FIELD_FL_STRING) {
                hist_err(file->tr, HIST_ERR_INVALID_STR_OPERAND, errpos(str));
                ret = -EINVAL;
-               goto free;
+               goto free_operands;
        }
 
        switch (field_op) {
@@ -2629,12 +2627,12 @@ static struct hist_field *parse_expr(struct hist_trigger_data *hist_data,
                break;
        default:
                ret = -EINVAL;
-               goto free;
+               goto free_operands;
        }
 
        ret = check_expr_operands(file->tr, operand1, operand2, &var1, &var2);
        if (ret)
-               goto free;
+               goto free_operands;
 
        operand_flags = var1 ? var1->flags : operand1->flags;
        operand2_flags = var2 ? var2->flags : operand2->flags;
@@ -2653,12 +2651,13 @@ static struct hist_field *parse_expr(struct hist_trigger_data *hist_data,
        expr = create_hist_field(hist_data, NULL, flags, var_name);
        if (!expr) {
                ret = -ENOMEM;
-               goto free;
+               goto free_operands;
        }
 
        operand1->read_once = true;
        operand2->read_once = true;
 
+       /* The operands are now owned and free'd by 'expr' */
        expr->operands[0] = operand1;
        expr->operands[1] = operand2;
 
@@ -2669,7 +2668,7 @@ static struct hist_field *parse_expr(struct hist_trigger_data *hist_data,
                if (!divisor) {
                        hist_err(file->tr, HIST_ERR_DIVISION_BY_ZERO, errpos(str));
                        ret = -EDOM;
-                       goto free;
+                       goto free_expr;
                }
 
                /*
@@ -2709,18 +2708,22 @@ static struct hist_field *parse_expr(struct hist_trigger_data *hist_data,
                expr->type = kstrdup_const(operand1->type, GFP_KERNEL);
                if (!expr->type) {
                        ret = -ENOMEM;
-                       goto free;
+                       goto free_expr;
                }
 
                expr->name = expr_str(expr, 0);
        }
 
        return expr;
-free:
-       destroy_hist_field(operand1, 0);
+
+free_operands:
        destroy_hist_field(operand2, 0);
-       destroy_hist_field(expr, 0);
+free_op1:
+       destroy_hist_field(operand1, 0);
+       return ERR_PTR(ret);
 
+free_expr:
+       destroy_hist_field(expr, 0);
        return ERR_PTR(ret);
 }
 
@@ -3026,8 +3029,10 @@ static inline void __update_field_vars(struct tracing_map_elt *elt,
                if (val->flags & HIST_FIELD_FL_STRING) {
                        char *str = elt_data->field_var_str[j++];
                        char *val_str = (char *)(uintptr_t)var_val;
+                       unsigned int size;
 
-                       strscpy(str, val_str, val->size);
+                       size = min(val->size, STR_VAR_LEN_MAX);
+                       strscpy(str, val_str, size);
                        var_val = (u64)(uintptr_t)str;
                }
                tracing_map_set_var(elt, var_idx, var_val);
@@ -4914,6 +4919,7 @@ static void hist_trigger_elt_update(struct hist_trigger_data *hist_data,
                        if (hist_field->flags & HIST_FIELD_FL_STRING) {
                                unsigned int str_start, var_str_idx, idx;
                                char *str, *val_str;
+                               unsigned int size;
 
                                str_start = hist_data->n_field_var_str +
                                        hist_data->n_save_var_str;
@@ -4922,7 +4928,9 @@ static void hist_trigger_elt_update(struct hist_trigger_data *hist_data,
 
                                str = elt_data->field_var_str[idx];
                                val_str = (char *)(uintptr_t)hist_val;
-                               strscpy(str, val_str, hist_field->size);
+
+                               size = min(hist_field->size, STR_VAR_LEN_MAX);
+                               strscpy(str, val_str, size);
 
                                hist_val = (u64)(uintptr_t)str;
                        }
index f9e8900..199ab20 100644 (file)
@@ -75,6 +75,12 @@ void nmi_trigger_cpumask_backtrace(const cpumask_t *mask,
                touch_softlockup_watchdog();
        }
 
+       /*
+        * Force flush any remote buffers that might be stuck in IRQ context
+        * and therefore could not run their irq_work.
+        */
+       printk_trigger_flush();
+
        clear_bit_unlock(0, &backtrace_flag);
        put_cpu();
 }
index 65218ec..fc45339 100644 (file)
@@ -11,8 +11,6 @@
 obj-$(CONFIG_ZSTD_COMPRESS) += zstd_compress.o
 obj-$(CONFIG_ZSTD_DECOMPRESS) += zstd_decompress.o
 
-ccflags-y += -O3
-
 zstd_compress-y := \
                zstd_compress_module.o \
                common/debug.o \
index a1a051e..f5a9c70 100644 (file)
@@ -16,6 +16,7 @@
 *********************************************************/
 /* force inlining */
 
+#if !defined(ZSTD_NO_INLINE)
 #if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */
 #  define INLINE_KEYWORD inline
 #else
 
 #define FORCE_INLINE_ATTR __attribute__((always_inline))
 
+#else
+
+#define INLINE_KEYWORD
+#define FORCE_INLINE_ATTR
+
+#endif
 
 /*
   On MSVC qsort requires that functions passed into it use the __cdecl calling conversion(CC).
index ee03e0a..b0610b2 100644 (file)
@@ -411,6 +411,8 @@ static size_t ZSTD_seqDecompressedSize(seqStore_t const* seqStore, const seqDef*
     const seqDef* sp = sstart;
     size_t matchLengthSum = 0;
     size_t litLengthSum = 0;
+    /* Only used by assert(), suppress unused variable warnings in production. */
+    (void)litLengthSum;
     while (send-sp > 0) {
         ZSTD_sequenceLength const seqLen = ZSTD_getSequenceLength(seqStore, sp);
         litLengthSum += seqLen.litLength;
index 0433705..dfc55e3 100644 (file)
@@ -8,6 +8,18 @@
  * You may select, at your option, one of the above-listed licenses.
  */
 
+/*
+ * Disable inlining for the optimal parser for the kernel build.
+ * It is unlikely to be used in the kernel, and where it is used
+ * latency shouldn't matter because it is very slow to begin with.
+ * We prefer a ~180KB binary size win over faster optimal parsing.
+ *
+ * TODO(https://github.com/facebook/zstd/issues/2862):
+ * Improve the code size of the optimal parser in general, so we
+ * don't need this hack for the kernel build.
+ */
+#define ZSTD_NO_INLINE 1
+
 #include "zstd_compress_internal.h"
 #include "hist.h"
 #include "zstd_opt.h"
index 5ba4f94..5ad72db 100644 (file)
@@ -4229,7 +4229,9 @@ static void __devlink_flash_update_notify(struct devlink *devlink,
        WARN_ON(cmd != DEVLINK_CMD_FLASH_UPDATE &&
                cmd != DEVLINK_CMD_FLASH_UPDATE_END &&
                cmd != DEVLINK_CMD_FLASH_UPDATE_STATUS);
-       WARN_ON(!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED));
+
+       if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED))
+               return;
 
        msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
        if (!msg)
index e471c9b..6102f09 100644 (file)
@@ -7162,6 +7162,8 @@ sock_filter_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
 #endif
        case BPF_FUNC_sk_storage_get:
                return &bpf_sk_storage_get_cg_sock_proto;
+       case BPF_FUNC_ktime_get_coarse_ns:
+               return &bpf_ktime_get_coarse_ns_proto;
        default:
                return bpf_base_func_proto(func_id);
        }
@@ -10327,6 +10329,8 @@ sk_reuseport_func_proto(enum bpf_func_id func_id,
                return &sk_reuseport_load_bytes_relative_proto;
        case BPF_FUNC_get_socket_cookie:
                return &bpf_get_socket_ptr_cookie_proto;
+       case BPF_FUNC_ktime_get_coarse_ns:
+               return &bpf_ktime_get_coarse_ns_proto;
        default:
                return bpf_base_func_proto(func_id);
        }
@@ -10833,6 +10837,8 @@ bpf_sk_base_func_proto(enum bpf_func_id func_id)
        case BPF_FUNC_skc_to_unix_sock:
                func = &bpf_skc_to_unix_sock_proto;
                break;
+       case BPF_FUNC_ktime_get_coarse_ns:
+               return &bpf_ktime_get_coarse_ns_proto;
        default:
                return bpf_base_func_proto(func_id);
        }
index 9b60e43..1a69784 100644 (file)
@@ -49,12 +49,6 @@ static int page_pool_init(struct page_pool *pool,
         * which is the XDP_TX use-case.
         */
        if (pool->p.flags & PP_FLAG_DMA_MAP) {
-               /* DMA-mapping is not supported on 32-bit systems with
-                * 64-bit DMA mapping.
-                */
-               if (sizeof(dma_addr_t) > sizeof(unsigned long))
-                       return -EOPNOTSUPP;
-
                if ((pool->p.dma_dir != DMA_FROM_DEVICE) &&
                    (pool->p.dma_dir != DMA_BIDIRECTIONAL))
                        return -EINVAL;
@@ -75,6 +69,10 @@ static int page_pool_init(struct page_pool *pool,
                 */
        }
 
+       if (PAGE_POOL_DMA_USE_PP_FRAG_COUNT &&
+           pool->p.flags & PP_FLAG_PAGE_FRAG)
+               return -EINVAL;
+
        if (ptr_ring_init(&pool->ring, ring_qsize, GFP_KERNEL) < 0)
                return -ENOMEM;
 
index 8f2b2f2..41e91d0 100644 (file)
@@ -2124,8 +2124,10 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
        newsk->sk_prot_creator = prot;
 
        /* SANITY */
-       if (likely(newsk->sk_net_refcnt))
+       if (likely(newsk->sk_net_refcnt)) {
                get_net(sock_net(newsk));
+               sock_inuse_add(sock_net(newsk), 1);
+       }
        sk_node_init(&newsk->sk_node);
        sock_lock_init(newsk);
        bh_lock_sock(newsk);
@@ -2197,8 +2199,6 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
        newsk->sk_err_soft = 0;
        newsk->sk_priority = 0;
        newsk->sk_incoming_cpu = raw_smp_processor_id();
-       if (likely(newsk->sk_net_refcnt))
-               sock_inuse_add(sock_net(newsk), 1);
 
        /* Before updating sk_refcnt, we must commit prior changes to memory
         * (Documentation/RCU/rculist_nulls.rst for details)
index 2cf02b4..4bb9401 100644 (file)
@@ -205,6 +205,8 @@ bpf_tcp_ca_get_func_proto(enum bpf_func_id func_id,
                    offsetof(struct tcp_congestion_ops, release))
                        return &bpf_sk_getsockopt_proto;
                return NULL;
+       case BPF_FUNC_ktime_get_coarse_ns:
+               return &bpf_ktime_get_coarse_ns_proto;
        default:
                return bpf_base_func_proto(func_id);
        }
index ec73a0d..323e622 100644 (file)
@@ -2591,7 +2591,7 @@ static int __devinet_sysctl_register(struct net *net, char *dev_name,
 free:
        kfree(t);
 out:
-       return -ENOBUFS;
+       return -ENOMEM;
 }
 
 static void __devinet_sysctl_unregister(struct net *net,
index b7796b4..bbb3d39 100644 (file)
@@ -1758,6 +1758,9 @@ static skb_frag_t *skb_advance_to_frag(struct sk_buff *skb, u32 offset_skb,
 {
        skb_frag_t *frag;
 
+       if (unlikely(offset_skb >= skb->len))
+               return NULL;
+
        offset_skb -= skb_headlen(skb);
        if ((int)offset_skb < 0 || skb_has_frag_list(skb))
                return NULL;
index 319dd7b..8bcecdd 100644 (file)
@@ -1807,6 +1807,17 @@ int udp_read_sock(struct sock *sk, read_descriptor_t *desc,
                skb = skb_recv_udp(sk, 0, 1, &err);
                if (!skb)
                        return err;
+
+               if (udp_lib_checksum_complete(skb)) {
+                       __UDP_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS,
+                                       IS_UDPLITE(sk));
+                       __UDP_INC_STATS(sock_net(sk), UDP_MIB_INERRORS,
+                                       IS_UDPLITE(sk));
+                       atomic_inc(&sk->sk_drops);
+                       kfree_skb(skb);
+                       continue;
+               }
+
                used = recv_actor(desc, skb, 0, skb->len);
                if (used <= 0) {
                        if (!copied)
index ed2f061..f0bac6f 100644 (file)
@@ -808,6 +808,12 @@ int esp6_input_done2(struct sk_buff *skb, int err)
                struct tcphdr *th;
 
                offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
+
+               if (offset < 0) {
+                       err = -EINVAL;
+                       goto out;
+               }
+
                uh = (void *)(skb->data + offset);
                th = (void *)(skb->data + offset);
                hdr_len += offset;
index e2b791c..bd3d319 100644 (file)
@@ -80,7 +80,8 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata,
        }
 
        /* also validate MU-MIMO change */
-       monitor_sdata = rtnl_dereference(local->monitor_sdata);
+       monitor_sdata = wiphy_dereference(local->hw.wiphy,
+                                         local->monitor_sdata);
 
        if (!monitor_sdata &&
            (params->vht_mumimo_groups || params->vht_mumimo_follow_addr))
@@ -840,7 +841,8 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
 
        mutex_lock(&local->mtx);
        if (local->use_chanctx) {
-               sdata = rtnl_dereference(local->monitor_sdata);
+               sdata = wiphy_dereference(local->hw.wiphy,
+                                         local->monitor_sdata);
                if (sdata) {
                        ieee80211_vif_release_channel(sdata);
                        ret = ieee80211_vif_use_channel(sdata, chandef,
@@ -2707,7 +2709,8 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
                sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
 
                if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
-                       sdata = rtnl_dereference(local->monitor_sdata);
+                       sdata = wiphy_dereference(local->hw.wiphy,
+                                                 local->monitor_sdata);
                        if (!sdata)
                                return -EOPNOTSUPP;
                }
@@ -2767,7 +2770,8 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
        mutex_unlock(&local->iflist_mtx);
 
        if (has_monitor) {
-               sdata = rtnl_dereference(local->monitor_sdata);
+               sdata = wiphy_dereference(local->hw.wiphy,
+                                         local->monitor_sdata);
                if (sdata) {
                        sdata->user_power_level = local->user_power_level;
                        if (txp_type != sdata->vif.bss_conf.txpower_type)
index 9a2145c..20aa5cc 100644 (file)
@@ -588,7 +588,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
         */
        if (local->suspended) {
                WARN_ON(local->wowlan);
-               WARN_ON(rtnl_dereference(local->monitor_sdata));
+               WARN_ON(rcu_access_pointer(local->monitor_sdata));
                return;
        }
 
@@ -961,6 +961,7 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
                return 0;
 
        ASSERT_RTNL();
+       lockdep_assert_wiphy(local->hw.wiphy);
 
        if (local->monitor_sdata)
                return 0;
@@ -1028,6 +1029,7 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
                return;
 
        ASSERT_RTNL();
+       lockdep_assert_wiphy(local->hw.wiphy);
 
        mutex_lock(&local->iflist_mtx);
 
index fb3aaa3..b71a142 100644 (file)
@@ -72,19 +72,19 @@ static inline void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local,
 #endif
 
 static inline void
-ieee80211_tpt_led_trig_tx(struct ieee80211_local *local, __le16 fc, int bytes)
+ieee80211_tpt_led_trig_tx(struct ieee80211_local *local, int bytes)
 {
 #ifdef CONFIG_MAC80211_LEDS
-       if (ieee80211_is_data(fc) && atomic_read(&local->tpt_led_active))
+       if (atomic_read(&local->tpt_led_active))
                local->tpt_led_trigger->tx_bytes += bytes;
 #endif
 }
 
 static inline void
-ieee80211_tpt_led_trig_rx(struct ieee80211_local *local, __le16 fc, int bytes)
+ieee80211_tpt_led_trig_rx(struct ieee80211_local *local, int bytes)
 {
 #ifdef CONFIG_MAC80211_LEDS
-       if (ieee80211_is_data(fc) && atomic_read(&local->tpt_led_active))
+       if (atomic_read(&local->tpt_led_active))
                local->tpt_led_trigger->rx_bytes += bytes;
 #endif
 }
index fc5c608..9541a4c 100644 (file)
@@ -364,7 +364,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
         * the compiler to think we have walked past the end of the
         * struct member.
         */
-       pos = (void *)&rthdr->it_optional[it_present - rthdr->it_optional];
+       pos = (void *)&rthdr->it_optional[it_present + 1 - rthdr->it_optional];
 
        /* the order of the following fields is important */
 
@@ -1952,7 +1952,8 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
                int keyid = rx->sta->ptk_idx;
                sta_ptk = rcu_dereference(rx->sta->ptk[keyid]);
 
-               if (ieee80211_has_protected(fc)) {
+               if (ieee80211_has_protected(fc) &&
+                   !(status->flag & RX_FLAG_IV_STRIPPED)) {
                        cs = rx->sta->cipher_scheme;
                        keyid = ieee80211_get_keyid(rx->skb, cs);
 
@@ -4863,6 +4864,7 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,
        struct ieee80211_rate *rate = NULL;
        struct ieee80211_supported_band *sband;
        struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 
        WARN_ON_ONCE(softirq_count() == 0);
 
@@ -4959,9 +4961,9 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,
        if (!(status->flag & RX_FLAG_8023))
                skb = ieee80211_rx_monitor(local, skb, rate);
        if (skb) {
-               ieee80211_tpt_led_trig_rx(local,
-                                         ((struct ieee80211_hdr *)skb->data)->frame_control,
-                                         skb->len);
+               if ((status->flag & RX_FLAG_8023) ||
+                       ieee80211_is_data_present(hdr->frame_control))
+                       ieee80211_tpt_led_trig_rx(local, skb->len);
 
                if (status->flag & RX_FLAG_8023)
                        __ieee80211_rx_handle_8023(hw, pubsta, skb, list);
index a756a19..278945e 100644 (file)
@@ -1721,21 +1721,19 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
  * Returns false if the frame couldn't be transmitted but was queued instead.
  */
 static bool __ieee80211_tx(struct ieee80211_local *local,
-                          struct sk_buff_head *skbs, int led_len,
-                          struct sta_info *sta, bool txpending)
+                          struct sk_buff_head *skbs, struct sta_info *sta,
+                          bool txpending)
 {
        struct ieee80211_tx_info *info;
        struct ieee80211_sub_if_data *sdata;
        struct ieee80211_vif *vif;
        struct sk_buff *skb;
        bool result;
-       __le16 fc;
 
        if (WARN_ON(skb_queue_empty(skbs)))
                return true;
 
        skb = skb_peek(skbs);
-       fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
        info = IEEE80211_SKB_CB(skb);
        sdata = vif_to_sdata(info->control.vif);
        if (sta && !sta->uploaded)
@@ -1769,8 +1767,6 @@ static bool __ieee80211_tx(struct ieee80211_local *local,
 
        result = ieee80211_tx_frags(local, vif, sta, skbs, txpending);
 
-       ieee80211_tpt_led_trig_tx(local, fc, led_len);
-
        WARN_ON_ONCE(!skb_queue_empty(skbs));
 
        return result;
@@ -1920,7 +1916,6 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
        ieee80211_tx_result res_prepare;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        bool result = true;
-       int led_len;
 
        if (unlikely(skb->len < 10)) {
                dev_kfree_skb(skb);
@@ -1928,7 +1923,6 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
        }
 
        /* initialises tx */
-       led_len = skb->len;
        res_prepare = ieee80211_tx_prepare(sdata, &tx, sta, skb);
 
        if (unlikely(res_prepare == TX_DROP)) {
@@ -1951,8 +1945,7 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
                return true;
 
        if (!invoke_tx_handlers_late(&tx))
-               result = __ieee80211_tx(local, &tx.skbs, led_len,
-                                       tx.sta, txpending);
+               result = __ieee80211_tx(local, &tx.skbs, tx.sta, txpending);
 
        return result;
 }
@@ -4175,6 +4168,7 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
        struct ieee80211_local *local = sdata->local;
        struct sta_info *sta;
        struct sk_buff *next;
+       int len = skb->len;
 
        if (unlikely(skb->len < ETH_HLEN)) {
                kfree_skb(skb);
@@ -4221,10 +4215,8 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
                }
        } else {
                /* we cannot process non-linear frames on this path */
-               if (skb_linearize(skb)) {
-                       kfree_skb(skb);
-                       goto out;
-               }
+               if (skb_linearize(skb))
+                       goto out_free;
 
                /* the frame could be fragmented, software-encrypted, and other
                 * things so we cannot really handle checksum offload with it -
@@ -4258,7 +4250,10 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
        goto out;
  out_free:
        kfree_skb(skb);
+       len = 0;
  out:
+       if (len)
+               ieee80211_tpt_led_trig_tx(local, len);
        rcu_read_unlock();
 }
 
@@ -4396,8 +4391,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 }
 
 static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata,
-                             struct sk_buff *skb, int led_len,
-                             struct sta_info *sta,
+                             struct sk_buff *skb, struct sta_info *sta,
                              bool txpending)
 {
        struct ieee80211_local *local = sdata->local;
@@ -4410,6 +4404,8 @@ static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata,
        if (sta)
                sk_pacing_shift_update(skb->sk, local->hw.tx_sk_pacing_shift);
 
+       ieee80211_tpt_led_trig_tx(local, skb->len);
+
        if (ieee80211_queue_skb(local, sdata, sta, skb))
                return true;
 
@@ -4498,7 +4494,7 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
        if (key)
                info->control.hw_key = &key->conf;
 
-       ieee80211_tx_8023(sdata, skb, skb->len, sta, false);
+       ieee80211_tx_8023(sdata, skb, sta, false);
 
        return;
 
@@ -4637,7 +4633,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
                if (IS_ERR(sta) || (sta && !sta->uploaded))
                        sta = NULL;
 
-               result = ieee80211_tx_8023(sdata, skb, skb->len, sta, true);
+               result = ieee80211_tx_8023(sdata, skb, sta, true);
        } else {
                struct sk_buff_head skbs;
 
@@ -4647,7 +4643,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
                hdr = (struct ieee80211_hdr *)skb->data;
                sta = sta_info_get(sdata, hdr->addr1);
 
-               result = __ieee80211_tx(local, &skbs, skb->len, sta, true);
+               result = __ieee80211_tx(local, &skbs, sta, true);
        }
 
        return result;
index 39fa2a5..43df2f0 100644 (file)
@@ -796,7 +796,7 @@ static void __iterate_interfaces(struct ieee80211_local *local,
 
        sdata = rcu_dereference_check(local->monitor_sdata,
                                      lockdep_is_held(&local->iflist_mtx) ||
-                                     lockdep_rtnl_is_held());
+                                     lockdep_is_held(&local->hw.wiphy->mtx));
        if (sdata &&
            (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || !active_only ||
             sdata->flags & IEEE80211_SDATA_IN_DRIVER))
@@ -2381,7 +2381,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                                   IEEE80211_TPT_LEDTRIG_FL_RADIO, 0);
 
        /* add interfaces */
-       sdata = rtnl_dereference(local->monitor_sdata);
+       sdata = wiphy_dereference(local->hw.wiphy, local->monitor_sdata);
        if (sdata) {
                /* in HW restart it exists already */
                WARN_ON(local->resuming);
@@ -2426,7 +2426,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                                WARN_ON(drv_add_chanctx(local, ctx));
                mutex_unlock(&local->chanctx_mtx);
 
-               sdata = rtnl_dereference(local->monitor_sdata);
+               sdata = wiphy_dereference(local->hw.wiphy,
+                                         local->monitor_sdata);
                if (sdata && ieee80211_sdata_running(sdata))
                        ieee80211_assign_chanctx(local, sdata);
        }
index 9ea6004..62c6733 100644 (file)
@@ -143,7 +143,6 @@ u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata,
 u16 __ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
                             struct sta_info *sta, struct sk_buff *skb)
 {
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct mac80211_qos_map *qos_map;
        bool qos;
 
@@ -156,7 +155,7 @@ u16 __ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
        else
                qos = false;
 
-       if (!qos || (info->control.flags & IEEE80211_TX_CTRL_DONT_REORDER)) {
+       if (!qos) {
                skb->priority = 0; /* required for correct WPA/11i MIC */
                return IEEE80211_AC_BE;
        }
index 3c645c1..dc7a240 100644 (file)
@@ -94,13 +94,13 @@ int nfc_dev_up(struct nfc_dev *dev)
 
        device_lock(&dev->dev);
 
-       if (dev->rfkill && rfkill_blocked(dev->rfkill)) {
-               rc = -ERFKILL;
+       if (!device_is_registered(&dev->dev)) {
+               rc = -ENODEV;
                goto error;
        }
 
-       if (!device_is_registered(&dev->dev)) {
-               rc = -ENODEV;
+       if (dev->rfkill && rfkill_blocked(dev->rfkill)) {
+               rc = -ERFKILL;
                goto error;
        }
 
@@ -1125,11 +1125,7 @@ int nfc_register_device(struct nfc_dev *dev)
        if (rc)
                pr_err("Could not register llcp device\n");
 
-       rc = nfc_genl_device_added(dev);
-       if (rc)
-               pr_debug("The userspace won't be notified that the device %s was added\n",
-                        dev_name(&dev->dev));
-
+       device_lock(&dev->dev);
        dev->rfkill = rfkill_alloc(dev_name(&dev->dev), &dev->dev,
                                   RFKILL_TYPE_NFC, &nfc_rfkill_ops, dev);
        if (dev->rfkill) {
@@ -1138,6 +1134,12 @@ int nfc_register_device(struct nfc_dev *dev)
                        dev->rfkill = NULL;
                }
        }
+       device_unlock(&dev->dev);
+
+       rc = nfc_genl_device_added(dev);
+       if (rc)
+               pr_debug("The userspace won't be notified that the device %s was added\n",
+                        dev_name(&dev->dev));
 
        return 0;
 }
@@ -1154,10 +1156,17 @@ void nfc_unregister_device(struct nfc_dev *dev)
 
        pr_debug("dev_name=%s\n", dev_name(&dev->dev));
 
+       rc = nfc_genl_device_removed(dev);
+       if (rc)
+               pr_debug("The userspace won't be notified that the device %s "
+                        "was removed\n", dev_name(&dev->dev));
+
+       device_lock(&dev->dev);
        if (dev->rfkill) {
                rfkill_unregister(dev->rfkill);
                rfkill_destroy(dev->rfkill);
        }
+       device_unlock(&dev->dev);
 
        if (dev->ops->check_presence) {
                device_lock(&dev->dev);
@@ -1167,11 +1176,6 @@ void nfc_unregister_device(struct nfc_dev *dev)
                cancel_work_sync(&dev->check_pres_work);
        }
 
-       rc = nfc_genl_device_removed(dev);
-       if (rc)
-               pr_debug("The userspace won't be notified that the device %s "
-                        "was removed\n", dev_name(&dev->dev));
-
        nfc_llcp_unregister_device(dev);
 
        mutex_lock(&nfc_devlist_mutex);
index 6fd873a..d253738 100644 (file)
@@ -144,12 +144,15 @@ inline int nci_request(struct nci_dev *ndev,
 {
        int rc;
 
-       if (!test_bit(NCI_UP, &ndev->flags))
-               return -ENETDOWN;
-
        /* Serialize all requests */
        mutex_lock(&ndev->req_lock);
-       rc = __nci_request(ndev, req, opt, timeout);
+       /* check the state after obtaing the lock against any races
+        * from nci_close_device when the device gets removed.
+        */
+       if (test_bit(NCI_UP, &ndev->flags))
+               rc = __nci_request(ndev, req, opt, timeout);
+       else
+               rc = -ENETDOWN;
        mutex_unlock(&ndev->req_lock);
 
        return rc;
@@ -473,6 +476,11 @@ static int nci_open_device(struct nci_dev *ndev)
 
        mutex_lock(&ndev->req_lock);
 
+       if (test_bit(NCI_UNREG, &ndev->flags)) {
+               rc = -ENODEV;
+               goto done;
+       }
+
        if (test_bit(NCI_UP, &ndev->flags)) {
                rc = -EALREADY;
                goto done;
@@ -545,6 +553,10 @@ done:
 static int nci_close_device(struct nci_dev *ndev)
 {
        nci_req_cancel(ndev, ENODEV);
+
+       /* This mutex needs to be held as a barrier for
+        * caller nci_unregister_device
+        */
        mutex_lock(&ndev->req_lock);
 
        if (!test_and_clear_bit(NCI_UP, &ndev->flags)) {
@@ -582,8 +594,8 @@ static int nci_close_device(struct nci_dev *ndev)
 
        del_timer_sync(&ndev->cmd_timer);
 
-       /* Clear flags */
-       ndev->flags = 0;
+       /* Clear flags except NCI_UNREG */
+       ndev->flags &= BIT(NCI_UNREG);
 
        mutex_unlock(&ndev->req_lock);
 
@@ -1266,6 +1278,12 @@ void nci_unregister_device(struct nci_dev *ndev)
 {
        struct nci_conn_info *conn_info, *n;
 
+       /* This set_bit is not protected with specialized barrier,
+        * However, it is fine because the mutex_lock(&ndev->req_lock);
+        * in nci_close_device() will help to emit one.
+        */
+       set_bit(NCI_UNREG, &ndev->flags);
+
        nci_close_device(ndev);
 
        destroy_workqueue(ndev->cmd_wq);
index d64b0ee..efc963a 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/if_arp.h>
 #include <net/net_namespace.h>
 #include <net/netlink.h>
+#include <net/dst.h>
 #include <net/pkt_sched.h>
 #include <net/pkt_cls.h>
 #include <linux/tc_act/tc_mirred.h>
@@ -228,6 +229,7 @@ static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a,
        bool want_ingress;
        bool is_redirect;
        bool expects_nh;
+       bool at_ingress;
        int m_eaction;
        int mac_len;
        bool at_nh;
@@ -263,7 +265,8 @@ static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a,
         * ingress - that covers the TC S/W datapath.
         */
        is_redirect = tcf_mirred_is_act_redirect(m_eaction);
-       use_reinsert = skb_at_tc_ingress(skb) && is_redirect &&
+       at_ingress = skb_at_tc_ingress(skb);
+       use_reinsert = at_ingress && is_redirect &&
                       tcf_mirred_can_reinsert(retval);
        if (!use_reinsert) {
                skb2 = skb_clone(skb, GFP_ATOMIC);
@@ -271,10 +274,12 @@ static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a,
                        goto out;
        }
 
+       want_ingress = tcf_mirred_act_wants_ingress(m_eaction);
+
        /* All mirred/redirected skbs should clear previous ct info */
        nf_reset_ct(skb2);
-
-       want_ingress = tcf_mirred_act_wants_ingress(m_eaction);
+       if (want_ingress && !at_ingress) /* drop dst for egress -> ingress */
+               skb_dst_drop(skb2);
 
        expects_nh = want_ingress || !m_mac_header_xmit;
        at_nh = skb->data == skb_network_header(skb);
index 59284da..b61c802 100644 (file)
@@ -566,6 +566,10 @@ static void smc_stat_fallback(struct smc_sock *smc)
 
 static void smc_switch_to_fallback(struct smc_sock *smc, int reason_code)
 {
+       wait_queue_head_t *smc_wait = sk_sleep(&smc->sk);
+       wait_queue_head_t *clc_wait = sk_sleep(smc->clcsock->sk);
+       unsigned long flags;
+
        smc->use_fallback = true;
        smc->fallback_rsn = reason_code;
        smc_stat_fallback(smc);
@@ -575,6 +579,16 @@ static void smc_switch_to_fallback(struct smc_sock *smc, int reason_code)
                smc->clcsock->file->private_data = smc->clcsock;
                smc->clcsock->wq.fasync_list =
                        smc->sk.sk_socket->wq.fasync_list;
+
+               /* There may be some entries remaining in
+                * smc socket->wq, which should be removed
+                * to clcsocket->wq during the fallback.
+                */
+               spin_lock_irqsave(&smc_wait->lock, flags);
+               spin_lock(&clc_wait->lock);
+               list_splice_init(&smc_wait->head, &clc_wait->head);
+               spin_unlock(&clc_wait->lock);
+               spin_unlock_irqrestore(&smc_wait->lock, flags);
        }
 }
 
index 49b8ba3..25ebd30 100644 (file)
@@ -708,13 +708,14 @@ static u8 smcr_next_link_id(struct smc_link_group *lgr)
        int i;
 
        while (1) {
+again:
                link_id = ++lgr->next_link_id;
                if (!link_id)   /* skip zero as link_id */
                        link_id = ++lgr->next_link_id;
                for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
                        if (smc_link_usable(&lgr->lnk[i]) &&
                            lgr->lnk[i].link_id == link_id)
-                               continue;
+                               goto again;
                }
                break;
        }
index dc60c32..b4d9419 100644 (file)
@@ -524,7 +524,7 @@ static int tipc_aead_init(struct tipc_aead **aead, struct tipc_aead_key *ukey,
                return -EEXIST;
 
        /* Allocate a new AEAD */
-       tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC);
+       tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
        if (unlikely(!tmp))
                return -ENOMEM;
 
@@ -597,6 +597,10 @@ static int tipc_aead_init(struct tipc_aead **aead, struct tipc_aead_key *ukey,
        tmp->cloned = NULL;
        tmp->authsize = TIPC_AES_GCM_TAG_SIZE;
        tmp->key = kmemdup(ukey, tipc_aead_key_size(ukey), GFP_KERNEL);
+       if (!tmp->key) {
+               tipc_aead_free(&tmp->rcu);
+               return -ENOMEM;
+       }
        memcpy(&tmp->salt, ukey->key + keylen, TIPC_AES_GCM_SALT_SIZE);
        atomic_set(&tmp->users, 0);
        atomic64_set(&tmp->seqno, 0);
@@ -1470,7 +1474,7 @@ int tipc_crypto_start(struct tipc_crypto **crypto, struct net *net,
                return -EEXIST;
 
        /* Allocate crypto */
-       c = kzalloc(sizeof(*c), GFP_ATOMIC);
+       c = kzalloc(sizeof(*c), GFP_KERNEL);
        if (!c)
                return -ENOMEM;
 
@@ -1484,7 +1488,7 @@ int tipc_crypto_start(struct tipc_crypto **crypto, struct net *net,
        }
 
        /* Allocate statistic structure */
-       c->stats = alloc_percpu_gfp(struct tipc_crypto_stats, GFP_ATOMIC);
+       c->stats = alloc_percpu(struct tipc_crypto_stats);
        if (!c->stats) {
                if (c->wq)
                        destroy_workqueue(c->wq);
@@ -2457,7 +2461,7 @@ static void tipc_crypto_work_tx(struct work_struct *work)
        }
 
        /* Lets duplicate it first */
-       skey = kmemdup(aead->key, tipc_aead_key_size(aead->key), GFP_ATOMIC);
+       skey = kmemdup(aead->key, tipc_aead_key_size(aead->key), GFP_KERNEL);
        rcu_read_unlock();
 
        /* Now, generate new key, initiate & distribute it */
index 1b7a487..09ae844 100644 (file)
@@ -1298,8 +1298,11 @@ static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb,
                return false;
 #ifdef CONFIG_TIPC_CRYPTO
        case MSG_CRYPTO:
-               tipc_crypto_msg_rcv(l->net, skb);
-               return true;
+               if (TIPC_SKB_CB(skb)->decrypted) {
+                       tipc_crypto_msg_rcv(l->net, skb);
+                       return true;
+               }
+               fallthrough;
 #endif
        default:
                pr_warn("Dropping received illegal msg type\n");
index 81232b7..a27b3b5 100644 (file)
@@ -936,33 +936,37 @@ nl80211_packet_pattern_policy[MAX_NL80211_PKTPAT + 1] = {
        [NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 },
 };
 
-int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
-                             struct cfg80211_registered_device **rdev,
-                             struct wireless_dev **wdev)
+static int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
+                                    struct cfg80211_registered_device **rdev,
+                                    struct wireless_dev **wdev,
+                                    struct nlattr **attrbuf)
 {
        int err;
 
        if (!cb->args[0]) {
-               struct nlattr **attrbuf;
+               struct nlattr **attrbuf_free = NULL;
 
-               attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf),
-                                 GFP_KERNEL);
-               if (!attrbuf)
-                       return -ENOMEM;
+               if (!attrbuf) {
+                       attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf),
+                                         GFP_KERNEL);
+                       if (!attrbuf)
+                               return -ENOMEM;
+                       attrbuf_free = attrbuf;
+               }
 
                err = nlmsg_parse_deprecated(cb->nlh,
                                             GENL_HDRLEN + nl80211_fam.hdrsize,
                                             attrbuf, nl80211_fam.maxattr,
                                             nl80211_policy, NULL);
                if (err) {
-                       kfree(attrbuf);
+                       kfree(attrbuf_free);
                        return err;
                }
 
                rtnl_lock();
                *wdev = __cfg80211_wdev_from_attrs(NULL, sock_net(cb->skb->sk),
                                                   attrbuf);
-               kfree(attrbuf);
+               kfree(attrbuf_free);
                if (IS_ERR(*wdev)) {
                        rtnl_unlock();
                        return PTR_ERR(*wdev);
@@ -6197,7 +6201,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
        int sta_idx = cb->args[2];
        int err;
 
-       err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
+       err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL);
        if (err)
                return err;
        /* nl80211_prepare_wdev_dump acquired it in the successful case */
@@ -7092,7 +7096,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
        int path_idx = cb->args[2];
        int err;
 
-       err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
+       err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL);
        if (err)
                return err;
        /* nl80211_prepare_wdev_dump acquired it in the successful case */
@@ -7292,7 +7296,7 @@ static int nl80211_dump_mpp(struct sk_buff *skb,
        int path_idx = cb->args[2];
        int err;
 
-       err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
+       err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL);
        if (err)
                return err;
        /* nl80211_prepare_wdev_dump acquired it in the successful case */
@@ -9718,7 +9722,7 @@ static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb)
        int start = cb->args[2], idx = 0;
        int err;
 
-       err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
+       err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL);
        if (err)
                return err;
        /* nl80211_prepare_wdev_dump acquired it in the successful case */
@@ -9851,7 +9855,7 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
        if (!attrbuf)
                return -ENOMEM;
 
-       res = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
+       res = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, attrbuf);
        if (res) {
                kfree(attrbuf);
                return res;
index a3f3877..d642e3b 100644 (file)
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Portions of this file
- * Copyright (C) 2018, 2020 Intel Corporation
+ * Copyright (C) 2018, 2020-2021 Intel Corporation
  */
 #ifndef __NET_WIRELESS_NL80211_H
 #define __NET_WIRELESS_NL80211_H
@@ -22,10 +22,6 @@ static inline u64 wdev_id(struct wireless_dev *wdev)
               ((u64)wiphy_to_rdev(wdev->wiphy)->wiphy_idx << 32);
 }
 
-int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
-                             struct cfg80211_registered_device **rdev,
-                             struct wireless_dev **wdev);
-
 int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
                          struct genl_info *info,
                          struct cfg80211_chan_def *chandef);
index 5ff1f87..41ea65d 100644 (file)
@@ -1046,6 +1046,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
 
                switch (otype) {
                case NL80211_IFTYPE_AP:
+               case NL80211_IFTYPE_P2P_GO:
                        cfg80211_stop_ap(rdev, dev, true);
                        break;
                case NL80211_IFTYPE_ADHOC:
index 90c4e1e..bc4ad48 100644 (file)
@@ -500,7 +500,7 @@ struct xdp_buff *xp_alloc(struct xsk_buff_pool *pool)
                pool->free_list_cnt--;
                xskb = list_first_entry(&pool->free_list, struct xdp_buff_xsk,
                                        free_list_node);
-               list_del(&xskb->free_list_node);
+               list_del_init(&xskb->free_list_node);
        }
 
        xskb->xdp.data = xskb->xdp.data_hard_start + XDP_PACKET_HEADROOM;
@@ -568,7 +568,7 @@ static u32 xp_alloc_reused(struct xsk_buff_pool *pool, struct xdp_buff **xdp, u3
        i = nb_entries;
        while (i--) {
                xskb = list_first_entry(&pool->free_list, struct xdp_buff_xsk, free_list_node);
-               list_del(&xskb->free_list_node);
+               list_del_init(&xskb->free_list_node);
 
                *xdp = &xskb->xdp;
                xdp++;
@@ -615,6 +615,9 @@ EXPORT_SYMBOL(xp_can_alloc);
 
 void xp_free(struct xdp_buff_xsk *xskb)
 {
+       if (!list_empty(&xskb->free_list_node))
+               return;
+
        xskb->pool->free_list_cnt++;
        list_add(&xskb->free_list_node, &xskb->pool->free_list);
 }
index bec3528..43d2e9a 100644 (file)
@@ -31,6 +31,15 @@ config SAMPLE_FTRACE_DIRECT
          This builds an ftrace direct function example
          that hooks to wake_up_process and prints the parameters.
 
+config SAMPLE_FTRACE_DIRECT_MULTI
+       tristate "Build register_ftrace_direct_multi() example"
+       depends on DYNAMIC_FTRACE_WITH_DIRECT_CALLS && m
+       depends on HAVE_SAMPLE_FTRACE_DIRECT_MULTI
+       help
+         This builds an ftrace direct function example
+         that hooks to wake_up_process and schedule, and prints
+         the function addresses.
+
 config SAMPLE_TRACE_ARRAY
         tristate "Build sample module for kernel access to Ftrace instancess"
        depends on EVENT_TRACING && m
@@ -237,5 +246,5 @@ endif # SAMPLES
 config HAVE_SAMPLE_FTRACE_DIRECT
        bool
 
-config HAVE_SAMPLE_FTRACE_MULTI_DIRECT
+config HAVE_SAMPLE_FTRACE_DIRECT_MULTI
        bool
index b7b9830..4bcd6b9 100644 (file)
@@ -22,7 +22,7 @@ subdir-$(CONFIG_SAMPLE_TIMER)         += timers
 obj-$(CONFIG_SAMPLE_TRACE_EVENTS)      += trace_events/
 obj-$(CONFIG_SAMPLE_TRACE_PRINTK)      += trace_printk/
 obj-$(CONFIG_SAMPLE_FTRACE_DIRECT)     += ftrace/
-obj-$(CONFIG_SAMPLE_FTRACE_MULTI_DIRECT) += ftrace/
+obj-$(CONFIG_SAMPLE_FTRACE_DIRECT_MULTI) += ftrace/
 obj-$(CONFIG_SAMPLE_TRACE_ARRAY)       += ftrace/
 subdir-$(CONFIG_SAMPLE_UHID)           += uhid
 obj-$(CONFIG_VIDEO_PCI_SKELETON)       += v4l/
index 722b3fa..1752a46 100644 (file)
@@ -9,8 +9,6 @@
  * Include file for sample Host Bandwidth Manager (HBM) BPF programs
  */
 #define KBUILD_MODNAME "foo"
-#include <stddef.h>
-#include <stdbool.h>
 #include <uapi/linux/bpf.h>
 #include <uapi/linux/if_ether.h>
 #include <uapi/linux/if_packet.h>
index d84e694..a81704d 100644 (file)
@@ -309,7 +309,6 @@ int main(int argc, char **argv)
        const char *mprog_filename = NULL, *mprog_name = NULL;
        struct xdp_redirect_cpu *skel;
        struct bpf_map_info info = {};
-       char ifname_buf[IF_NAMESIZE];
        struct bpf_cpumap_val value;
        __u32 infosz = sizeof(info);
        int ret = EXIT_FAIL_OPTION;
@@ -390,10 +389,10 @@ int main(int argc, char **argv)
                case 'd':
                        if (strlen(optarg) >= IF_NAMESIZE) {
                                fprintf(stderr, "-d/--dev name too long\n");
+                               usage(argv, long_options, __doc__, mask, true, skel->obj);
                                goto end_cpu;
                        }
-                       safe_strncpy(ifname_buf, optarg, strlen(ifname_buf));
-                       ifindex = if_nametoindex(ifname_buf);
+                       ifindex = if_nametoindex(optarg);
                        if (!ifindex)
                                ifindex = strtoul(optarg, NULL, 0);
                        if (!ifindex) {
index b32d821..8740838 100644 (file)
@@ -120,7 +120,10 @@ struct sample_output {
                __u64 xmit;
        } totals;
        struct {
-               __u64 pps;
+               union {
+                       __u64 pps;
+                       __u64 num;
+               };
                __u64 drop;
                __u64 err;
        } rx_cnt;
@@ -1322,7 +1325,7 @@ int sample_install_xdp(struct bpf_program *xdp_prog, int ifindex, bool generic,
 
 static void sample_summary_print(void)
 {
-       double period = sample_out.rx_cnt.pps;
+       double num = sample_out.rx_cnt.num;
 
        if (sample_out.totals.rx) {
                double pkts = sample_out.totals.rx;
@@ -1330,7 +1333,7 @@ static void sample_summary_print(void)
                print_always("  Packets received    : %'-10llu\n",
                             sample_out.totals.rx);
                print_always("  Average packets/s   : %'-10.0f\n",
-                            sample_round(pkts / period));
+                            sample_round(pkts / num));
        }
        if (sample_out.totals.redir) {
                double pkts = sample_out.totals.redir;
@@ -1338,7 +1341,7 @@ static void sample_summary_print(void)
                print_always("  Packets redirected  : %'-10llu\n",
                             sample_out.totals.redir);
                print_always("  Average redir/s     : %'-10.0f\n",
-                            sample_round(pkts / period));
+                            sample_round(pkts / num));
        }
        if (sample_out.totals.drop)
                print_always("  Rx dropped          : %'-10llu\n",
@@ -1355,7 +1358,7 @@ static void sample_summary_print(void)
                print_always("  Packets transmitted : %'-10llu\n",
                             sample_out.totals.xmit);
                print_always("  Average transmit/s  : %'-10.0f\n",
-                            sample_round(pkts / period));
+                            sample_round(pkts / num));
        }
 }
 
@@ -1422,7 +1425,7 @@ static int sample_stats_collect(struct stats_record *rec)
        return 0;
 }
 
-static void sample_summary_update(struct sample_output *out, int interval)
+static void sample_summary_update(struct sample_output *out)
 {
        sample_out.totals.rx += out->totals.rx;
        sample_out.totals.redir += out->totals.redir;
@@ -1430,12 +1433,11 @@ static void sample_summary_update(struct sample_output *out, int interval)
        sample_out.totals.drop_xmit += out->totals.drop_xmit;
        sample_out.totals.err += out->totals.err;
        sample_out.totals.xmit += out->totals.xmit;
-       sample_out.rx_cnt.pps += interval;
+       sample_out.rx_cnt.num++;
 }
 
 static void sample_stats_print(int mask, struct stats_record *cur,
-                              struct stats_record *prev, char *prog_name,
-                              int interval)
+                              struct stats_record *prev, char *prog_name)
 {
        struct sample_output out = {};
 
@@ -1452,7 +1454,7 @@ static void sample_stats_print(int mask, struct stats_record *cur,
        else if (mask & SAMPLE_DEVMAP_XMIT_CNT_MULTI)
                stats_get_devmap_xmit_multi(cur, prev, 0, &out,
                                            mask & SAMPLE_DEVMAP_XMIT_CNT);
-       sample_summary_update(&out, interval);
+       sample_summary_update(&out);
 
        stats_print(prog_name, mask, cur, prev, &out);
 }
@@ -1495,7 +1497,7 @@ static void swap(struct stats_record **a, struct stats_record **b)
 }
 
 static int sample_timer_cb(int timerfd, struct stats_record **rec,
-                          struct stats_record **prev, int interval)
+                          struct stats_record **prev)
 {
        char line[64] = "Summary";
        int ret;
@@ -1524,7 +1526,7 @@ static int sample_timer_cb(int timerfd, struct stats_record **rec,
                snprintf(line, sizeof(line), "%s->%s", f ?: "?", t ?: "?");
        }
 
-       sample_stats_print(sample_mask, *rec, *prev, line, interval);
+       sample_stats_print(sample_mask, *rec, *prev, line);
        return 0;
 }
 
@@ -1579,7 +1581,7 @@ int sample_run(int interval, void (*post_cb)(void *), void *ctx)
                if (pfd[0].revents & POLLIN)
                        ret = sample_signal_cb();
                else if (pfd[1].revents & POLLIN)
-                       ret = sample_timer_cb(timerfd, &rec, &prev, interval);
+                       ret = sample_timer_cb(timerfd, &rec, &prev);
 
                if (ret)
                        break;
index e8a3f85..b9198e2 100644 (file)
@@ -3,7 +3,7 @@
 obj-$(CONFIG_SAMPLE_FTRACE_DIRECT) += ftrace-direct.o
 obj-$(CONFIG_SAMPLE_FTRACE_DIRECT) += ftrace-direct-too.o
 obj-$(CONFIG_SAMPLE_FTRACE_DIRECT) += ftrace-direct-modify.o
-obj-$(CONFIG_SAMPLE_FTRACE_MULTI_DIRECT) += ftrace-direct-multi.o
+obj-$(CONFIG_SAMPLE_FTRACE_DIRECT_MULTI) += ftrace-direct-multi.o
 
 CFLAGS_sample-trace-array.o := -I$(src)
 obj-$(CONFIG_SAMPLE_TRACE_ARRAY) += sample-trace-array.o
index b6d7806..2fafc9a 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/mm.h> /* for handle_mm_fault() */
 #include <linux/ftrace.h>
 #include <linux/sched/stat.h>
+#include <asm/asm-offsets.h>
 
 extern void my_direct_func(unsigned long ip);
 
@@ -14,6 +15,8 @@ void my_direct_func(unsigned long ip)
 
 extern void my_tramp(void *);
 
+#ifdef CONFIG_X86_64
+
 asm (
 "      .pushsection    .text, \"ax\", @progbits\n"
 "      .type           my_tramp, @function\n"
@@ -31,6 +34,33 @@ asm (
 "      .popsection\n"
 );
 
+#endif /* CONFIG_X86_64 */
+
+#ifdef CONFIG_S390
+
+asm (
+"      .pushsection    .text, \"ax\", @progbits\n"
+"      .type           my_tramp, @function\n"
+"      .globl          my_tramp\n"
+"   my_tramp:"
+"      lgr             %r1,%r15\n"
+"      stmg            %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n"
+"      stg             %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n"
+"      aghi            %r15,"__stringify(-STACK_FRAME_OVERHEAD)"\n"
+"      stg             %r1,"__stringify(__SF_BACKCHAIN)"(%r15)\n"
+"      lgr             %r2,%r0\n"
+"      brasl           %r14,my_direct_func\n"
+"      aghi            %r15,"__stringify(STACK_FRAME_OVERHEAD)"\n"
+"      lmg             %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n"
+"      lg              %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n"
+"      lgr             %r1,%r0\n"
+"      br              %r1\n"
+"      .size           my_tramp, .-my_tramp\n"
+"      .popsection\n"
+);
+
+#endif /* CONFIG_S390 */
+
 static struct ftrace_ops direct;
 
 static int __init ftrace_direct_multi_init(void)
index d0ce5cf..d5b5f2a 100644 (file)
 #define X86_FEATURE_XSAVEC             (10*32+ 1) /* XSAVEC instruction */
 #define X86_FEATURE_XGETBV1            (10*32+ 2) /* XGETBV with ECX = 1 instruction */
 #define X86_FEATURE_XSAVES             (10*32+ 3) /* XSAVES/XRSTORS instructions */
+#define X86_FEATURE_XFD                        (10*32+ 4) /* "" eXtended Feature Disabling */
 
 /*
  * Extended auxiliary flags: Linux defined - for features scattered in various
 /* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */
 #define X86_FEATURE_AVX_VNNI           (12*32+ 4) /* AVX VNNI instructions */
 #define X86_FEATURE_AVX512_BF16                (12*32+ 5) /* AVX512 BFLOAT16 instructions */
+#define X86_FEATURE_AMX_TILE           (18*32+24) /* AMX tile Support */
 
 /* AMD-defined CPU features, CPUID level 0x80000008 (EBX), word 13 */
 #define X86_FEATURE_CLZERO             (13*32+ 0) /* CLZERO instruction */
index 2ef1f65..5a776a0 100644 (file)
@@ -504,4 +504,8 @@ struct kvm_pmu_event_filter {
 #define KVM_PMU_EVENT_ALLOW 0
 #define KVM_PMU_EVENT_DENY 1
 
+/* for KVM_{GET,SET,HAS}_DEVICE_ATTR */
+#define KVM_VCPU_TSC_CTRL 0 /* control group for the timestamp counter (TSC) */
+#define   KVM_VCPU_TSC_OFFSET 0 /* attribute for the TSC offset */
+
 #endif /* _ASM_X86_KVM_H */
index bbd1150..8791d0e 100644 (file)
@@ -88,5 +88,4 @@ $(BPFOBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(BPFOBJ_OU
 
 $(DEFAULT_BPFTOOL): $(BPFOBJ) | $(BPFTOOL_OUTPUT)
        $(Q)$(MAKE) $(submake_extras) -C ../bpftool OUTPUT=$(BPFTOOL_OUTPUT)   \
-                   LIBBPF_OUTPUT=$(BPFOBJ_OUTPUT)                             \
-                   LIBBPF_DESTDIR=$(BPF_DESTDIR) CC=$(HOSTCC) LD=$(HOSTLD)
+                   CC=$(HOSTCC) LD=$(HOSTLD)
index 9204395..0b243ce 100644 (file)
@@ -200,7 +200,6 @@ int main(int argc, char *argv[])
        main_test_timerfd();
        main_test_stackprotector_all();
        main_test_libdw_dwarf_unwind();
-       main_test_sync_compare_and_swap(argc, argv);
        main_test_zlib();
        main_test_pthread_attr_setaffinity_np();
        main_test_pthread_barrier();
index a067410..1daa452 100644 (file)
@@ -269,6 +269,7 @@ struct kvm_xen_exit {
 #define KVM_EXIT_AP_RESET_HOLD    32
 #define KVM_EXIT_X86_BUS_LOCK     33
 #define KVM_EXIT_XEN              34
+#define KVM_EXIT_RISCV_SBI        35
 
 /* For KVM_EXIT_INTERNAL_ERROR */
 /* Emulate instruction failed. */
@@ -397,13 +398,23 @@ struct kvm_run {
                 * "ndata" is correct, that new fields are enumerated in "flags",
                 * and that each flag enumerates fields that are 64-bit aligned
                 * and sized (so that ndata+internal.data[] is valid/accurate).
+                *
+                * Space beyond the defined fields may be used to store arbitrary
+                * debug information relating to the emulation failure. It is
+                * accounted for in "ndata" but the format is unspecified and is
+                * not represented in "flags". Any such information is *not* ABI!
                 */
                struct {
                        __u32 suberror;
                        __u32 ndata;
                        __u64 flags;
-                       __u8  insn_size;
-                       __u8  insn_bytes[15];
+                       union {
+                               struct {
+                                       __u8  insn_size;
+                                       __u8  insn_bytes[15];
+                               };
+                       };
+                       /* Arbitrary debug data may follow. */
                } emulation_failure;
                /* KVM_EXIT_OSI */
                struct {
@@ -469,6 +480,13 @@ struct kvm_run {
                } msr;
                /* KVM_EXIT_XEN */
                struct kvm_xen_exit xen;
+               /* KVM_EXIT_RISCV_SBI */
+               struct {
+                       unsigned long extension_id;
+                       unsigned long function_id;
+                       unsigned long args[6];
+                       unsigned long ret[2];
+               } riscv_sbi;
                /* Fix the size of the union. */
                char padding[256];
        };
@@ -1112,6 +1130,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_BINARY_STATS_FD 203
 #define KVM_CAP_EXIT_ON_EMULATION_FAILURE 204
 #define KVM_CAP_ARM_MTE 205
+#define KVM_CAP_VM_MOVE_ENC_CONTEXT_FROM 206
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1223,11 +1242,16 @@ struct kvm_irqfd {
 
 /* Do not use 1, KVM_CHECK_EXTENSION returned it before we had flags.  */
 #define KVM_CLOCK_TSC_STABLE           2
+#define KVM_CLOCK_REALTIME             (1 << 2)
+#define KVM_CLOCK_HOST_TSC             (1 << 3)
 
 struct kvm_clock_data {
        __u64 clock;
        __u32 flags;
-       __u32 pad[9];
+       __u32 pad0;
+       __u64 realtime;
+       __u64 host_tsc;
+       __u32 pad[4];
 };
 
 /* For KVM_CAP_SW_TLB */
index d26e547..6f3df00 100644 (file)
@@ -45,8 +45,8 @@ struct bpf_gen {
        int nr_fd_array;
 };
 
-void bpf_gen__init(struct bpf_gen *gen, int log_level);
-int bpf_gen__finish(struct bpf_gen *gen);
+void bpf_gen__init(struct bpf_gen *gen, int log_level, int nr_progs, int nr_maps);
+int bpf_gen__finish(struct bpf_gen *gen, int nr_progs, int nr_maps);
 void bpf_gen__free(struct bpf_gen *gen);
 void bpf_gen__load_btf(struct bpf_gen *gen, const void *raw_data, __u32 raw_size);
 void bpf_gen__map_create(struct bpf_gen *gen, struct bpf_create_map_params *map_attr, int map_idx);
index 502dea5..9934851 100644 (file)
@@ -18,7 +18,7 @@
 #define MAX_USED_MAPS  64
 #define MAX_USED_PROGS 32
 #define MAX_KFUNC_DESCS 256
-#define MAX_FD_ARRAY_SZ (MAX_USED_PROGS + MAX_KFUNC_DESCS)
+#define MAX_FD_ARRAY_SZ (MAX_USED_MAPS + MAX_KFUNC_DESCS)
 
 /* The following structure describes the stack layout of the loader program.
  * In addition R6 contains the pointer to context.
@@ -33,8 +33,8 @@
  */
 struct loader_stack {
        __u32 btf_fd;
-       __u32 prog_fd[MAX_USED_PROGS];
        __u32 inner_map_fd;
+       __u32 prog_fd[MAX_USED_PROGS];
 };
 
 #define stack_off(field) \
@@ -42,6 +42,11 @@ struct loader_stack {
 
 #define attr_field(attr, field) (attr + offsetof(union bpf_attr, field))
 
+static int blob_fd_array_off(struct bpf_gen *gen, int index)
+{
+       return gen->fd_array + index * sizeof(int);
+}
+
 static int realloc_insn_buf(struct bpf_gen *gen, __u32 size)
 {
        size_t off = gen->insn_cur - gen->insn_start;
@@ -102,11 +107,15 @@ static void emit2(struct bpf_gen *gen, struct bpf_insn insn1, struct bpf_insn in
        emit(gen, insn2);
 }
 
-void bpf_gen__init(struct bpf_gen *gen, int log_level)
+static int add_data(struct bpf_gen *gen, const void *data, __u32 size);
+static void emit_sys_close_blob(struct bpf_gen *gen, int blob_off);
+
+void bpf_gen__init(struct bpf_gen *gen, int log_level, int nr_progs, int nr_maps)
 {
-       size_t stack_sz = sizeof(struct loader_stack);
+       size_t stack_sz = sizeof(struct loader_stack), nr_progs_sz;
        int i;
 
+       gen->fd_array = add_data(gen, NULL, MAX_FD_ARRAY_SZ * sizeof(int));
        gen->log_level = log_level;
        /* save ctx pointer into R6 */
        emit(gen, BPF_MOV64_REG(BPF_REG_6, BPF_REG_1));
@@ -118,19 +127,27 @@ void bpf_gen__init(struct bpf_gen *gen, int log_level)
        emit(gen, BPF_MOV64_IMM(BPF_REG_3, 0));
        emit(gen, BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel));
 
+       /* amount of stack actually used, only used to calculate iterations, not stack offset */
+       nr_progs_sz = offsetof(struct loader_stack, prog_fd[nr_progs]);
        /* jump over cleanup code */
        emit(gen, BPF_JMP_IMM(BPF_JA, 0, 0,
-                             /* size of cleanup code below */
-                             (stack_sz / 4) * 3 + 2));
+                             /* size of cleanup code below (including map fd cleanup) */
+                             (nr_progs_sz / 4) * 3 + 2 +
+                             /* 6 insns for emit_sys_close_blob,
+                              * 6 insns for debug_regs in emit_sys_close_blob
+                              */
+                             nr_maps * (6 + (gen->log_level ? 6 : 0))));
 
        /* remember the label where all error branches will jump to */
        gen->cleanup_label = gen->insn_cur - gen->insn_start;
        /* emit cleanup code: close all temp FDs */
-       for (i = 0; i < stack_sz; i += 4) {
+       for (i = 0; i < nr_progs_sz; i += 4) {
                emit(gen, BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_10, -stack_sz + i));
                emit(gen, BPF_JMP_IMM(BPF_JSLE, BPF_REG_1, 0, 1));
                emit(gen, BPF_EMIT_CALL(BPF_FUNC_sys_close));
        }
+       for (i = 0; i < nr_maps; i++)
+               emit_sys_close_blob(gen, blob_fd_array_off(gen, i));
        /* R7 contains the error code from sys_bpf. Copy it into R0 and exit. */
        emit(gen, BPF_MOV64_REG(BPF_REG_0, BPF_REG_7));
        emit(gen, BPF_EXIT_INSN());
@@ -160,8 +177,6 @@ static int add_data(struct bpf_gen *gen, const void *data, __u32 size)
  */
 static int add_map_fd(struct bpf_gen *gen)
 {
-       if (!gen->fd_array)
-               gen->fd_array = add_data(gen, NULL, MAX_FD_ARRAY_SZ * sizeof(int));
        if (gen->nr_maps == MAX_USED_MAPS) {
                pr_warn("Total maps exceeds %d\n", MAX_USED_MAPS);
                gen->error = -E2BIG;
@@ -174,8 +189,6 @@ static int add_kfunc_btf_fd(struct bpf_gen *gen)
 {
        int cur;
 
-       if (!gen->fd_array)
-               gen->fd_array = add_data(gen, NULL, MAX_FD_ARRAY_SZ * sizeof(int));
        if (gen->nr_fd_array == MAX_KFUNC_DESCS) {
                cur = add_data(gen, NULL, sizeof(int));
                return (cur - gen->fd_array) / sizeof(int);
@@ -183,11 +196,6 @@ static int add_kfunc_btf_fd(struct bpf_gen *gen)
        return MAX_USED_MAPS + gen->nr_fd_array++;
 }
 
-static int blob_fd_array_off(struct bpf_gen *gen, int index)
-{
-       return gen->fd_array + index * sizeof(int);
-}
-
 static int insn_bytes_to_bpf_size(__u32 sz)
 {
        switch (sz) {
@@ -359,10 +367,15 @@ static void emit_sys_close_blob(struct bpf_gen *gen, int blob_off)
        __emit_sys_close(gen);
 }
 
-int bpf_gen__finish(struct bpf_gen *gen)
+int bpf_gen__finish(struct bpf_gen *gen, int nr_progs, int nr_maps)
 {
        int i;
 
+       if (nr_progs != gen->nr_progs || nr_maps != gen->nr_maps) {
+               pr_warn("progs/maps mismatch\n");
+               gen->error = -EFAULT;
+               return gen->error;
+       }
        emit_sys_close_stack(gen, stack_off(btf_fd));
        for (i = 0; i < gen->nr_progs; i++)
                move_stack2ctx(gen,
index a1bea19..7c74342 100644 (file)
@@ -7258,7 +7258,7 @@ int bpf_object__load_xattr(struct bpf_object_load_attr *attr)
        }
 
        if (obj->gen_loader)
-               bpf_gen__init(obj->gen_loader, attr->log_level);
+               bpf_gen__init(obj->gen_loader, attr->log_level, obj->nr_programs, obj->nr_maps);
 
        err = bpf_object__probe_loading(obj);
        err = err ? : bpf_object__load_vmlinux_btf(obj, false);
@@ -7277,7 +7277,7 @@ int bpf_object__load_xattr(struct bpf_object_load_attr *attr)
                for (i = 0; i < obj->nr_maps; i++)
                        obj->maps[i].fd = -1;
                if (!err)
-                       err = bpf_gen__finish(obj->gen_loader);
+                       err = bpf_gen__finish(obj->gen_loader, obj->nr_programs, obj->nr_maps);
        }
 
        /* clean up fd_array */
index 07e65a0..afd1447 100644 (file)
@@ -1010,6 +1010,9 @@ ifndef NO_AUXTRACE
   ifndef NO_AUXTRACE
     $(call detected,CONFIG_AUXTRACE)
     CFLAGS += -DHAVE_AUXTRACE_SUPPORT
+    ifeq ($(feature-reallocarray), 0)
+      CFLAGS += -DCOMPAT_NEED_REALLOCARRAY
+    endif
   endif
 endif
 
index 1ca7bc3..e2c481f 100644 (file)
 446    n64     landlock_restrict_self          sys_landlock_restrict_self
 # 447 reserved for memfd_secret
 448    n64     process_mrelease                sys_process_mrelease
+449    n64     futex_waitv                     sys_futex_waitv
index 488f6e6..fa0ff4c 100644 (file)
@@ -223,6 +223,8 @@ static unsigned int group(pthread_t *pth,
                snd_ctx->out_fds[i] = fds[1];
                if (!thread_mode)
                        close(fds[0]);
+
+               free(ctx);
        }
 
        /* Now we have all the fds, fork the senders */
@@ -239,6 +241,8 @@ static unsigned int group(pthread_t *pth,
                for (i = 0; i < num_fds; i++)
                        close(snd_ctx->out_fds[i]);
 
+       free(snd_ctx);
+
        /* Return number of children to reap */
        return num_fds * 2;
 }
index 8167ebf..8ae4004 100644 (file)
@@ -619,14 +619,17 @@ static int report__browse_hists(struct report *rep)
        int ret;
        struct perf_session *session = rep->session;
        struct evlist *evlist = session->evlist;
-       const char *help = perf_tip(system_path(TIPDIR));
+       char *help = NULL, *path = NULL;
 
-       if (help == NULL) {
+       path = system_path(TIPDIR);
+       if (perf_tip(&help, path) || help == NULL) {
                /* fallback for people who don't install perf ;-) */
-               help = perf_tip(DOCDIR);
-               if (help == NULL)
-                       help = "Cannot load tips.txt file, please install perf!";
+               free(path);
+               path = system_path(DOCDIR);
+               if (perf_tip(&help, path) || help == NULL)
+                       help = strdup("Cannot load tips.txt file, please install perf!");
        }
+       free(path);
 
        switch (use_browser) {
        case 1:
@@ -651,7 +654,7 @@ static int report__browse_hists(struct report *rep)
                ret = evlist__tty_browse_hists(evlist, rep, help);
                break;
        }
-
+       free(help);
        return ret;
 }
 
index fbb68de..d01532d 100644 (file)
@@ -88,7 +88,6 @@ static int test__event_update(struct test_suite *test __maybe_unused, int subtes
        struct evsel *evsel;
        struct event_name tmp;
        struct evlist *evlist = evlist__new_default();
-       char *unit = strdup("KRAVA");
 
        TEST_ASSERT_VAL("failed to get evlist", evlist);
 
@@ -99,7 +98,8 @@ static int test__event_update(struct test_suite *test __maybe_unused, int subtes
 
        perf_evlist__id_add(&evlist->core, &evsel->core, 0, 0, 123);
 
-       evsel->unit = unit;
+       free((char *)evsel->unit);
+       evsel->unit = strdup("KRAVA");
 
        TEST_ASSERT_VAL("failed to synthesize attr update unit",
                        !perf_event__synthesize_event_update_unit(NULL, evsel, process_event_unit));
@@ -119,7 +119,6 @@ static int test__event_update(struct test_suite *test __maybe_unused, int subtes
        TEST_ASSERT_VAL("failed to synthesize attr update cpus",
                        !perf_event__synthesize_event_update_cpus(&tmp.tool, evsel, process_event_cpus));
 
-       free(unit);
        evlist__delete(evlist);
        return 0;
 }
index b669d22..07f2411 100644 (file)
@@ -36,7 +36,7 @@
  * These are based on the input value (213) specified
  * in branch_stack variable.
  */
-#define BS_EXPECTED_BE 0xa00d000000000000
+#define BS_EXPECTED_BE 0xa000d00000000000
 #define BS_EXPECTED_LE 0xd5000000
 #define FLAG(s)        s->branch_stack->entries[i].flags
 
index 820d942..9d4c451 100644 (file)
@@ -21,6 +21,7 @@ do {                                            \
 volatile u64 data1;
 volatile u8 data2[3];
 
+#ifndef __s390x__
 static int wp_read(int fd, long long *count, int size)
 {
        int ret = read(fd, count, size);
@@ -48,7 +49,6 @@ static void get__perf_event_attr(struct perf_event_attr *attr, int wp_type,
        attr->exclude_hv     = 1;
 }
 
-#ifndef __s390x__
 static int __event(int wp_type, void *wp_addr, unsigned long wp_len)
 {
        int fd;
index c1f24d0..5075ece 100644 (file)
@@ -535,6 +535,18 @@ struct perf_hpp_list perf_hpp_list = {
 #undef __HPP_SORT_ACC_FN
 #undef __HPP_SORT_RAW_FN
 
+static void fmt_free(struct perf_hpp_fmt *fmt)
+{
+       /*
+        * At this point fmt should be completely
+        * unhooked, if not it's a bug.
+        */
+       BUG_ON(!list_empty(&fmt->list));
+       BUG_ON(!list_empty(&fmt->sort_list));
+
+       if (fmt->free)
+               fmt->free(fmt);
+}
 
 void perf_hpp__init(void)
 {
@@ -598,9 +610,10 @@ void perf_hpp_list__prepend_sort_field(struct perf_hpp_list *list,
        list_add(&format->sort_list, &list->sorts);
 }
 
-void perf_hpp__column_unregister(struct perf_hpp_fmt *format)
+static void perf_hpp__column_unregister(struct perf_hpp_fmt *format)
 {
        list_del_init(&format->list);
+       fmt_free(format);
 }
 
 void perf_hpp__cancel_cumulate(void)
@@ -672,19 +685,6 @@ next:
 }
 
 
-static void fmt_free(struct perf_hpp_fmt *fmt)
-{
-       /*
-        * At this point fmt should be completely
-        * unhooked, if not it's a bug.
-        */
-       BUG_ON(!list_empty(&fmt->list));
-       BUG_ON(!list_empty(&fmt->sort_list));
-
-       if (fmt->free)
-               fmt->free(fmt);
-}
-
 void perf_hpp__reset_output_field(struct perf_hpp_list *list)
 {
        struct perf_hpp_fmt *fmt, *tmp;
index 4748bcf..fccac06 100644 (file)
@@ -51,6 +51,7 @@ struct arm_spe {
        u8                              timeless_decoding;
        u8                              data_queued;
 
+       u64                             sample_type;
        u8                              sample_flc;
        u8                              sample_llc;
        u8                              sample_tlb;
@@ -287,6 +288,12 @@ static void arm_spe_prep_sample(struct arm_spe *spe,
        event->sample.header.size = sizeof(struct perf_event_header);
 }
 
+static int arm_spe__inject_event(union perf_event *event, struct perf_sample *sample, u64 type)
+{
+       event->header.size = perf_event__sample_event_size(sample, type, 0);
+       return perf_event__synthesize_sample(event, type, 0, sample);
+}
+
 static inline int
 arm_spe_deliver_synth_event(struct arm_spe *spe,
                            struct arm_spe_queue *speq __maybe_unused,
@@ -295,6 +302,12 @@ arm_spe_deliver_synth_event(struct arm_spe *spe,
 {
        int ret;
 
+       if (spe->synth_opts.inject) {
+               ret = arm_spe__inject_event(event, sample, spe->sample_type);
+               if (ret)
+                       return ret;
+       }
+
        ret = perf_session__deliver_synth_event(spe->session, event, sample);
        if (ret)
                pr_err("ARM SPE: failed to deliver event, error %d\n", ret);
@@ -986,6 +999,8 @@ arm_spe_synth_events(struct arm_spe *spe, struct perf_session *session)
        else
                attr.sample_type |= PERF_SAMPLE_TIME;
 
+       spe->sample_type = attr.sample_type;
+
        attr.exclude_user = evsel->core.attr.exclude_user;
        attr.exclude_kernel = evsel->core.attr.exclude_kernel;
        attr.exclude_hv = evsel->core.attr.exclude_hv;
index a59fb2e..ac0127b 100644 (file)
@@ -241,7 +241,7 @@ void evsel__init(struct evsel *evsel,
 {
        perf_evsel__init(&evsel->core, attr, idx);
        evsel->tracking    = !idx;
-       evsel->unit        = "";
+       evsel->unit        = strdup("");
        evsel->scale       = 1.0;
        evsel->max_events  = ULONG_MAX;
        evsel->evlist      = NULL;
@@ -276,13 +276,8 @@ struct evsel *evsel__new_idx(struct perf_event_attr *attr, int idx)
        }
 
        if (evsel__is_clock(evsel)) {
-               /*
-                * The evsel->unit points to static alias->unit
-                * so it's ok to use static string in here.
-                */
-               static const char *unit = "msec";
-
-               evsel->unit = unit;
+               free((char *)evsel->unit);
+               evsel->unit = strdup("msec");
                evsel->scale = 1e-6;
        }
 
@@ -420,7 +415,11 @@ struct evsel *evsel__clone(struct evsel *orig)
 
        evsel->max_events = orig->max_events;
        evsel->tool_event = orig->tool_event;
-       evsel->unit = orig->unit;
+       free((char *)evsel->unit);
+       evsel->unit = strdup(orig->unit);
+       if (evsel->unit == NULL)
+               goto out_err;
+
        evsel->scale = orig->scale;
        evsel->snapshot = orig->snapshot;
        evsel->per_pkg = orig->per_pkg;
@@ -1441,6 +1440,7 @@ void evsel__exit(struct evsel *evsel)
        zfree(&evsel->group_name);
        zfree(&evsel->name);
        zfree(&evsel->pmu_name);
+       zfree(&evsel->unit);
        zfree(&evsel->metric_id);
        evsel__zero_per_pkg(evsel);
        hashmap__free(evsel->per_pkg_mask);
index fda8d14..79cce21 100644 (file)
@@ -4257,9 +4257,11 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
 
        switch (ev->type) {
        case PERF_EVENT_UPDATE__UNIT:
+               free((char *)evsel->unit);
                evsel->unit = strdup(ev->data);
                break;
        case PERF_EVENT_UPDATE__NAME:
+               free(evsel->name);
                evsel->name = strdup(ev->data);
                break;
        case PERF_EVENT_UPDATE__SCALE:
@@ -4268,11 +4270,11 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
                break;
        case PERF_EVENT_UPDATE__CPUS:
                ev_cpus = (struct perf_record_event_update_cpus *)ev->data;
-
                map = cpu_map__new_data(&ev_cpus->cpus);
-               if (map)
+               if (map) {
+                       perf_cpu_map__put(evsel->core.own_cpus);
                        evsel->core.own_cpus = map;
-               else
+               else
                        pr_err("failed to get event_update cpus\n");
        default:
                break;
index 65fe65b..b776465 100644 (file)
@@ -289,15 +289,10 @@ static long hist_time(unsigned long htime)
        return htime;
 }
 
-static void he_stat__add_period(struct he_stat *he_stat, u64 period,
-                               u64 weight, u64 ins_lat, u64 p_stage_cyc)
+static void he_stat__add_period(struct he_stat *he_stat, u64 period)
 {
-
        he_stat->period         += period;
-       he_stat->weight         += weight;
        he_stat->nr_events      += 1;
-       he_stat->ins_lat        += ins_lat;
-       he_stat->p_stage_cyc    += p_stage_cyc;
 }
 
 static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src)
@@ -308,9 +303,6 @@ static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src)
        dest->period_guest_sys  += src->period_guest_sys;
        dest->period_guest_us   += src->period_guest_us;
        dest->nr_events         += src->nr_events;
-       dest->weight            += src->weight;
-       dest->ins_lat           += src->ins_lat;
-       dest->p_stage_cyc               += src->p_stage_cyc;
 }
 
 static void he_stat__decay(struct he_stat *he_stat)
@@ -598,9 +590,6 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists,
        struct hist_entry *he;
        int64_t cmp;
        u64 period = entry->stat.period;
-       u64 weight = entry->stat.weight;
-       u64 ins_lat = entry->stat.ins_lat;
-       u64 p_stage_cyc = entry->stat.p_stage_cyc;
        bool leftmost = true;
 
        p = &hists->entries_in->rb_root.rb_node;
@@ -619,11 +608,11 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists,
 
                if (!cmp) {
                        if (sample_self) {
-                               he_stat__add_period(&he->stat, period, weight, ins_lat, p_stage_cyc);
+                               he_stat__add_period(&he->stat, period);
                                hist_entry__add_callchain_period(he, period);
                        }
                        if (symbol_conf.cumulate_callchain)
-                               he_stat__add_period(he->stat_acc, period, weight, ins_lat, p_stage_cyc);
+                               he_stat__add_period(he->stat_acc, period);
 
                        /*
                         * This mem info was allocated from sample__resolve_mem
@@ -733,9 +722,6 @@ __hists__add_entry(struct hists *hists,
                .stat = {
                        .nr_events = 1,
                        .period = sample->period,
-                       .weight = sample->weight,
-                       .ins_lat = sample->ins_lat,
-                       .p_stage_cyc = sample->p_stage_cyc,
                },
                .parent = sym_parent,
                .filtered = symbol__parent_filter(sym_parent) | al->filtered,
@@ -748,6 +734,9 @@ __hists__add_entry(struct hists *hists,
                .raw_size = sample->raw_size,
                .ops = ops,
                .time = hist_time(sample->time),
+               .weight = sample->weight,
+               .ins_lat = sample->ins_lat,
+               .p_stage_cyc = sample->p_stage_cyc,
        }, *he = hists__findnew_entry(hists, &entry, al, sample_self);
 
        if (!hists->has_callchains && he && he->callchain_size != 0)
index 5343b62..621f35a 100644 (file)
@@ -369,7 +369,6 @@ enum {
 };
 
 void perf_hpp__init(void);
-void perf_hpp__column_unregister(struct perf_hpp_fmt *format);
 void perf_hpp__cancel_cumulate(void);
 void perf_hpp__setup_output_field(struct perf_hpp_list *list);
 void perf_hpp__reset_output_field(struct perf_hpp_list *list);
index 5bfb6f8..ba74fdf 100644 (file)
@@ -402,8 +402,10 @@ static int add_event_tool(struct list_head *list, int *idx,
        if (!evsel)
                return -ENOMEM;
        evsel->tool_event = tool_event;
-       if (tool_event == PERF_TOOL_DURATION_TIME)
-               evsel->unit = "ns";
+       if (tool_event == PERF_TOOL_DURATION_TIME) {
+               free((char *)evsel->unit);
+               evsel->unit = strdup("ns");
+       }
        return 0;
 }
 
@@ -1630,7 +1632,8 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
        if (parse_state->fake_pmu)
                return 0;
 
-       evsel->unit = info.unit;
+       free((char *)evsel->unit);
+       evsel->unit = strdup(info.unit);
        evsel->scale = info.scale;
        evsel->per_pkg = info.per_pkg;
        evsel->snapshot = info.snapshot;
index 568a88c..a111065 100644 (file)
@@ -1325,88 +1325,68 @@ struct sort_entry sort_mispredict = {
        .se_width_idx   = HISTC_MISPREDICT,
 };
 
-static u64 he_weight(struct hist_entry *he)
-{
-       return he->stat.nr_events ? he->stat.weight / he->stat.nr_events : 0;
-}
-
 static int64_t
-sort__local_weight_cmp(struct hist_entry *left, struct hist_entry *right)
+sort__weight_cmp(struct hist_entry *left, struct hist_entry *right)
 {
-       return he_weight(left) - he_weight(right);
+       return left->weight - right->weight;
 }
 
 static int hist_entry__local_weight_snprintf(struct hist_entry *he, char *bf,
                                    size_t size, unsigned int width)
 {
-       return repsep_snprintf(bf, size, "%-*llu", width, he_weight(he));
+       return repsep_snprintf(bf, size, "%-*llu", width, he->weight);
 }
 
 struct sort_entry sort_local_weight = {
        .se_header      = "Local Weight",
-       .se_cmp         = sort__local_weight_cmp,
+       .se_cmp         = sort__weight_cmp,
        .se_snprintf    = hist_entry__local_weight_snprintf,
        .se_width_idx   = HISTC_LOCAL_WEIGHT,
 };
 
-static int64_t
-sort__global_weight_cmp(struct hist_entry *left, struct hist_entry *right)
-{
-       return left->stat.weight - right->stat.weight;
-}
-
 static int hist_entry__global_weight_snprintf(struct hist_entry *he, char *bf,
                                              size_t size, unsigned int width)
 {
-       return repsep_snprintf(bf, size, "%-*llu", width, he->stat.weight);
+       return repsep_snprintf(bf, size, "%-*llu", width,
+                              he->weight * he->stat.nr_events);
 }
 
 struct sort_entry sort_global_weight = {
        .se_header      = "Weight",
-       .se_cmp         = sort__global_weight_cmp,
+       .se_cmp         = sort__weight_cmp,
        .se_snprintf    = hist_entry__global_weight_snprintf,
        .se_width_idx   = HISTC_GLOBAL_WEIGHT,
 };
 
-static u64 he_ins_lat(struct hist_entry *he)
-{
-               return he->stat.nr_events ? he->stat.ins_lat / he->stat.nr_events : 0;
-}
-
 static int64_t
-sort__local_ins_lat_cmp(struct hist_entry *left, struct hist_entry *right)
+sort__ins_lat_cmp(struct hist_entry *left, struct hist_entry *right)
 {
-               return he_ins_lat(left) - he_ins_lat(right);
+       return left->ins_lat - right->ins_lat;
 }
 
 static int hist_entry__local_ins_lat_snprintf(struct hist_entry *he, char *bf,
                                              size_t size, unsigned int width)
 {
-               return repsep_snprintf(bf, size, "%-*u", width, he_ins_lat(he));
+       return repsep_snprintf(bf, size, "%-*u", width, he->ins_lat);
 }
 
 struct sort_entry sort_local_ins_lat = {
        .se_header      = "Local INSTR Latency",
-       .se_cmp         = sort__local_ins_lat_cmp,
+       .se_cmp         = sort__ins_lat_cmp,
        .se_snprintf    = hist_entry__local_ins_lat_snprintf,
        .se_width_idx   = HISTC_LOCAL_INS_LAT,
 };
 
-static int64_t
-sort__global_ins_lat_cmp(struct hist_entry *left, struct hist_entry *right)
-{
-               return left->stat.ins_lat - right->stat.ins_lat;
-}
-
 static int hist_entry__global_ins_lat_snprintf(struct hist_entry *he, char *bf,
                                               size_t size, unsigned int width)
 {
-               return repsep_snprintf(bf, size, "%-*u", width, he->stat.ins_lat);
+       return repsep_snprintf(bf, size, "%-*u", width,
+                              he->ins_lat * he->stat.nr_events);
 }
 
 struct sort_entry sort_global_ins_lat = {
        .se_header      = "INSTR Latency",
-       .se_cmp         = sort__global_ins_lat_cmp,
+       .se_cmp         = sort__ins_lat_cmp,
        .se_snprintf    = hist_entry__global_ins_lat_snprintf,
        .se_width_idx   = HISTC_GLOBAL_INS_LAT,
 };
@@ -1414,13 +1394,13 @@ struct sort_entry sort_global_ins_lat = {
 static int64_t
 sort__global_p_stage_cyc_cmp(struct hist_entry *left, struct hist_entry *right)
 {
-       return left->stat.p_stage_cyc - right->stat.p_stage_cyc;
+       return left->p_stage_cyc - right->p_stage_cyc;
 }
 
 static int hist_entry__p_stage_cyc_snprintf(struct hist_entry *he, char *bf,
                                        size_t size, unsigned int width)
 {
-       return repsep_snprintf(bf, size, "%-*u", width, he->stat.p_stage_cyc);
+       return repsep_snprintf(bf, size, "%-*u", width, he->p_stage_cyc);
 }
 
 struct sort_entry sort_p_stage_cyc = {
index b67c469..7b71455 100644 (file)
@@ -49,9 +49,6 @@ struct he_stat {
        u64                     period_us;
        u64                     period_guest_sys;
        u64                     period_guest_us;
-       u64                     weight;
-       u64                     ins_lat;
-       u64                     p_stage_cyc;
        u32                     nr_events;
 };
 
@@ -109,6 +106,9 @@ struct hist_entry {
        s32                     socket;
        s32                     cpu;
        u64                     code_page_size;
+       u64                     weight;
+       u64                     ins_lat;
+       u64                     p_stage_cyc;
        u8                      cpumode;
        u8                      depth;
 
index 37a9492..df3c467 100644 (file)
@@ -379,32 +379,32 @@ fetch_kernel_version(unsigned int *puint, char *str,
        return 0;
 }
 
-const char *perf_tip(const char *dirpath)
+int perf_tip(char **strp, const char *dirpath)
 {
        struct strlist *tips;
        struct str_node *node;
-       char *tip = NULL;
        struct strlist_config conf = {
                .dirname = dirpath,
                .file_only = true,
        };
+       int ret = 0;
 
+       *strp = NULL;
        tips = strlist__new("tips.txt", &conf);
        if (tips == NULL)
-               return errno == ENOENT ? NULL :
-                       "Tip: check path of tips.txt or get more memory! ;-p";
+               return -errno;
 
        if (strlist__nr_entries(tips) == 0)
                goto out;
 
        node = strlist__entry(tips, random() % strlist__nr_entries(tips));
-       if (asprintf(&tip, "Tip: %s", node->s) < 0)
-               tip = (char *)"Tip: get more memory! ;-)";
+       if (asprintf(strp, "Tip: %s", node->s) < 0)
+               ret = -ENOMEM;
 
 out:
        strlist__delete(tips);
 
-       return tip;
+       return ret;
 }
 
 char *perf_exe(char *buf, int len)
index ad73705..9f0d36b 100644 (file)
@@ -39,7 +39,7 @@ int fetch_kernel_version(unsigned int *puint,
 #define KVER_FMT       "%d.%d.%d"
 #define KVER_PARAM(x)  KVER_VERSION(x), KVER_PATCHLEVEL(x), KVER_SUBLEVEL(x)
 
-const char *perf_tip(const char *dirpath);
+int perf_tip(char **strp, const char *dirpath);
 
 #ifndef HAVE_SCHED_GETCPU_SUPPORT
 int sched_getcpu(void);
index 54b0a41..62fafbe 100644 (file)
@@ -187,7 +187,7 @@ DEFAULT_BPFTOOL := $(HOST_SCRATCH_DIR)/sbin/bpftool
 $(OUTPUT)/runqslower: $(BPFOBJ) | $(DEFAULT_BPFTOOL) $(RUNQSLOWER_OUTPUT)
        $(Q)$(MAKE) $(submake_extras) -C $(TOOLSDIR)/bpf/runqslower            \
                    OUTPUT=$(RUNQSLOWER_OUTPUT) VMLINUX_BTF=$(VMLINUX_BTF)     \
-                   BPFTOOL_OUTPUT=$(BUILD_DIR)/bpftool/                       \
+                   BPFTOOL_OUTPUT=$(HOST_BUILD_DIR)/bpftool/                  \
                    BPFOBJ_OUTPUT=$(BUILD_DIR)/libbpf                          \
                    BPFOBJ=$(BPFOBJ) BPF_INCLUDE=$(INCLUDE_DIR) &&             \
                    cp $(RUNQSLOWER_OUTPUT)runqslower $@
diff --git a/tools/testing/selftests/bpf/prog_tests/helper_restricted.c b/tools/testing/selftests/bpf/prog_tests/helper_restricted.c
new file mode 100644 (file)
index 0000000..e1de5f8
--- /dev/null
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <test_progs.h>
+#include "test_helper_restricted.skel.h"
+
+void test_helper_restricted(void)
+{
+       int prog_i = 0, prog_cnt;
+       int duration = 0;
+
+       do {
+               struct test_helper_restricted *test;
+               int maybeOK;
+
+               test = test_helper_restricted__open();
+               if (!ASSERT_OK_PTR(test, "open"))
+                       return;
+
+               prog_cnt = test->skeleton->prog_cnt;
+
+               for (int j = 0; j < prog_cnt; ++j) {
+                       struct bpf_program *prog = *test->skeleton->progs[j].prog;
+
+                       maybeOK = bpf_program__set_autoload(prog, prog_i == j);
+                       ASSERT_OK(maybeOK, "set autoload");
+               }
+
+               maybeOK = test_helper_restricted__load(test);
+               CHECK(!maybeOK, test->skeleton->progs[prog_i].name, "helper isn't restricted");
+
+               test_helper_restricted__destroy(test);
+       } while (++prog_i < prog_cnt);
+}
diff --git a/tools/testing/selftests/bpf/progs/test_helper_restricted.c b/tools/testing/selftests/bpf/progs/test_helper_restricted.c
new file mode 100644 (file)
index 0000000..68d64c3
--- /dev/null
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <time.h>
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+
+struct timer {
+       struct bpf_timer t;
+};
+
+struct lock {
+       struct bpf_spin_lock l;
+};
+
+struct {
+       __uint(type, BPF_MAP_TYPE_ARRAY);
+       __uint(max_entries, 1);
+       __type(key, __u32);
+       __type(value, struct timer);
+} timers SEC(".maps");
+
+struct {
+       __uint(type, BPF_MAP_TYPE_ARRAY);
+       __uint(max_entries, 1);
+       __type(key, __u32);
+       __type(value, struct lock);
+} locks SEC(".maps");
+
+static int timer_cb(void *map, int *key, struct timer *timer)
+{
+       return 0;
+}
+
+static void timer_work(void)
+{
+       struct timer *timer;
+       const int key = 0;
+
+       timer  = bpf_map_lookup_elem(&timers, &key);
+       if (timer) {
+               bpf_timer_init(&timer->t, &timers, CLOCK_MONOTONIC);
+               bpf_timer_set_callback(&timer->t, timer_cb);
+               bpf_timer_start(&timer->t, 10E9, 0);
+               bpf_timer_cancel(&timer->t);
+       }
+}
+
+static void spin_lock_work(void)
+{
+       const int key = 0;
+       struct lock *lock;
+
+       lock = bpf_map_lookup_elem(&locks, &key);
+       if (lock) {
+               bpf_spin_lock(&lock->l);
+               bpf_spin_unlock(&lock->l);
+       }
+}
+
+SEC("raw_tp/sys_enter")
+int raw_tp_timer(void *ctx)
+{
+       timer_work();
+
+       return 0;
+}
+
+SEC("tp/syscalls/sys_enter_nanosleep")
+int tp_timer(void *ctx)
+{
+       timer_work();
+
+       return 0;
+}
+
+SEC("kprobe/sys_nanosleep")
+int kprobe_timer(void *ctx)
+{
+       timer_work();
+
+       return 0;
+}
+
+SEC("perf_event")
+int perf_event_timer(void *ctx)
+{
+       timer_work();
+
+       return 0;
+}
+
+SEC("raw_tp/sys_enter")
+int raw_tp_spin_lock(void *ctx)
+{
+       spin_lock_work();
+
+       return 0;
+}
+
+SEC("tp/syscalls/sys_enter_nanosleep")
+int tp_spin_lock(void *ctx)
+{
+       spin_lock_work();
+
+       return 0;
+}
+
+SEC("kprobe/sys_nanosleep")
+int kprobe_spin_lock(void *ctx)
+{
+       spin_lock_work();
+
+       return 0;
+}
+
+SEC("perf_event")
+int perf_event_spin_lock(void *ctx)
+{
+       spin_lock_work();
+
+       return 0;
+}
+
+const char LICENSE[] SEC("license") = "GPL";
index 25afe42..465ef3f 100644 (file)
@@ -92,6 +92,7 @@ struct bpf_test {
        int fixup_map_event_output[MAX_FIXUPS];
        int fixup_map_reuseport_array[MAX_FIXUPS];
        int fixup_map_ringbuf[MAX_FIXUPS];
+       int fixup_map_timer[MAX_FIXUPS];
        /* Expected verifier log output for result REJECT or VERBOSE_ACCEPT.
         * Can be a tab-separated sequence of expected strings. An empty string
         * means no log verification.
@@ -604,8 +605,15 @@ static int create_cgroup_storage(bool percpu)
  *   int cnt;
  *   struct bpf_spin_lock l;
  * };
+ * struct bpf_timer {
+ *   __u64 :64;
+ *   __u64 :64;
+ * } __attribute__((aligned(8)));
+ * struct timer {
+ *   struct bpf_timer t;
+ * };
  */
-static const char btf_str_sec[] = "\0bpf_spin_lock\0val\0cnt\0l";
+static const char btf_str_sec[] = "\0bpf_spin_lock\0val\0cnt\0l\0bpf_timer\0timer\0t";
 static __u32 btf_raw_types[] = {
        /* int */
        BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
@@ -616,6 +624,11 @@ static __u32 btf_raw_types[] = {
        BTF_TYPE_ENC(15, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 8),
        BTF_MEMBER_ENC(19, 1, 0), /* int cnt; */
        BTF_MEMBER_ENC(23, 2, 32),/* struct bpf_spin_lock l; */
+       /* struct bpf_timer */                          /* [4] */
+       BTF_TYPE_ENC(25, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 0), 16),
+       /* struct timer */                              /* [5] */
+       BTF_TYPE_ENC(35, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), 16),
+       BTF_MEMBER_ENC(41, 4, 0), /* struct bpf_timer t; */
 };
 
 static int load_btf(void)
@@ -696,6 +709,29 @@ static int create_sk_storage_map(void)
        return fd;
 }
 
+static int create_map_timer(void)
+{
+       struct bpf_create_map_attr attr = {
+               .name = "test_map",
+               .map_type = BPF_MAP_TYPE_ARRAY,
+               .key_size = 4,
+               .value_size = 16,
+               .max_entries = 1,
+               .btf_key_type_id = 1,
+               .btf_value_type_id = 5,
+       };
+       int fd, btf_fd;
+
+       btf_fd = load_btf();
+       if (btf_fd < 0)
+               return -1;
+       attr.btf_fd = btf_fd;
+       fd = bpf_create_map_xattr(&attr);
+       if (fd < 0)
+               printf("Failed to create map with timer\n");
+       return fd;
+}
+
 static char bpf_vlog[UINT_MAX >> 8];
 
 static void do_test_fixup(struct bpf_test *test, enum bpf_prog_type prog_type,
@@ -722,6 +758,7 @@ static void do_test_fixup(struct bpf_test *test, enum bpf_prog_type prog_type,
        int *fixup_map_event_output = test->fixup_map_event_output;
        int *fixup_map_reuseport_array = test->fixup_map_reuseport_array;
        int *fixup_map_ringbuf = test->fixup_map_ringbuf;
+       int *fixup_map_timer = test->fixup_map_timer;
 
        if (test->fill_helper) {
                test->fill_insns = calloc(MAX_TEST_INSNS, sizeof(struct bpf_insn));
@@ -907,6 +944,13 @@ static void do_test_fixup(struct bpf_test *test, enum bpf_prog_type prog_type,
                        fixup_map_ringbuf++;
                } while (*fixup_map_ringbuf);
        }
+       if (*fixup_map_timer) {
+               map_fds[21] = create_map_timer();
+               do {
+                       prog[*fixup_map_timer].imm = map_fds[21];
+                       fixup_map_timer++;
+               } while (*fixup_map_timer);
+       }
 }
 
 struct libcap {
diff --git a/tools/testing/selftests/bpf/verifier/helper_restricted.c b/tools/testing/selftests/bpf/verifier/helper_restricted.c
new file mode 100644 (file)
index 0000000..a067b70
--- /dev/null
@@ -0,0 +1,196 @@
+{
+       "bpf_ktime_get_coarse_ns is forbidden in BPF_PROG_TYPE_KPROBE",
+       .insns = {
+               BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_ktime_get_coarse_ns),
+               BPF_MOV64_IMM(BPF_REG_0, 0),
+               BPF_EXIT_INSN(),
+       },
+       .errstr = "unknown func bpf_ktime_get_coarse_ns",
+       .result = REJECT,
+       .prog_type = BPF_PROG_TYPE_KPROBE,
+},
+{
+       "bpf_ktime_get_coarse_ns is forbidden in BPF_PROG_TYPE_TRACEPOINT",
+       .insns = {
+               BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_ktime_get_coarse_ns),
+               BPF_MOV64_IMM(BPF_REG_0, 0),
+               BPF_EXIT_INSN(),
+       },
+       .errstr = "unknown func bpf_ktime_get_coarse_ns",
+       .result = REJECT,
+       .prog_type = BPF_PROG_TYPE_TRACEPOINT,
+},
+{
+       "bpf_ktime_get_coarse_ns is forbidden in BPF_PROG_TYPE_PERF_EVENT",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_ktime_get_coarse_ns),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .errstr = "unknown func bpf_ktime_get_coarse_ns",
+       .result = REJECT,
+       .prog_type = BPF_PROG_TYPE_PERF_EVENT,
+},
+{
+       "bpf_ktime_get_coarse_ns is forbidden in BPF_PROG_TYPE_RAW_TRACEPOINT",
+       .insns = {
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_ktime_get_coarse_ns),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .errstr = "unknown func bpf_ktime_get_coarse_ns",
+       .result = REJECT,
+       .prog_type = BPF_PROG_TYPE_RAW_TRACEPOINT,
+},
+{
+       "bpf_timer_init isn restricted in BPF_PROG_TYPE_KPROBE",
+       .insns = {
+       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+       BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
+       BPF_LD_MAP_FD(BPF_REG_1, 0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_LD_MAP_FD(BPF_REG_2, 0),
+       BPF_MOV64_IMM(BPF_REG_3, 1),
+       BPF_EMIT_CALL(BPF_FUNC_timer_init),
+       BPF_EXIT_INSN(),
+       },
+       .fixup_map_timer = { 3, 8 },
+       .errstr = "tracing progs cannot use bpf_timer yet",
+       .result = REJECT,
+       .prog_type = BPF_PROG_TYPE_KPROBE,
+},
+{
+       "bpf_timer_init is forbidden in BPF_PROG_TYPE_PERF_EVENT",
+       .insns = {
+       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+       BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
+       BPF_LD_MAP_FD(BPF_REG_1, 0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_LD_MAP_FD(BPF_REG_2, 0),
+       BPF_MOV64_IMM(BPF_REG_3, 1),
+       BPF_EMIT_CALL(BPF_FUNC_timer_init),
+       BPF_EXIT_INSN(),
+       },
+       .fixup_map_timer = { 3, 8 },
+       .errstr = "tracing progs cannot use bpf_timer yet",
+       .result = REJECT,
+       .prog_type = BPF_PROG_TYPE_PERF_EVENT,
+},
+{
+       "bpf_timer_init is forbidden in BPF_PROG_TYPE_TRACEPOINT",
+       .insns = {
+       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+       BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
+       BPF_LD_MAP_FD(BPF_REG_1, 0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_LD_MAP_FD(BPF_REG_2, 0),
+       BPF_MOV64_IMM(BPF_REG_3, 1),
+       BPF_EMIT_CALL(BPF_FUNC_timer_init),
+       BPF_EXIT_INSN(),
+       },
+       .fixup_map_timer = { 3, 8 },
+       .errstr = "tracing progs cannot use bpf_timer yet",
+       .result = REJECT,
+       .prog_type = BPF_PROG_TYPE_TRACEPOINT,
+},
+{
+       "bpf_timer_init is forbidden in BPF_PROG_TYPE_RAW_TRACEPOINT",
+       .insns = {
+       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+       BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
+       BPF_LD_MAP_FD(BPF_REG_1, 0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_LD_MAP_FD(BPF_REG_2, 0),
+       BPF_MOV64_IMM(BPF_REG_3, 1),
+       BPF_EMIT_CALL(BPF_FUNC_timer_init),
+       BPF_EXIT_INSN(),
+       },
+       .fixup_map_timer = { 3, 8 },
+       .errstr = "tracing progs cannot use bpf_timer yet",
+       .result = REJECT,
+       .prog_type = BPF_PROG_TYPE_RAW_TRACEPOINT,
+},
+{
+       "bpf_spin_lock is forbidden in BPF_PROG_TYPE_KPROBE",
+       .insns = {
+       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+       BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
+       BPF_LD_MAP_FD(BPF_REG_1, 0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_EMIT_CALL(BPF_FUNC_spin_lock),
+       BPF_EXIT_INSN(),
+       },
+       .fixup_map_spin_lock = { 3 },
+       .errstr = "tracing progs cannot use bpf_spin_lock yet",
+       .result = REJECT,
+       .prog_type = BPF_PROG_TYPE_KPROBE,
+},
+{
+       "bpf_spin_lock is forbidden in BPF_PROG_TYPE_TRACEPOINT",
+       .insns = {
+       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+       BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
+       BPF_LD_MAP_FD(BPF_REG_1, 0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_EMIT_CALL(BPF_FUNC_spin_lock),
+       BPF_EXIT_INSN(),
+       },
+       .fixup_map_spin_lock = { 3 },
+       .errstr = "tracing progs cannot use bpf_spin_lock yet",
+       .result = REJECT,
+       .prog_type = BPF_PROG_TYPE_TRACEPOINT,
+},
+{
+       "bpf_spin_lock is forbidden in BPF_PROG_TYPE_PERF_EVENT",
+       .insns = {
+       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+       BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
+       BPF_LD_MAP_FD(BPF_REG_1, 0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_EMIT_CALL(BPF_FUNC_spin_lock),
+       BPF_EXIT_INSN(),
+       },
+       .fixup_map_spin_lock = { 3 },
+       .errstr = "tracing progs cannot use bpf_spin_lock yet",
+       .result = REJECT,
+       .prog_type = BPF_PROG_TYPE_PERF_EVENT,
+},
+{
+       "bpf_spin_lock is forbidden in BPF_PROG_TYPE_RAW_TRACEPOINT",
+       .insns = {
+       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+       BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
+       BPF_LD_MAP_FD(BPF_REG_1, 0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_EMIT_CALL(BPF_FUNC_spin_lock),
+       BPF_EXIT_INSN(),
+       },
+       .fixup_map_spin_lock = { 3 },
+       .errstr = "tracing progs cannot use bpf_spin_lock yet",
+       .result = REJECT,
+       .prog_type = BPF_PROG_TYPE_RAW_TRACEPOINT,
+},
index 2798927..128a348 100644 (file)
        .result = ACCEPT,
 },
 {
+       "map in map state pruning",
+       .insns = {
+       BPF_ST_MEM(0, BPF_REG_10, -4, 0),
+       BPF_MOV64_REG(BPF_REG_6, BPF_REG_10),
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -4),
+       BPF_MOV64_REG(BPF_REG_2, BPF_REG_6),
+       BPF_LD_MAP_FD(BPF_REG_1, 0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
+       BPF_EXIT_INSN(),
+       BPF_MOV64_REG(BPF_REG_2, BPF_REG_6),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 11),
+       BPF_MOV64_REG(BPF_REG_2, BPF_REG_6),
+       BPF_LD_MAP_FD(BPF_REG_1, 0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
+       BPF_EXIT_INSN(),
+       BPF_MOV64_REG(BPF_REG_2, BPF_REG_6),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
+       BPF_EXIT_INSN(),
+       BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .fixup_map_in_map = { 4, 14 },
+       .flags = BPF_F_TEST_STATE_FREQ,
+       .result = VERBOSE_ACCEPT,
+       .errstr = "processed 25 insns",
+       .prog_type = BPF_PROG_TYPE_XDP,
+},
+{
        "invalid inner map pointer",
        .insns = {
        BPF_ST_MEM(0, BPF_REG_10, -4, 0),
index 39f2bbe..d7b312b 100644 (file)
@@ -3,5 +3,6 @@
 TEST_PROGS := gpio-mockup.sh
 TEST_FILES := gpio-mockup-sysfs.sh
 TEST_GEN_PROGS_EXTENDED := gpio-mockup-cdev
+CFLAGS += -O2 -g -Wall -I../../../../usr/include/
 
 include ../lib.mk
index e83eac7..d1640f4 100644 (file)
@@ -117,7 +117,7 @@ int main(int argc, char *argv[])
 {
        char *chip;
        int opt, ret, cfd, lfd;
-       unsigned int offset, val, abiv;
+       unsigned int offset, val = 0, abiv;
        uint32_t flags_v1;
        uint64_t flags_v2;
 
index d4a8301..3763105 100644 (file)
@@ -23,6 +23,7 @@
 /x86_64/platform_info_test
 /x86_64/set_boot_cpu_id
 /x86_64/set_sregs_test
+/x86_64/sev_migrate_tests
 /x86_64/smm_test
 /x86_64/state_test
 /x86_64/svm_vmcall_test
index 5d95113..d890903 100644 (file)
@@ -47,7 +47,7 @@
 #include "guest_modes.h"
 
 /* Global variable used to synchronize all of the vCPU threads. */
-static int iteration = -1;
+static int iteration;
 
 /* Defines what vCPU threads should do during a given iteration. */
 static enum {
@@ -215,12 +215,11 @@ static bool spin_wait_for_next_iteration(int *current_iteration)
        return true;
 }
 
-static void *vcpu_thread_main(void *arg)
+static void vcpu_thread_main(struct perf_test_vcpu_args *vcpu_args)
 {
-       struct perf_test_vcpu_args *vcpu_args = arg;
        struct kvm_vm *vm = perf_test_args.vm;
        int vcpu_id = vcpu_args->vcpu_id;
-       int current_iteration = -1;
+       int current_iteration = 0;
 
        while (spin_wait_for_next_iteration(&current_iteration)) {
                switch (READ_ONCE(iteration_work)) {
@@ -235,8 +234,6 @@ static void *vcpu_thread_main(void *arg)
 
                vcpu_last_completed_iteration[vcpu_id] = current_iteration;
        }
-
-       return NULL;
 }
 
 static void spin_wait_for_vcpu(int vcpu_id, int target_iteration)
@@ -277,8 +274,7 @@ static void run_iteration(struct kvm_vm *vm, int vcpus, const char *description)
 static void access_memory(struct kvm_vm *vm, int vcpus, enum access_type access,
                          const char *description)
 {
-       perf_test_args.wr_fract = (access == ACCESS_READ) ? INT_MAX : 1;
-       sync_global_to_guest(vm, perf_test_args);
+       perf_test_set_wr_fract(vm, (access == ACCESS_READ) ? INT_MAX : 1);
        iteration_work = ITERATION_ACCESS_MEMORY;
        run_iteration(vm, vcpus, description);
 }
@@ -296,48 +292,16 @@ static void mark_memory_idle(struct kvm_vm *vm, int vcpus)
        run_iteration(vm, vcpus, "Mark memory idle");
 }
 
-static pthread_t *create_vcpu_threads(int vcpus)
-{
-       pthread_t *vcpu_threads;
-       int i;
-
-       vcpu_threads = malloc(vcpus * sizeof(vcpu_threads[0]));
-       TEST_ASSERT(vcpu_threads, "Failed to allocate vcpu_threads.");
-
-       for (i = 0; i < vcpus; i++) {
-               vcpu_last_completed_iteration[i] = iteration;
-               pthread_create(&vcpu_threads[i], NULL, vcpu_thread_main,
-                              &perf_test_args.vcpu_args[i]);
-       }
-
-       return vcpu_threads;
-}
-
-static void terminate_vcpu_threads(pthread_t *vcpu_threads, int vcpus)
-{
-       int i;
-
-       /* Set done to signal the vCPU threads to exit */
-       done = true;
-
-       for (i = 0; i < vcpus; i++)
-               pthread_join(vcpu_threads[i], NULL);
-}
-
 static void run_test(enum vm_guest_mode mode, void *arg)
 {
        struct test_params *params = arg;
        struct kvm_vm *vm;
-       pthread_t *vcpu_threads;
        int vcpus = params->vcpus;
 
        vm = perf_test_create_vm(mode, vcpus, params->vcpu_memory_bytes, 1,
-                                params->backing_src);
+                                params->backing_src, !overlap_memory_access);
 
-       perf_test_setup_vcpus(vm, vcpus, params->vcpu_memory_bytes,
-                             !overlap_memory_access);
-
-       vcpu_threads = create_vcpu_threads(vcpus);
+       perf_test_start_vcpu_threads(vcpus, vcpu_thread_main);
 
        pr_info("\n");
        access_memory(vm, vcpus, ACCESS_WRITE, "Populating memory");
@@ -352,8 +316,10 @@ static void run_test(enum vm_guest_mode mode, void *arg)
        mark_memory_idle(vm, vcpus);
        access_memory(vm, vcpus, ACCESS_READ, "Reading from idle memory");
 
-       terminate_vcpu_threads(vcpu_threads, vcpus);
-       free(vcpu_threads);
+       /* Set done to signal the vCPU threads to exit */
+       done = true;
+
+       perf_test_join_vcpu_threads(vcpus);
        perf_test_destroy_vm(vm);
 }
 
index 1510b21..6a719d0 100644 (file)
@@ -42,10 +42,9 @@ static uint64_t guest_percpu_mem_size = DEFAULT_PER_VCPU_MEM_SIZE;
 static size_t demand_paging_size;
 static char *guest_data_prototype;
 
-static void *vcpu_worker(void *data)
+static void vcpu_worker(struct perf_test_vcpu_args *vcpu_args)
 {
        int ret;
-       struct perf_test_vcpu_args *vcpu_args = (struct perf_test_vcpu_args *)data;
        int vcpu_id = vcpu_args->vcpu_id;
        struct kvm_vm *vm = perf_test_args.vm;
        struct kvm_run *run;
@@ -68,8 +67,6 @@ static void *vcpu_worker(void *data)
        ts_diff = timespec_elapsed(start);
        PER_VCPU_DEBUG("vCPU %d execution time: %ld.%.9lds\n", vcpu_id,
                       ts_diff.tv_sec, ts_diff.tv_nsec);
-
-       return NULL;
 }
 
 static int handle_uffd_page_request(int uffd_mode, int uffd, uint64_t addr)
@@ -282,7 +279,6 @@ struct test_params {
 static void run_test(enum vm_guest_mode mode, void *arg)
 {
        struct test_params *p = arg;
-       pthread_t *vcpu_threads;
        pthread_t *uffd_handler_threads = NULL;
        struct uffd_handler_args *uffd_args = NULL;
        struct timespec start;
@@ -293,9 +289,7 @@ static void run_test(enum vm_guest_mode mode, void *arg)
        int r;
 
        vm = perf_test_create_vm(mode, nr_vcpus, guest_percpu_mem_size, 1,
-                                p->src_type);
-
-       perf_test_args.wr_fract = 1;
+                                p->src_type, p->partition_vcpu_memory_access);
 
        demand_paging_size = get_backing_src_pagesz(p->src_type);
 
@@ -304,12 +298,6 @@ static void run_test(enum vm_guest_mode mode, void *arg)
                    "Failed to allocate buffer for guest data pattern");
        memset(guest_data_prototype, 0xAB, demand_paging_size);
 
-       vcpu_threads = malloc(nr_vcpus * sizeof(*vcpu_threads));
-       TEST_ASSERT(vcpu_threads, "Memory allocation failed");
-
-       perf_test_setup_vcpus(vm, nr_vcpus, guest_percpu_mem_size,
-                             p->partition_vcpu_memory_access);
-
        if (p->uffd_mode) {
                uffd_handler_threads =
                        malloc(nr_vcpus * sizeof(*uffd_handler_threads));
@@ -322,26 +310,15 @@ static void run_test(enum vm_guest_mode mode, void *arg)
                TEST_ASSERT(pipefds, "Unable to allocate memory for pipefd");
 
                for (vcpu_id = 0; vcpu_id < nr_vcpus; vcpu_id++) {
-                       vm_paddr_t vcpu_gpa;
+                       struct perf_test_vcpu_args *vcpu_args;
                        void *vcpu_hva;
                        void *vcpu_alias;
-                       uint64_t vcpu_mem_size;
-
 
-                       if (p->partition_vcpu_memory_access) {
-                               vcpu_gpa = guest_test_phys_mem +
-                                          (vcpu_id * guest_percpu_mem_size);
-                               vcpu_mem_size = guest_percpu_mem_size;
-                       } else {
-                               vcpu_gpa = guest_test_phys_mem;
-                               vcpu_mem_size = guest_percpu_mem_size * nr_vcpus;
-                       }
-                       PER_VCPU_DEBUG("Added VCPU %d with test mem gpa [%lx, %lx)\n",
-                                      vcpu_id, vcpu_gpa, vcpu_gpa + vcpu_mem_size);
+                       vcpu_args = &perf_test_args.vcpu_args[vcpu_id];
 
                        /* Cache the host addresses of the region */
-                       vcpu_hva = addr_gpa2hva(vm, vcpu_gpa);
-                       vcpu_alias = addr_gpa2alias(vm, vcpu_gpa);
+                       vcpu_hva = addr_gpa2hva(vm, vcpu_args->gpa);
+                       vcpu_alias = addr_gpa2alias(vm, vcpu_args->gpa);
 
                        /*
                         * Set up user fault fd to handle demand paging
@@ -355,32 +332,18 @@ static void run_test(enum vm_guest_mode mode, void *arg)
                                            pipefds[vcpu_id * 2], p->uffd_mode,
                                            p->uffd_delay, &uffd_args[vcpu_id],
                                            vcpu_hva, vcpu_alias,
-                                           vcpu_mem_size);
+                                           vcpu_args->pages * perf_test_args.guest_page_size);
                }
        }
 
-       /* Export the shared variables to the guest */
-       sync_global_to_guest(vm, perf_test_args);
-
        pr_info("Finished creating vCPUs and starting uffd threads\n");
 
        clock_gettime(CLOCK_MONOTONIC, &start);
-
-       for (vcpu_id = 0; vcpu_id < nr_vcpus; vcpu_id++) {
-               pthread_create(&vcpu_threads[vcpu_id], NULL, vcpu_worker,
-                              &perf_test_args.vcpu_args[vcpu_id]);
-       }
-
+       perf_test_start_vcpu_threads(nr_vcpus, vcpu_worker);
        pr_info("Started all vCPUs\n");
 
-       /* Wait for the vcpu threads to quit */
-       for (vcpu_id = 0; vcpu_id < nr_vcpus; vcpu_id++) {
-               pthread_join(vcpu_threads[vcpu_id], NULL);
-               PER_VCPU_DEBUG("Joined thread for vCPU %d\n", vcpu_id);
-       }
-
+       perf_test_join_vcpu_threads(nr_vcpus);
        ts_diff = timespec_elapsed(start);
-
        pr_info("All vCPU threads joined\n");
 
        if (p->uffd_mode) {
@@ -404,7 +367,6 @@ static void run_test(enum vm_guest_mode mode, void *arg)
        perf_test_destroy_vm(vm);
 
        free(guest_data_prototype);
-       free(vcpu_threads);
        if (p->uffd_mode) {
                free(uffd_handler_threads);
                free(uffd_args);
index 7ffab5b..1954b96 100644 (file)
@@ -31,7 +31,7 @@ static bool host_quit;
 static int iteration;
 static int vcpu_last_completed_iteration[KVM_MAX_VCPUS];
 
-static void *vcpu_worker(void *data)
+static void vcpu_worker(struct perf_test_vcpu_args *vcpu_args)
 {
        int ret;
        struct kvm_vm *vm = perf_test_args.vm;
@@ -41,7 +41,6 @@ static void *vcpu_worker(void *data)
        struct timespec ts_diff;
        struct timespec total = (struct timespec){0};
        struct timespec avg;
-       struct perf_test_vcpu_args *vcpu_args = (struct perf_test_vcpu_args *)data;
        int vcpu_id = vcpu_args->vcpu_id;
 
        run = vcpu_state(vm, vcpu_id);
@@ -83,8 +82,6 @@ static void *vcpu_worker(void *data)
        pr_debug("\nvCPU %d dirtied 0x%lx pages over %d iterations in %ld.%.9lds. (Avg %ld.%.9lds/iteration)\n",
                vcpu_id, pages_count, vcpu_last_completed_iteration[vcpu_id],
                total.tv_sec, total.tv_nsec, avg.tv_sec, avg.tv_nsec);
-
-       return NULL;
 }
 
 struct test_params {
@@ -170,7 +167,6 @@ static void free_bitmaps(unsigned long *bitmaps[], int slots)
 static void run_test(enum vm_guest_mode mode, void *arg)
 {
        struct test_params *p = arg;
-       pthread_t *vcpu_threads;
        struct kvm_vm *vm;
        unsigned long **bitmaps;
        uint64_t guest_num_pages;
@@ -186,9 +182,10 @@ static void run_test(enum vm_guest_mode mode, void *arg)
        struct timespec clear_dirty_log_total = (struct timespec){0};
 
        vm = perf_test_create_vm(mode, nr_vcpus, guest_percpu_mem_size,
-                                p->slots, p->backing_src);
+                                p->slots, p->backing_src,
+                                p->partition_vcpu_memory_access);
 
-       perf_test_args.wr_fract = p->wr_fract;
+       perf_test_set_wr_fract(vm, p->wr_fract);
 
        guest_num_pages = (nr_vcpus * guest_percpu_mem_size) >> vm_get_page_shift(vm);
        guest_num_pages = vm_adjust_num_guest_pages(mode, guest_num_pages);
@@ -203,25 +200,15 @@ static void run_test(enum vm_guest_mode mode, void *arg)
                vm_enable_cap(vm, &cap);
        }
 
-       vcpu_threads = malloc(nr_vcpus * sizeof(*vcpu_threads));
-       TEST_ASSERT(vcpu_threads, "Memory allocation failed");
-
-       perf_test_setup_vcpus(vm, nr_vcpus, guest_percpu_mem_size,
-                             p->partition_vcpu_memory_access);
-
-       sync_global_to_guest(vm, perf_test_args);
-
        /* Start the iterations */
        iteration = 0;
        host_quit = false;
 
        clock_gettime(CLOCK_MONOTONIC, &start);
-       for (vcpu_id = 0; vcpu_id < nr_vcpus; vcpu_id++) {
+       for (vcpu_id = 0; vcpu_id < nr_vcpus; vcpu_id++)
                vcpu_last_completed_iteration[vcpu_id] = -1;
 
-               pthread_create(&vcpu_threads[vcpu_id], NULL, vcpu_worker,
-                              &perf_test_args.vcpu_args[vcpu_id]);
-       }
+       perf_test_start_vcpu_threads(nr_vcpus, vcpu_worker);
 
        /* Allow the vCPUs to populate memory */
        pr_debug("Starting iteration %d - Populating\n", iteration);
@@ -290,8 +277,7 @@ static void run_test(enum vm_guest_mode mode, void *arg)
 
        /* Tell the vcpu thread to quit */
        host_quit = true;
-       for (vcpu_id = 0; vcpu_id < nr_vcpus; vcpu_id++)
-               pthread_join(vcpu_threads[vcpu_id], NULL);
+       perf_test_join_vcpu_threads(nr_vcpus);
 
        avg = timespec_div(get_dirty_log_total, p->iterations);
        pr_info("Get dirty log over %lu iterations took %ld.%.9lds. (Avg %ld.%.9lds/iteration)\n",
@@ -306,7 +292,6 @@ static void run_test(enum vm_guest_mode mode, void *arg)
        }
 
        free_bitmaps(bitmaps, p->slots);
-       free(vcpu_threads);
        perf_test_destroy_vm(vm);
 }
 
index 792c60e..3fcd89e 100644 (file)
@@ -115,7 +115,7 @@ static void guest_code(void)
                        addr = guest_test_virt_mem;
                        addr += (READ_ONCE(random_array[i]) % guest_num_pages)
                                * guest_page_size;
-                       addr &= ~(host_page_size - 1);
+                       addr = align_down(addr, host_page_size);
                        *(uint64_t *)addr = READ_ONCE(iteration);
                }
 
@@ -737,14 +737,14 @@ static void run_test(enum vm_guest_mode mode, void *arg)
        if (!p->phys_offset) {
                guest_test_phys_mem = (vm_get_max_gfn(vm) -
                                       guest_num_pages) * guest_page_size;
-               guest_test_phys_mem &= ~(host_page_size - 1);
+               guest_test_phys_mem = align_down(guest_test_phys_mem, host_page_size);
        } else {
                guest_test_phys_mem = p->phys_offset;
        }
 
 #ifdef __s390x__
        /* Align to 1M (segment size) */
-       guest_test_phys_mem &= ~((1 << 20) - 1);
+       guest_test_phys_mem = align_down(guest_test_phys_mem, 1 << 20);
 #endif
 
        pr_info("guest physical test memory offset: 0x%lx\n", guest_test_phys_mem);
index df9f1a3..a86f953 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef SELFTEST_KVM_PERF_TEST_UTIL_H
 #define SELFTEST_KVM_PERF_TEST_UTIL_H
 
+#include <pthread.h>
+
 #include "kvm_util.h"
 
 /* Default guest test virtual memory offset */
@@ -18,6 +20,7 @@
 #define PERF_TEST_MEM_SLOT_INDEX       1
 
 struct perf_test_vcpu_args {
+       uint64_t gpa;
        uint64_t gva;
        uint64_t pages;
 
@@ -27,7 +30,7 @@ struct perf_test_vcpu_args {
 
 struct perf_test_args {
        struct kvm_vm *vm;
-       uint64_t host_page_size;
+       uint64_t gpa;
        uint64_t guest_page_size;
        int wr_fract;
 
@@ -36,19 +39,15 @@ struct perf_test_args {
 
 extern struct perf_test_args perf_test_args;
 
-/*
- * Guest physical memory offset of the testing memory slot.
- * This will be set to the topmost valid physical address minus
- * the test memory size.
- */
-extern uint64_t guest_test_phys_mem;
-
 struct kvm_vm *perf_test_create_vm(enum vm_guest_mode mode, int vcpus,
                                   uint64_t vcpu_memory_bytes, int slots,
-                                  enum vm_mem_backing_src_type backing_src);
+                                  enum vm_mem_backing_src_type backing_src,
+                                  bool partition_vcpu_memory_access);
 void perf_test_destroy_vm(struct kvm_vm *vm);
-void perf_test_setup_vcpus(struct kvm_vm *vm, int vcpus,
-                          uint64_t vcpu_memory_bytes,
-                          bool partition_vcpu_memory_access);
+
+void perf_test_set_wr_fract(struct kvm_vm *vm, int wr_fract);
+
+void perf_test_start_vcpu_threads(int vcpus, void (*vcpu_fn)(struct perf_test_vcpu_args *));
+void perf_test_join_vcpu_threads(int vcpus);
 
 #endif /* SELFTEST_KVM_PERF_TEST_UTIL_H */
index f8fddc8..99e0dcd 100644 (file)
@@ -104,6 +104,7 @@ size_t get_trans_hugepagesz(void);
 size_t get_def_hugetlb_pagesz(void);
 const struct vm_mem_backing_src_alias *vm_mem_backing_src_alias(uint32_t i);
 size_t get_backing_src_pagesz(uint32_t i);
+bool is_backing_src_hugetlb(uint32_t i);
 void backing_src_help(const char *flag);
 enum vm_mem_backing_src_type parse_backing_src_type(const char *type_name);
 long get_run_delay(void);
@@ -117,4 +118,29 @@ static inline bool backing_src_is_shared(enum vm_mem_backing_src_type t)
        return vm_mem_backing_src_alias(t)->flag & MAP_SHARED;
 }
 
+/* Aligns x up to the next multiple of size. Size must be a power of 2. */
+static inline uint64_t align_up(uint64_t x, uint64_t size)
+{
+       uint64_t mask = size - 1;
+
+       TEST_ASSERT(size != 0 && !(size & (size - 1)),
+                   "size not a power of 2: %lu", size);
+       return ((x + mask) & ~mask);
+}
+
+static inline uint64_t align_down(uint64_t x, uint64_t size)
+{
+       uint64_t x_aligned_up = align_up(x, size);
+
+       if (x == x_aligned_up)
+               return x;
+       else
+               return x_aligned_up - size;
+}
+
+static inline void *align_ptr_up(void *x, size_t size)
+{
+       return (void *)align_up((unsigned long)x, size);
+}
+
 #endif /* SELFTEST_KVM_TEST_UTIL_H */
index 36407cb..3836322 100644 (file)
@@ -280,7 +280,7 @@ static struct kvm_vm *pre_init_before_test(enum vm_guest_mode mode, void *arg)
 #ifdef __s390x__
        alignment = max(0x100000, alignment);
 #endif
-       guest_test_phys_mem &= ~(alignment - 1);
+       guest_test_phys_mem = align_down(guest_test_virt_mem, alignment);
 
        /* Set up the shared data structure test_args */
        test_args.vm = vm;
index eac44f5..13e8e3d 100644 (file)
@@ -157,8 +157,7 @@ void kvm_vm_elf_load(struct kvm_vm *vm, const char *filename)
                        "memsize of 0,\n"
                        "  phdr index: %u p_memsz: 0x%" PRIx64,
                        n1, (uint64_t) phdr.p_memsz);
-               vm_vaddr_t seg_vstart = phdr.p_vaddr;
-               seg_vstart &= ~(vm_vaddr_t)(vm->page_size - 1);
+               vm_vaddr_t seg_vstart = align_down(phdr.p_vaddr, vm->page_size);
                vm_vaddr_t seg_vend = phdr.p_vaddr + phdr.p_memsz - 1;
                seg_vend |= vm->page_size - 1;
                size_t seg_size = seg_vend - seg_vstart + 1;
index 14bb4d5..8f2e0bb 100644 (file)
 
 static int vcpu_mmap_sz(void);
 
-/* Aligns x up to the next multiple of size. Size must be a power of 2. */
-static void *align(void *x, size_t size)
-{
-       size_t mask = size - 1;
-       TEST_ASSERT(size != 0 && !(size & (size - 1)),
-                   "size not a power of 2: %lu", size);
-       return (void *) (((size_t) x + mask) & ~mask);
-}
-
 int open_path_or_exit(const char *path, int flags)
 {
        int fd;
@@ -191,15 +182,15 @@ const char *vm_guest_mode_string(uint32_t i)
 }
 
 const struct vm_guest_mode_params vm_guest_mode_params[] = {
-       { 52, 48,  0x1000, 12 },
-       { 52, 48, 0x10000, 16 },
-       { 48, 48,  0x1000, 12 },
-       { 48, 48, 0x10000, 16 },
-       { 40, 48,  0x1000, 12 },
-       { 40, 48, 0x10000, 16 },
-       {  0,  0,  0x1000, 12 },
-       { 47, 64,  0x1000, 12 },
-       { 44, 64,  0x1000, 12 },
+       [VM_MODE_P52V48_4K]     = { 52, 48,  0x1000, 12 },
+       [VM_MODE_P52V48_64K]    = { 52, 48, 0x10000, 16 },
+       [VM_MODE_P48V48_4K]     = { 48, 48,  0x1000, 12 },
+       [VM_MODE_P48V48_64K]    = { 48, 48, 0x10000, 16 },
+       [VM_MODE_P40V48_4K]     = { 40, 48,  0x1000, 12 },
+       [VM_MODE_P40V48_64K]    = { 40, 48, 0x10000, 16 },
+       [VM_MODE_PXXV48_4K]     = {  0,  0,  0x1000, 12 },
+       [VM_MODE_P47V64_4K]     = { 47, 64,  0x1000, 12 },
+       [VM_MODE_P44V64_4K]     = { 44, 64,  0x1000, 12 },
 };
 _Static_assert(sizeof(vm_guest_mode_params)/sizeof(struct vm_guest_mode_params) == NUM_VM_MODES,
               "Missing new mode params?");
@@ -879,9 +870,17 @@ void vm_userspace_mem_region_add(struct kvm_vm *vm,
        alignment = 1;
 #endif
 
+       /*
+        * When using THP mmap is not guaranteed to returned a hugepage aligned
+        * address so we have to pad the mmap. Padding is not needed for HugeTLB
+        * because mmap will always return an address aligned to the HugeTLB
+        * page size.
+        */
        if (src_type == VM_MEM_SRC_ANONYMOUS_THP)
                alignment = max(backing_src_pagesz, alignment);
 
+       ASSERT_EQ(guest_paddr, align_up(guest_paddr, backing_src_pagesz));
+
        /* Add enough memory to align up if necessary */
        if (alignment > 1)
                region->mmap_size += alignment;
@@ -914,8 +913,13 @@ void vm_userspace_mem_region_add(struct kvm_vm *vm,
                    "test_malloc failed, mmap_start: %p errno: %i",
                    region->mmap_start, errno);
 
+       TEST_ASSERT(!is_backing_src_hugetlb(src_type) ||
+                   region->mmap_start == align_ptr_up(region->mmap_start, backing_src_pagesz),
+                   "mmap_start %p is not aligned to HugeTLB page size 0x%lx",
+                   region->mmap_start, backing_src_pagesz);
+
        /* Align host address */
-       region->host_mem = align(region->mmap_start, alignment);
+       region->host_mem = align_ptr_up(region->mmap_start, alignment);
 
        /* As needed perform madvise */
        if ((src_type == VM_MEM_SRC_ANONYMOUS ||
@@ -958,7 +962,7 @@ void vm_userspace_mem_region_add(struct kvm_vm *vm,
                            "mmap of alias failed, errno: %i", errno);
 
                /* Align host alias address */
-               region->host_alias = align(region->mmap_alias, alignment);
+               region->host_alias = align_ptr_up(region->mmap_alias, alignment);
        }
 }
 
index 0ef80db..722df3a 100644 (file)
 
 struct perf_test_args perf_test_args;
 
-uint64_t guest_test_phys_mem;
-
 /*
  * Guest virtual memory offset of the testing memory slot.
  * Must not conflict with identity mapped test code.
  */
 static uint64_t guest_test_virt_mem = DEFAULT_GUEST_TEST_MEM;
 
+struct vcpu_thread {
+       /* The id of the vCPU. */
+       int vcpu_id;
+
+       /* The pthread backing the vCPU. */
+       pthread_t thread;
+
+       /* Set to true once the vCPU thread is up and running. */
+       bool running;
+};
+
+/* The vCPU threads involved in this test. */
+static struct vcpu_thread vcpu_threads[KVM_MAX_VCPUS];
+
+/* The function run by each vCPU thread, as provided by the test. */
+static void (*vcpu_thread_fn)(struct perf_test_vcpu_args *);
+
+/* Set to true once all vCPU threads are up and running. */
+static bool all_vcpu_threads_running;
+
 /*
  * Continuously write to the first 8 bytes of each page in the
  * specified region.
  */
 static void guest_code(uint32_t vcpu_id)
 {
-       struct perf_test_vcpu_args *vcpu_args = &perf_test_args.vcpu_args[vcpu_id];
+       struct perf_test_args *pta = &perf_test_args;
+       struct perf_test_vcpu_args *vcpu_args = &pta->vcpu_args[vcpu_id];
        uint64_t gva;
        uint64_t pages;
        int i;
@@ -37,9 +56,9 @@ static void guest_code(uint32_t vcpu_id)
 
        while (true) {
                for (i = 0; i < pages; i++) {
-                       uint64_t addr = gva + (i * perf_test_args.guest_page_size);
+                       uint64_t addr = gva + (i * pta->guest_page_size);
 
-                       if (i % perf_test_args.wr_fract == 0)
+                       if (i % pta->wr_fract == 0)
                                *(uint64_t *)addr = 0x0123456789ABCDEF;
                        else
                                READ_ONCE(*(uint64_t *)addr);
@@ -49,35 +68,81 @@ static void guest_code(uint32_t vcpu_id)
        }
 }
 
+void perf_test_setup_vcpus(struct kvm_vm *vm, int vcpus,
+                          uint64_t vcpu_memory_bytes,
+                          bool partition_vcpu_memory_access)
+{
+       struct perf_test_args *pta = &perf_test_args;
+       struct perf_test_vcpu_args *vcpu_args;
+       int vcpu_id;
+
+       for (vcpu_id = 0; vcpu_id < vcpus; vcpu_id++) {
+               vcpu_args = &pta->vcpu_args[vcpu_id];
+
+               vcpu_args->vcpu_id = vcpu_id;
+               if (partition_vcpu_memory_access) {
+                       vcpu_args->gva = guest_test_virt_mem +
+                                        (vcpu_id * vcpu_memory_bytes);
+                       vcpu_args->pages = vcpu_memory_bytes /
+                                          pta->guest_page_size;
+                       vcpu_args->gpa = pta->gpa + (vcpu_id * vcpu_memory_bytes);
+               } else {
+                       vcpu_args->gva = guest_test_virt_mem;
+                       vcpu_args->pages = (vcpus * vcpu_memory_bytes) /
+                                          pta->guest_page_size;
+                       vcpu_args->gpa = pta->gpa;
+               }
+
+               vcpu_args_set(vm, vcpu_id, 1, vcpu_id);
+
+               pr_debug("Added VCPU %d with test mem gpa [%lx, %lx)\n",
+                        vcpu_id, vcpu_args->gpa, vcpu_args->gpa +
+                        (vcpu_args->pages * pta->guest_page_size));
+       }
+}
+
 struct kvm_vm *perf_test_create_vm(enum vm_guest_mode mode, int vcpus,
                                   uint64_t vcpu_memory_bytes, int slots,
-                                  enum vm_mem_backing_src_type backing_src)
+                                  enum vm_mem_backing_src_type backing_src,
+                                  bool partition_vcpu_memory_access)
 {
+       struct perf_test_args *pta = &perf_test_args;
        struct kvm_vm *vm;
        uint64_t guest_num_pages;
+       uint64_t backing_src_pagesz = get_backing_src_pagesz(backing_src);
        int i;
 
        pr_info("Testing guest mode: %s\n", vm_guest_mode_string(mode));
 
-       perf_test_args.host_page_size = getpagesize();
-       perf_test_args.guest_page_size = vm_guest_mode_params[mode].page_size;
+       /* By default vCPUs will write to memory. */
+       pta->wr_fract = 1;
+
+       /*
+        * Snapshot the non-huge page size.  This is used by the guest code to
+        * access/dirty pages at the logging granularity.
+        */
+       pta->guest_page_size = vm_guest_mode_params[mode].page_size;
 
        guest_num_pages = vm_adjust_num_guest_pages(mode,
-                               (vcpus * vcpu_memory_bytes) / perf_test_args.guest_page_size);
+                               (vcpus * vcpu_memory_bytes) / pta->guest_page_size);
 
-       TEST_ASSERT(vcpu_memory_bytes % perf_test_args.host_page_size == 0,
+       TEST_ASSERT(vcpu_memory_bytes % getpagesize() == 0,
                    "Guest memory size is not host page size aligned.");
-       TEST_ASSERT(vcpu_memory_bytes % perf_test_args.guest_page_size == 0,
+       TEST_ASSERT(vcpu_memory_bytes % pta->guest_page_size == 0,
                    "Guest memory size is not guest page size aligned.");
        TEST_ASSERT(guest_num_pages % slots == 0,
                    "Guest memory cannot be evenly divided into %d slots.",
                    slots);
 
+       /*
+        * Pass guest_num_pages to populate the page tables for test memory.
+        * The memory is also added to memslot 0, but that's a benign side
+        * effect as KVM allows aliasing HVAs in meslots.
+        */
        vm = vm_create_with_vcpus(mode, vcpus, DEFAULT_GUEST_PHY_PAGES,
-                                 (vcpus * vcpu_memory_bytes) / perf_test_args.guest_page_size,
-                                 0, guest_code, NULL);
+                                 guest_num_pages, 0, guest_code, NULL);
 
-       perf_test_args.vm = vm;
+       pta->vm = vm;
 
        /*
         * If there should be more memory in the guest test region than there
@@ -90,20 +155,18 @@ struct kvm_vm *perf_test_create_vm(enum vm_guest_mode mode, int vcpus,
                    guest_num_pages, vm_get_max_gfn(vm), vcpus,
                    vcpu_memory_bytes);
 
-       guest_test_phys_mem = (vm_get_max_gfn(vm) - guest_num_pages) *
-                             perf_test_args.guest_page_size;
-       guest_test_phys_mem &= ~(perf_test_args.host_page_size - 1);
+       pta->gpa = (vm_get_max_gfn(vm) - guest_num_pages) * pta->guest_page_size;
+       pta->gpa = align_down(pta->gpa, backing_src_pagesz);
 #ifdef __s390x__
        /* Align to 1M (segment size) */
-       guest_test_phys_mem &= ~((1 << 20) - 1);
+       pta->gpa = align_down(pta->gpa, 1 << 20);
 #endif
-       pr_info("guest physical test memory offset: 0x%lx\n", guest_test_phys_mem);
+       pr_info("guest physical test memory offset: 0x%lx\n", pta->gpa);
 
        /* Add extra memory slots for testing */
        for (i = 0; i < slots; i++) {
                uint64_t region_pages = guest_num_pages / slots;
-               vm_paddr_t region_start = guest_test_phys_mem +
-                       region_pages * perf_test_args.guest_page_size * i;
+               vm_paddr_t region_start = pta->gpa + region_pages * pta->guest_page_size * i;
 
                vm_userspace_mem_region_add(vm, backing_src, region_start,
                                            PERF_TEST_MEM_SLOT_INDEX + i,
@@ -111,10 +174,15 @@ struct kvm_vm *perf_test_create_vm(enum vm_guest_mode mode, int vcpus,
        }
 
        /* Do mapping for the demand paging memory slot */
-       virt_map(vm, guest_test_virt_mem, guest_test_phys_mem, guest_num_pages);
+       virt_map(vm, guest_test_virt_mem, pta->gpa, guest_num_pages);
+
+       perf_test_setup_vcpus(vm, vcpus, vcpu_memory_bytes, partition_vcpu_memory_access);
 
        ucall_init(vm, NULL);
 
+       /* Export the shared variables to the guest. */
+       sync_global_to_guest(vm, perf_test_args);
+
        return vm;
 }
 
@@ -124,36 +192,60 @@ void perf_test_destroy_vm(struct kvm_vm *vm)
        kvm_vm_free(vm);
 }
 
-void perf_test_setup_vcpus(struct kvm_vm *vm, int vcpus,
-                          uint64_t vcpu_memory_bytes,
-                          bool partition_vcpu_memory_access)
+void perf_test_set_wr_fract(struct kvm_vm *vm, int wr_fract)
+{
+       perf_test_args.wr_fract = wr_fract;
+       sync_global_to_guest(vm, perf_test_args);
+}
+
+static void *vcpu_thread_main(void *data)
+{
+       struct vcpu_thread *vcpu = data;
+
+       WRITE_ONCE(vcpu->running, true);
+
+       /*
+        * Wait for all vCPU threads to be up and running before calling the test-
+        * provided vCPU thread function. This prevents thread creation (which
+        * requires taking the mmap_sem in write mode) from interfering with the
+        * guest faulting in its memory.
+        */
+       while (!READ_ONCE(all_vcpu_threads_running))
+               ;
+
+       vcpu_thread_fn(&perf_test_args.vcpu_args[vcpu->vcpu_id]);
+
+       return NULL;
+}
+
+void perf_test_start_vcpu_threads(int vcpus, void (*vcpu_fn)(struct perf_test_vcpu_args *))
 {
-       vm_paddr_t vcpu_gpa;
-       struct perf_test_vcpu_args *vcpu_args;
        int vcpu_id;
 
+       vcpu_thread_fn = vcpu_fn;
+       WRITE_ONCE(all_vcpu_threads_running, false);
+
        for (vcpu_id = 0; vcpu_id < vcpus; vcpu_id++) {
-               vcpu_args = &perf_test_args.vcpu_args[vcpu_id];
+               struct vcpu_thread *vcpu = &vcpu_threads[vcpu_id];
 
-               vcpu_args->vcpu_id = vcpu_id;
-               if (partition_vcpu_memory_access) {
-                       vcpu_args->gva = guest_test_virt_mem +
-                                        (vcpu_id * vcpu_memory_bytes);
-                       vcpu_args->pages = vcpu_memory_bytes /
-                                          perf_test_args.guest_page_size;
-                       vcpu_gpa = guest_test_phys_mem +
-                                  (vcpu_id * vcpu_memory_bytes);
-               } else {
-                       vcpu_args->gva = guest_test_virt_mem;
-                       vcpu_args->pages = (vcpus * vcpu_memory_bytes) /
-                                          perf_test_args.guest_page_size;
-                       vcpu_gpa = guest_test_phys_mem;
-               }
+               vcpu->vcpu_id = vcpu_id;
+               WRITE_ONCE(vcpu->running, false);
 
-               vcpu_args_set(vm, vcpu_id, 1, vcpu_id);
+               pthread_create(&vcpu->thread, NULL, vcpu_thread_main, vcpu);
+       }
 
-               pr_debug("Added VCPU %d with test mem gpa [%lx, %lx)\n",
-                        vcpu_id, vcpu_gpa, vcpu_gpa +
-                        (vcpu_args->pages * perf_test_args.guest_page_size));
+       for (vcpu_id = 0; vcpu_id < vcpus; vcpu_id++) {
+               while (!READ_ONCE(vcpu_threads[vcpu_id].running))
+                       ;
        }
+
+       WRITE_ONCE(all_vcpu_threads_running, true);
+}
+
+void perf_test_join_vcpu_threads(int vcpus)
+{
+       int vcpu_id;
+
+       for (vcpu_id = 0; vcpu_id < vcpus; vcpu_id++)
+               pthread_join(vcpu_threads[vcpu_id].thread, NULL);
 }
index b724291..6d23878 100644 (file)
@@ -283,6 +283,11 @@ size_t get_backing_src_pagesz(uint32_t i)
        }
 }
 
+bool is_backing_src_hugetlb(uint32_t i)
+{
+       return !!(vm_mem_backing_src_alias(i)->flag & MAP_HUGETLB);
+}
+
 static void print_available_backing_src_types(const char *prefix)
 {
        int i;
index 4cfcafe..1410d0a 100644 (file)
@@ -36,11 +36,9 @@ static uint64_t guest_percpu_mem_size = DEFAULT_PER_VCPU_MEM_SIZE;
 
 static bool run_vcpus = true;
 
-static void *vcpu_worker(void *data)
+static void vcpu_worker(struct perf_test_vcpu_args *vcpu_args)
 {
        int ret;
-       struct perf_test_vcpu_args *vcpu_args =
-               (struct perf_test_vcpu_args *)data;
        int vcpu_id = vcpu_args->vcpu_id;
        struct kvm_vm *vm = perf_test_args.vm;
        struct kvm_run *run;
@@ -59,8 +57,6 @@ static void *vcpu_worker(void *data)
                            "Invalid guest sync status: exit_reason=%s\n",
                            exit_reason_str(run->exit_reason));
        }
-
-       return NULL;
 }
 
 struct memslot_antagonist_args {
@@ -80,7 +76,7 @@ static void add_remove_memslot(struct kvm_vm *vm, useconds_t delay,
         * Add the dummy memslot just below the perf_test_util memslot, which is
         * at the top of the guest physical address space.
         */
-       gpa = guest_test_phys_mem - pages * vm_get_page_size(vm);
+       gpa = perf_test_args.gpa - pages * vm_get_page_size(vm);
 
        for (i = 0; i < nr_modifications; i++) {
                usleep(delay);
@@ -100,29 +96,15 @@ struct test_params {
 static void run_test(enum vm_guest_mode mode, void *arg)
 {
        struct test_params *p = arg;
-       pthread_t *vcpu_threads;
        struct kvm_vm *vm;
-       int vcpu_id;
 
        vm = perf_test_create_vm(mode, nr_vcpus, guest_percpu_mem_size, 1,
-                                VM_MEM_SRC_ANONYMOUS);
-
-       perf_test_args.wr_fract = 1;
-
-       vcpu_threads = malloc(nr_vcpus * sizeof(*vcpu_threads));
-       TEST_ASSERT(vcpu_threads, "Memory allocation failed");
-
-       perf_test_setup_vcpus(vm, nr_vcpus, guest_percpu_mem_size,
-                             p->partition_vcpu_memory_access);
-
-       /* Export the shared variables to the guest */
-       sync_global_to_guest(vm, perf_test_args);
+                                VM_MEM_SRC_ANONYMOUS,
+                                p->partition_vcpu_memory_access);
 
        pr_info("Finished creating vCPUs\n");
 
-       for (vcpu_id = 0; vcpu_id < nr_vcpus; vcpu_id++)
-               pthread_create(&vcpu_threads[vcpu_id], NULL, vcpu_worker,
-                              &perf_test_args.vcpu_args[vcpu_id]);
+       perf_test_start_vcpu_threads(nr_vcpus, vcpu_worker);
 
        pr_info("Started all vCPUs\n");
 
@@ -131,16 +113,10 @@ static void run_test(enum vm_guest_mode mode, void *arg)
 
        run_vcpus = false;
 
-       /* Wait for the vcpu threads to quit */
-       for (vcpu_id = 0; vcpu_id < nr_vcpus; vcpu_id++)
-               pthread_join(vcpu_threads[vcpu_id], NULL);
-
+       perf_test_join_vcpu_threads(nr_vcpus);
        pr_info("All vCPU threads joined\n");
 
-       ucall_uninit(vm);
-       kvm_vm_free(vm);
-
-       free(vcpu_threads);
+       perf_test_destroy_vm(vm);
 }
 
 static void help(char *name)
index eda0d2a..a0699f0 100644 (file)
 
 #define PVTIME_ADDR    (SHINFO_REGION_GPA + PAGE_SIZE)
 #define RUNSTATE_ADDR  (SHINFO_REGION_GPA + PAGE_SIZE + 0x20)
+#define VCPU_INFO_ADDR (SHINFO_REGION_GPA + 0x40)
 
 #define RUNSTATE_VADDR (SHINFO_REGION_GVA + PAGE_SIZE + 0x20)
+#define VCPU_INFO_VADDR        (SHINFO_REGION_GVA + 0x40)
+
+#define EVTCHN_VECTOR  0x10
 
 static struct kvm_vm *vm;
 
@@ -56,15 +60,44 @@ struct vcpu_runstate_info {
     uint64_t time[4];
 };
 
+struct arch_vcpu_info {
+    unsigned long cr2;
+    unsigned long pad; /* sizeof(vcpu_info_t) == 64 */
+};
+
+struct vcpu_info {
+        uint8_t evtchn_upcall_pending;
+        uint8_t evtchn_upcall_mask;
+        unsigned long evtchn_pending_sel;
+        struct arch_vcpu_info arch;
+        struct pvclock_vcpu_time_info time;
+}; /* 64 bytes (x86) */
+
 #define RUNSTATE_running  0
 #define RUNSTATE_runnable 1
 #define RUNSTATE_blocked  2
 #define RUNSTATE_offline  3
 
+static void evtchn_handler(struct ex_regs *regs)
+{
+       struct vcpu_info *vi = (void *)VCPU_INFO_VADDR;
+       vi->evtchn_upcall_pending = 0;
+
+       GUEST_SYNC(0x20);
+}
+
 static void guest_code(void)
 {
        struct vcpu_runstate_info *rs = (void *)RUNSTATE_VADDR;
 
+       __asm__ __volatile__(
+               "sti\n"
+               "nop\n"
+       );
+
+       /* Trigger an interrupt injection */
+       GUEST_SYNC(0);
+
        /* Test having the host set runstates manually */
        GUEST_SYNC(RUNSTATE_runnable);
        GUEST_ASSERT(rs->time[RUNSTATE_runnable] != 0);
@@ -153,7 +186,7 @@ int main(int argc, char *argv[])
 
        struct kvm_xen_vcpu_attr vi = {
                .type = KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO,
-               .u.gpa = SHINFO_REGION_GPA + 0x40,
+               .u.gpa = VCPU_INFO_ADDR,
        };
        vcpu_ioctl(vm, VCPU_ID, KVM_XEN_VCPU_SET_ATTR, &vi);
 
@@ -163,6 +196,16 @@ int main(int argc, char *argv[])
        };
        vcpu_ioctl(vm, VCPU_ID, KVM_XEN_VCPU_SET_ATTR, &pvclock);
 
+       struct kvm_xen_hvm_attr vec = {
+               .type = KVM_XEN_ATTR_TYPE_UPCALL_VECTOR,
+               .u.vector = EVTCHN_VECTOR,
+       };
+       vm_ioctl(vm, KVM_XEN_HVM_SET_ATTR, &vec);
+
+       vm_init_descriptor_tables(vm);
+       vcpu_init_descriptor_tables(vm, VCPU_ID);
+       vm_install_exception_handler(vm, EVTCHN_VECTOR, evtchn_handler);
+
        if (do_runstate_tests) {
                struct kvm_xen_vcpu_attr st = {
                        .type = KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADDR,
@@ -171,9 +214,14 @@ int main(int argc, char *argv[])
                vcpu_ioctl(vm, VCPU_ID, KVM_XEN_VCPU_SET_ATTR, &st);
        }
 
+       struct vcpu_info *vinfo = addr_gpa2hva(vm, VCPU_INFO_VADDR);
+       vinfo->evtchn_upcall_pending = 0;
+
        struct vcpu_runstate_info *rs = addr_gpa2hva(vm, RUNSTATE_ADDR);
        rs->state = 0x5a;
 
+       bool evtchn_irq_expected = false;
+
        for (;;) {
                volatile struct kvm_run *run = vcpu_state(vm, VCPU_ID);
                struct ucall uc;
@@ -193,16 +241,21 @@ int main(int argc, char *argv[])
                        struct kvm_xen_vcpu_attr rst;
                        long rundelay;
 
-                       /* If no runstate support, bail out early */
-                       if (!do_runstate_tests)
-                               goto done;
-
-                       TEST_ASSERT(rs->state_entry_time == rs->time[0] +
-                                   rs->time[1] + rs->time[2] + rs->time[3],
-                                   "runstate times don't add up");
+                       if (do_runstate_tests)
+                               TEST_ASSERT(rs->state_entry_time == rs->time[0] +
+                                           rs->time[1] + rs->time[2] + rs->time[3],
+                                           "runstate times don't add up");
 
                        switch (uc.args[1]) {
-                       case RUNSTATE_running...RUNSTATE_offline:
+                       case 0:
+                               evtchn_irq_expected = true;
+                               vinfo->evtchn_upcall_pending = 1;
+                               break;
+
+                       case RUNSTATE_runnable...RUNSTATE_offline:
+                               TEST_ASSERT(!evtchn_irq_expected, "Event channel IRQ not seen");
+                               if (!do_runstate_tests)
+                                       goto done;
                                rst.type = KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_CURRENT;
                                rst.u.runstate.state = uc.args[1];
                                vcpu_ioctl(vm, VCPU_ID, KVM_XEN_VCPU_SET_ATTR, &rst);
@@ -236,6 +289,10 @@ int main(int argc, char *argv[])
                                        sched_yield();
                                } while (get_run_delay() < rundelay);
                                break;
+                       case 0x20:
+                               TEST_ASSERT(evtchn_irq_expected, "Unexpected event channel IRQ");
+                               evtchn_irq_expected = false;
+                               break;
                        }
                        break;
                }
index a4bd1b0..697994a 100644 (file)
@@ -6,6 +6,7 @@ CONFIG_IPV6_MULTIPLE_TABLES=y
 CONFIG_NET_VRF=m
 CONFIG_BPF_SYSCALL=y
 CONFIG_CGROUP_BPF=y
+CONFIG_NET_ACT_CT=m
 CONFIG_NET_ACT_MIRRED=m
 CONFIG_NET_ACT_MPLS=m
 CONFIG_NET_ACT_VLAN=m
index d9eca22..de19eb6 100755 (executable)
@@ -3,7 +3,7 @@
 
 ALL_TESTS="gact_drop_and_ok_test mirred_egress_redirect_test \
        mirred_egress_mirror_test matchall_mirred_egress_mirror_test \
-       gact_trap_test"
+       gact_trap_test mirred_egress_to_ingress_test"
 NUM_NETIFS=4
 source tc_common.sh
 source lib.sh
@@ -13,10 +13,12 @@ tcflags="skip_hw"
 h1_create()
 {
        simple_if_init $h1 192.0.2.1/24
+       tc qdisc add dev $h1 clsact
 }
 
 h1_destroy()
 {
+       tc qdisc del dev $h1 clsact
        simple_if_fini $h1 192.0.2.1/24
 }
 
@@ -153,6 +155,49 @@ gact_trap_test()
        log_test "trap ($tcflags)"
 }
 
+mirred_egress_to_ingress_test()
+{
+       RET=0
+
+       tc filter add dev $h1 protocol ip pref 100 handle 100 egress flower \
+               ip_proto icmp src_ip 192.0.2.1 dst_ip 192.0.2.2 type 8 action \
+                       ct commit nat src addr 192.0.2.2 pipe \
+                       ct clear pipe \
+                       ct commit nat dst addr 192.0.2.1 pipe \
+                       mirred ingress redirect dev $h1
+
+       tc filter add dev $swp1 protocol ip pref 11 handle 111 ingress flower \
+               ip_proto icmp src_ip 192.0.2.1 dst_ip 192.0.2.2 type 8 action drop
+       tc filter add dev $swp1 protocol ip pref 12 handle 112 ingress flower \
+               ip_proto icmp src_ip 192.0.2.1 dst_ip 192.0.2.2 type 0 action pass
+
+       $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
+               -t icmp "ping,id=42,seq=10" -q
+
+       tc_check_packets "dev $h1 egress" 100 1
+       check_err $? "didn't mirror first packet"
+
+       tc_check_packets "dev $swp1 ingress" 111 1
+       check_fail $? "didn't redirect first packet"
+       tc_check_packets "dev $swp1 ingress" 112 1
+       check_err $? "didn't receive reply to first packet"
+
+       ping 192.0.2.2 -I$h1 -c1 -w1 -q 1>/dev/null 2>&1
+
+       tc_check_packets "dev $h1 egress" 100 2
+       check_err $? "didn't mirror second packet"
+       tc_check_packets "dev $swp1 ingress" 111 1
+       check_fail $? "didn't redirect second packet"
+       tc_check_packets "dev $swp1 ingress" 112 2
+       check_err $? "didn't receive reply to second packet"
+
+       tc filter del dev $h1 egress protocol ip pref 100 handle 100 flower
+       tc filter del dev $swp1 ingress protocol ip pref 11 handle 111 flower
+       tc filter del dev $swp1 ingress protocol ip pref 12 handle 112 flower
+
+       log_test "mirred_egress_to_ingress ($tcflags)"
+}
+
 setup_prepare()
 {
        h1=${NETIFS[p1]}
index fdeb44d..3224651 100755 (executable)
@@ -118,16 +118,18 @@ gre_gst_test_checks()
        local addr=$2
        local proto=$3
 
-       $NS_EXEC nc $proto -kl $port >/dev/null &
+       [ "$proto" == 6 ] && addr="[$addr]"
+
+       $NS_EXEC socat - tcp${proto}-listen:$port,reuseaddr,fork >/dev/null &
        PID=$!
        while ! $NS_EXEC ss -ltn | grep -q $port; do ((i++)); sleep 0.01; done
 
-       cat $TMPFILE | timeout 1 nc $proto -N $addr $port
+       cat $TMPFILE | timeout 1 socat -u STDIN TCP:$addr:$port
        log_test $? 0 "$name - copy file w/ TSO"
 
        ethtool -K veth0 tso off
 
-       cat $TMPFILE | timeout 1 nc $proto -N $addr $port
+       cat $TMPFILE | timeout 1 socat -u STDIN TCP:$addr:$port
        log_test $? 0 "$name - copy file w/ GSO"
 
        ethtool -K veth0 tso on
@@ -155,8 +157,8 @@ gre6_gso_test()
 
        sleep 2
 
-       gre_gst_test_checks GREv6/v4 172.16.2.2
-       gre_gst_test_checks GREv6/v6 2001:db8:1::2 -6
+       gre_gst_test_checks GREv6/v4 172.16.2.2 4
+       gre_gst_test_checks GREv6/v6 2001:db8:1::2 6
 
        cleanup
 }
@@ -212,8 +214,8 @@ if [ ! -x "$(command -v ip)" ]; then
        exit $ksft_skip
 fi
 
-if [ ! -x "$(command -v nc)" ]; then
-       echo "SKIP: Could not run test without nc tool"
+if [ ! -x "$(command -v socat)" ]; then
+       echo "SKIP: Could not run test without socat tool"
        exit $ksft_skip
 fi
 
index d317245..9646bb9 100644 (file)
@@ -2548,72 +2548,36 @@ struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn)
 }
 EXPORT_SYMBOL_GPL(gfn_to_page);
 
-void kvm_release_pfn(kvm_pfn_t pfn, bool dirty, struct gfn_to_pfn_cache *cache)
+void kvm_release_pfn(kvm_pfn_t pfn, bool dirty)
 {
        if (pfn == 0)
                return;
 
-       if (cache)
-               cache->pfn = cache->gfn = 0;
-
        if (dirty)
                kvm_release_pfn_dirty(pfn);
        else
                kvm_release_pfn_clean(pfn);
 }
 
-static void kvm_cache_gfn_to_pfn(struct kvm_memory_slot *slot, gfn_t gfn,
-                                struct gfn_to_pfn_cache *cache, u64 gen)
-{
-       kvm_release_pfn(cache->pfn, cache->dirty, cache);
-
-       cache->pfn = gfn_to_pfn_memslot(slot, gfn);
-       cache->gfn = gfn;
-       cache->dirty = false;
-       cache->generation = gen;
-}
-
-static int __kvm_map_gfn(struct kvm_memslots *slots, gfn_t gfn,
-                        struct kvm_host_map *map,
-                        struct gfn_to_pfn_cache *cache,
-                        bool atomic)
+int kvm_vcpu_map(struct kvm_vcpu *vcpu, gfn_t gfn, struct kvm_host_map *map)
 {
        kvm_pfn_t pfn;
        void *hva = NULL;
        struct page *page = KVM_UNMAPPED_PAGE;
-       struct kvm_memory_slot *slot = __gfn_to_memslot(slots, gfn);
-       u64 gen = slots->generation;
 
        if (!map)
                return -EINVAL;
 
-       if (cache) {
-               if (!cache->pfn || cache->gfn != gfn ||
-                       cache->generation != gen) {
-                       if (atomic)
-                               return -EAGAIN;
-                       kvm_cache_gfn_to_pfn(slot, gfn, cache, gen);
-               }
-               pfn = cache->pfn;
-       } else {
-               if (atomic)
-                       return -EAGAIN;
-               pfn = gfn_to_pfn_memslot(slot, gfn);
-       }
+       pfn = gfn_to_pfn(vcpu->kvm, gfn);
        if (is_error_noslot_pfn(pfn))
                return -EINVAL;
 
        if (pfn_valid(pfn)) {
                page = pfn_to_page(pfn);
-               if (atomic)
-                       hva = kmap_atomic(page);
-               else
-                       hva = kmap(page);
+               hva = kmap(page);
 #ifdef CONFIG_HAS_IOMEM
-       } else if (!atomic) {
-               hva = memremap(pfn_to_hpa(pfn), PAGE_SIZE, MEMREMAP_WB);
        } else {
-               return -EINVAL;
+               hva = memremap(pfn_to_hpa(pfn), PAGE_SIZE, MEMREMAP_WB);
 #endif
        }
 
@@ -2627,27 +2591,9 @@ static int __kvm_map_gfn(struct kvm_memslots *slots, gfn_t gfn,
 
        return 0;
 }
-
-int kvm_map_gfn(struct kvm_vcpu *vcpu, gfn_t gfn, struct kvm_host_map *map,
-               struct gfn_to_pfn_cache *cache, bool atomic)
-{
-       return __kvm_map_gfn(kvm_memslots(vcpu->kvm), gfn, map,
-                       cache, atomic);
-}
-EXPORT_SYMBOL_GPL(kvm_map_gfn);
-
-int kvm_vcpu_map(struct kvm_vcpu *vcpu, gfn_t gfn, struct kvm_host_map *map)
-{
-       return __kvm_map_gfn(kvm_vcpu_memslots(vcpu), gfn, map,
-               NULL, false);
-}
 EXPORT_SYMBOL_GPL(kvm_vcpu_map);
 
-static void __kvm_unmap_gfn(struct kvm *kvm,
-                       struct kvm_memory_slot *memslot,
-                       struct kvm_host_map *map,
-                       struct gfn_to_pfn_cache *cache,
-                       bool dirty, bool atomic)
+void kvm_vcpu_unmap(struct kvm_vcpu *vcpu, struct kvm_host_map *map, bool dirty)
 {
        if (!map)
                return;
@@ -2655,45 +2601,21 @@ static void __kvm_unmap_gfn(struct kvm *kvm,
        if (!map->hva)
                return;
 
-       if (map->page != KVM_UNMAPPED_PAGE) {
-               if (atomic)
-                       kunmap_atomic(map->hva);
-               else
-                       kunmap(map->page);
-       }
+       if (map->page != KVM_UNMAPPED_PAGE)
+               kunmap(map->page);
 #ifdef CONFIG_HAS_IOMEM
-       else if (!atomic)
-               memunmap(map->hva);
        else
-               WARN_ONCE(1, "Unexpected unmapping in atomic context");
+               memunmap(map->hva);
 #endif
 
        if (dirty)
-               mark_page_dirty_in_slot(kvm, memslot, map->gfn);
+               kvm_vcpu_mark_page_dirty(vcpu, map->gfn);
 
-       if (cache)
-               cache->dirty |= dirty;
-       else
-               kvm_release_pfn(map->pfn, dirty, NULL);
+       kvm_release_pfn(map->pfn, dirty);
 
        map->hva = NULL;
        map->page = NULL;
 }
-
-int kvm_unmap_gfn(struct kvm_vcpu *vcpu, struct kvm_host_map *map, 
-                 struct gfn_to_pfn_cache *cache, bool dirty, bool atomic)
-{
-       __kvm_unmap_gfn(vcpu->kvm, gfn_to_memslot(vcpu->kvm, map->gfn), map,
-                       cache, dirty, atomic);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(kvm_unmap_gfn);
-
-void kvm_vcpu_unmap(struct kvm_vcpu *vcpu, struct kvm_host_map *map, bool dirty)
-{
-       __kvm_unmap_gfn(vcpu->kvm, kvm_vcpu_gfn_to_memslot(vcpu, map->gfn),
-                       map, NULL, dirty, false);
-}
 EXPORT_SYMBOL_GPL(kvm_vcpu_unmap);
 
 struct page *kvm_vcpu_gfn_to_page(struct kvm_vcpu *vcpu, gfn_t gfn)