]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
Merge tag 'perf_urgent_for_v6.7_rc6' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 17 Dec 2023 22:03:11 +0000 (14:03 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 17 Dec 2023 22:03:11 +0000 (14:03 -0800)
Pull perf fix from Borislav Petkov:

 - Avoid iterating over newly created group leader event's siblings
   because there are none, and thus prevent a lockdep splat

* tag 'perf_urgent_for_v6.7_rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  perf: Fix perf_event_validate_size() lockdep splat

266 files changed:
.mailmap
Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml
Documentation/devicetree/bindings/display/panel/panel-simple.yaml
Documentation/filesystems/fuse-io.rst
MAINTAINERS
arch/arm64/include/asm/pgtable.h
arch/loongarch/include/asm/efi.h
arch/loongarch/kernel/Makefile
arch/m68k/include/asm/kexec.h
arch/m68k/kernel/Makefile
arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
arch/mips/boot/dts/loongson/ls7a-pch.dtsi
arch/mips/cavium-octeon/smp.c
arch/mips/include/asm/kexec.h
arch/mips/include/asm/smp-ops.h
arch/mips/include/asm/smp.h
arch/mips/kernel/Makefile
arch/mips/kernel/smp-bmips.c
arch/mips/kernel/smp-cps.c
arch/mips/loongson64/reset.c
arch/mips/loongson64/smp.c
arch/powerpc/configs/skiroot_defconfig
arch/powerpc/platforms/pseries/vas.c
arch/powerpc/platforms/pseries/vas.h
arch/riscv/Kconfig
arch/riscv/include/asm/pgtable.h
arch/riscv/kernel/crash_core.c
arch/s390/configs/debug_defconfig
arch/sh/include/asm/kexec.h
arch/sh/kernel/Makefile
arch/sh/kernel/reboot.c
arch/sh/kernel/setup.c
arch/x86/boot/compressed/acpi.c
drivers/accel/ivpu/ivpu_hw_37xx.c
drivers/atm/solos-pci.c
drivers/clk/qcom/Kconfig
drivers/clk/rockchip/clk-rk3128.c
drivers/clk/rockchip/clk-rk3568.c
drivers/cxl/core/hdm.c
drivers/cxl/core/memdev.c
drivers/cxl/core/pci.c
drivers/cxl/core/pmu.c
drivers/cxl/core/port.c
drivers/cxl/core/region.c
drivers/dma/fsl-edma-common.c
drivers/dma/fsl-edma-main.c
drivers/dma/idxd/registers.h
drivers/dma/idxd/submit.c
drivers/dma/stm32-dma.c
drivers/dma/ti/k3-psil-am62.c
drivers/dma/ti/k3-psil-am62a.c
drivers/dpll/dpll_netlink.c
drivers/edac/versal_edac.c
drivers/firmware/efi/libstub/loongarch-stub.c
drivers/firmware/efi/libstub/loongarch.c
drivers/firmware/efi/libstub/x86-stub.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c
drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/dc/dc_hw_types.h
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c
drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c
drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c
drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c
drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
drivers/gpu/drm/amd/display/modules/power/power_helpers.c
drivers/gpu/drm/amd/pm/amdgpu_pm.c
drivers/gpu/drm/drm_auth.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/i915/display/intel_dp_link_training.c
drivers/gpu/drm/i915/display/intel_fb.c
drivers/gpu/drm/i915/display/skl_scaler.c
drivers/gpu/drm/i915/gt/intel_reset.c
drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
drivers/gpu/drm/i915/i915_gpu_error.h
drivers/gpu/drm/i915/selftests/igt_live_test.c
drivers/gpu/drm/i915/selftests/igt_live_test.h
drivers/gpu/drm/mediatek/mtk_disp_gamma.c
drivers/gpu/drm/mediatek/mtk_drm_crtc.c
drivers/gpu/drm/mediatek/mtk_drm_drv.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c
drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c
drivers/hid/hid-apple.c
drivers/hid/hid-ids.h
drivers/hid/hid-lenovo.c
drivers/hid/hid-quirks.c
drivers/hid/i2c-hid/i2c-hid-acpi.c
drivers/net/ethernet/amazon/ena/ena_eth_com.c
drivers/net/ethernet/amazon/ena/ena_netdev.c
drivers/net/ethernet/aquantia/atlantic/aq_ring.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-flower.c
drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/intel/iavf/iavf.h
drivers/net/ethernet/intel/iavf/iavf_ethtool.c
drivers/net/ethernet/intel/iavf/iavf_fdir.h
drivers/net/ethernet/intel/iavf/iavf_main.c
drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
drivers/net/ethernet/marvell/octeon_ep/octep_main.c
drivers/net/ethernet/marvell/octeontx2/af/rpm.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en/tc/post_act.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c
drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
drivers/net/ethernet/qlogic/qed/qed_cxt.c
drivers/net/ethernet/qualcomm/qca_debug.c
drivers/net/ethernet/qualcomm/qca_spi.c
drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
drivers/net/team/team.c
drivers/pci/controller/dwc/pcie-qcom.c
drivers/pci/controller/pci-loongson.c
drivers/pci/controller/vmd.c
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/pcie/aspm.c
drivers/perf/arm-cmn.c
drivers/phy/mediatek/phy-mtk-mipi-dsi-mt8183.c
drivers/phy/sunplus/phy-sunplus-usb2.c
drivers/phy/ti/phy-gmii-sel.c
drivers/platform/x86/intel/vbtn.c
drivers/platform/x86/intel_ips.c
drivers/platform/x86/thinkpad_acpi.c
drivers/soundwire/intel_ace2x.c
drivers/soundwire/stream.c
fs/afs/rxrpc.c
fs/bcachefs/btree_cache.c
fs/bcachefs/btree_io.c
fs/bcachefs/btree_io.h
fs/bcachefs/btree_key_cache.c
fs/bcachefs/btree_update.c
fs/bcachefs/btree_update_interior.c
fs/bcachefs/data_update.c
fs/bcachefs/dirent.c
fs/bcachefs/dirent.h
fs/bcachefs/extents.c
fs/bcachefs/fs-ioctl.c
fs/bcachefs/fs.c
fs/bcachefs/inode.c
fs/bcachefs/journal.c
fs/bcachefs/journal.h
fs/bcachefs/journal_io.c
fs/bcachefs/journal_reclaim.c
fs/bcachefs/recovery.c
fs/bcachefs/reflink.c
fs/bcachefs/sysfs.c
fs/btrfs/delalloc-space.c
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/ordered-data.c
fs/btrfs/qgroup.c
fs/btrfs/qgroup.h
fs/btrfs/transaction.c
fs/btrfs/transaction.h
fs/ext4/file.c
fs/ext4/mballoc.c
fs/fuse/dax.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/fuse/inode.c
fs/jbd2/commit.c
fs/jbd2/journal.c
fs/nfsd/auth.c
fs/nfsd/nfssvc.c
fs/nfsd/vfs.c
fs/open.c
fs/smb/client/cached_dir.c
fs/smb/client/smb2misc.c
fs/smb/client/smb2ops.c
fs/smb/client/smb2pdu.c
fs/smb/client/smb2proto.h
fs/smb/common/smb2pdu.h
fs/smb/server/oplock.c
fs/smb/server/oplock.h
fs/smb/server/smb2ops.c
fs/smb/server/smb2pdu.c
fs/smb/server/vfs.c
fs/smb/server/vfs_cache.c
fs/smb/server/vfs_cache.h
fs/tracefs/event_inode.c
fs/ufs/util.c
include/linux/cred.h
include/linux/damon.h
include/linux/io_uring_types.h
include/linux/jbd2.h
include/linux/mlx5/mlx5_ifc.h
include/linux/mm.h
include/linux/mm_inline.h
include/linux/mmzone.h
include/linux/pci.h
include/net/addrconf.h
include/net/if_inet6.h
include/net/netfilter/nf_flow_table.h
include/uapi/linux/fuse.h
io_uring/poll.c
io_uring/uring_cmd.c
kernel/Kconfig.kexec
kernel/crash_core.c
kernel/cred.c
kernel/exit.c
kernel/resource.c
kernel/trace/ring_buffer.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_events_hist.c
kernel/trace/trace_output.c
lib/Kconfig.debug
mm/damon/core.c
mm/shmem.c
mm/vmscan.c
mm/workingset.c
net/appletalk/ddp.c
net/atm/ioctl.c
net/core/neighbour.c
net/core/skbuff.c
net/ipv4/tcp_input.c
net/ipv4/tcp_output.c
net/ipv6/addrconf.c
net/rose/af_rose.c
net/sched/act_ct.c
net/sunrpc/auth.c
net/vmw_vsock/virtio_transport_common.c
scripts/sign-file.c
security/selinux/hooks.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/tas2781_hda_i2c.c
tools/objtool/noreturns.h
tools/testing/cxl/Kbuild
tools/testing/cxl/cxl_core_exports.c [new file with mode: 0644]
tools/testing/cxl/test/cxl.c
tools/testing/selftests/Makefile
tools/testing/selftests/bpf/config.x86_64
tools/testing/selftests/hid/config.common
tools/testing/selftests/lib.mk
tools/testing/selftests/mm/cow.c

index 19eb49e55836b0c086a63225158db62991cef8b9..3ac1c12545f20109885881b96eb0752d45a809a8 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -266,6 +266,9 @@ Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
 Jernej Skrabec <jernej.skrabec@gmail.com> <jernej.skrabec@siol.net>
 Jessica Zhang <quic_jesszhan@quicinc.com> <jesszhan@codeaurora.org>
 Jilai Wang <quic_jilaiw@quicinc.com> <jilaiw@codeaurora.org>
+Jiri Kosina <jikos@kernel.org> <jikos@jikos.cz>
+Jiri Kosina <jikos@kernel.org> <jkosina@suse.cz>
+Jiri Kosina <jikos@kernel.org> <jkosina@suse.com>
 Jiri Pirko <jiri@resnulli.us> <jiri@nvidia.com>
 Jiri Pirko <jiri@resnulli.us> <jiri@mellanox.com>
 Jiri Pirko <jiri@resnulli.us> <jpirko@redhat.com>
index 73674baea75d329bfa949c9de1e71f8c9cf58562..f9160d7bac3caa5e12c4de6b19063cd3247d17b3 100644 (file)
@@ -42,6 +42,8 @@ properties:
       - lg,acx467akm-7
         # LG Corporation 7" WXGA TFT LCD panel
       - lg,ld070wx3-sl01
+        # LG Corporation 5" HD TFT LCD panel
+      - lg,lh500wx1-sd03
         # One Stop Displays OSD101T2587-53TS 10.1" 1920x1200 panel
       - osddisplays,osd101t2587-53ts
         # Panasonic 10" WUXGA TFT LCD panel
index 3ec9ee95045fbce8db9f623753b2f67fb79ccd45..11422af3477e58749fca386610186f9c714dfff0 100644 (file)
@@ -208,8 +208,6 @@ properties:
       - lemaker,bl035-rgb-002
         # LG 7" (800x480 pixels) TFT LCD panel
       - lg,lb070wv8
-        # LG Corporation 5" HD TFT LCD panel
-      - lg,lh500wx1-sd03
         # LG LP079QX1-SP0V 7.9" (1536x2048 pixels) TFT LCD panel
       - lg,lp079qx1-sp0v
         # LG 9.7" (2048x1536 pixels) TFT LCD panel
index 255a368fe534b4582c9be673523330e962803123..6464de4266ad504f8bdc89c834230f3c9f5219dc 100644 (file)
@@ -15,7 +15,8 @@ The direct-io mode can be selected with the FOPEN_DIRECT_IO flag in the
 FUSE_OPEN reply.
 
 In direct-io mode the page cache is completely bypassed for reads and writes.
-No read-ahead takes place. Shared mmap is disabled.
+No read-ahead takes place. Shared mmap is disabled by default. To allow shared
+mmap, the FUSE_DIRECT_IO_ALLOW_MMAP flag may be enabled in the FUSE_INIT reply.
 
 In cached mode reads may be satisfied from the page cache, and data may be
 read-ahead by the kernel to fill the cache.  The cache is always kept consistent
index e2c6187a3ac80f18aca297c6fb73332708c105df..9104430e148e6d4717f3c32c663914697dfe16cc 100644 (file)
@@ -12189,6 +12189,8 @@ LINUX FOR POWERPC (32-BIT AND 64-BIT)
 M:     Michael Ellerman <mpe@ellerman.id.au>
 R:     Nicholas Piggin <npiggin@gmail.com>
 R:     Christophe Leroy <christophe.leroy@csgroup.eu>
+R:     Aneesh Kumar K.V <aneesh.kumar@kernel.org>
+R:     Naveen N. Rao <naveen.n.rao@linux.ibm.com>
 L:     linuxppc-dev@lists.ozlabs.org
 S:     Supported
 W:     https://github.com/linuxppc/wiki/wiki
@@ -19564,7 +19566,6 @@ S:      Maintained
 F:     drivers/misc/sgi-xp/
 
 SHARED MEMORY COMMUNICATIONS (SMC) SOCKETS
-M:     Karsten Graul <kgraul@linux.ibm.com>
 M:     Wenjia Zhang <wenjia@linux.ibm.com>
 M:     Jan Karcher <jaka@linux.ibm.com>
 R:     D. Wythe <alibuda@linux.alibaba.com>
index b19a8aee684c873f2cea80947548af6a358b57ee..79ce70fbb751c616074fe24f0ea9772391a12ea9 100644 (file)
@@ -834,6 +834,12 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
                pte = set_pte_bit(pte, __pgprot(PTE_DIRTY));
 
        pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
+       /*
+        * If we end up clearing hw dirtiness for a sw-dirty PTE, set hardware
+        * dirtiness again.
+        */
+       if (pte_sw_dirty(pte))
+               pte = pte_mkdirty(pte);
        return pte;
 }
 
index 091897d40b0375758b4822ae1a95719013314709..91d81f9730ab3f81c8e6cba875a6fdadc4b0657a 100644 (file)
@@ -32,6 +32,6 @@ static inline unsigned long efi_get_kimg_min_align(void)
 
 #define EFI_KIMG_PREFERRED_ADDRESS     PHYSADDR(VMLINUX_LOAD_ADDRESS)
 
-unsigned long kernel_entry_address(void);
+unsigned long kernel_entry_address(unsigned long kernel_addr);
 
 #endif /* _ASM_LOONGARCH_EFI_H */
index 4fcc168f07323154b4d7fc6712ab7a2298bb0d3e..3c808c6803703c931d5bb52b6eefd71464da726c 100644 (file)
@@ -57,7 +57,7 @@ obj-$(CONFIG_MAGIC_SYSRQ)     += sysrq.o
 
 obj-$(CONFIG_RELOCATABLE)      += relocate.o
 
-obj-$(CONFIG_KEXEC)            += machine_kexec.o relocate_kernel.o
+obj-$(CONFIG_KEXEC_CORE)       += machine_kexec.o relocate_kernel.o
 obj-$(CONFIG_CRASH_DUMP)       += crash_dump.o
 
 obj-$(CONFIG_UNWINDER_GUESS)   += unwind_guess.o
index f5a8b2defa4bcee418aea24ab85b23c9d6fd1b06..3b0b64f0a353170ecac839677f6a8ae02bc8feb0 100644 (file)
@@ -2,7 +2,7 @@
 #ifndef _ASM_M68K_KEXEC_H
 #define _ASM_M68K_KEXEC_H
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 
 /* Maximum physical address we can use pages from */
 #define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
@@ -25,6 +25,6 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
 
 #endif /* __ASSEMBLY__ */
 
-#endif /* CONFIG_KEXEC */
+#endif /* CONFIG_KEXEC_CORE */
 
 #endif /* _ASM_M68K_KEXEC_H */
index 01fb69a5095f4375d641a4f0f7958b907d7b716c..f335bf3268a108a45bab079fbf0a1c8ead9beb71 100644 (file)
@@ -25,7 +25,7 @@ obj-$(CONFIG_PCI) += pcibios.o
 
 obj-$(CONFIG_M68K_NONCOHERENT_DMA) += dma.o
 
-obj-$(CONFIG_KEXEC)            += machine_kexec.o relocate_kernel.o
+obj-$(CONFIG_KEXEC_CORE)       += machine_kexec.o relocate_kernel.o
 obj-$(CONFIG_BOOTINFO_PROC)    += bootinfo_proc.o
 obj-$(CONFIG_UBOOT)            += uboot.o
 
index f878f47e4501bcd90e6e6faac10e50ef44b4c2ae..ee3e2153dd13fb78894f25d9efd476075c9d86d8 100644 (file)
                                compatible = "pci0014,7a03.0",
                                                   "pci0014,7a03",
                                                   "pciclass0c0320",
-                                                  "pciclass0c03",
-                                                  "loongson, pci-gmac";
+                                                  "pciclass0c03";
 
                                reg = <0x1800 0x0 0x0 0x0 0x0>;
                                interrupts = <12 IRQ_TYPE_LEVEL_LOW>,
index 7c69e8245c2f10aa30a98fef4601e271ac640d34..cce9428afc41fc3ec1e347a344f6e48b9b345ca4 100644 (file)
                                compatible = "pci0014,7a03.0",
                                                   "pci0014,7a03",
                                                   "pciclass020000",
-                                                  "pciclass0200",
-                                                  "loongson, pci-gmac";
+                                                  "pciclass0200";
 
                                reg = <0x1800 0x0 0x0 0x0 0x0>;
                                interrupts = <12 IRQ_TYPE_LEVEL_HIGH>,
index 33c09688210fff313b48e438986b95da0f53be6c..08ea2cde1eb5b3af1ccec1badec2f665b1a4bc92 100644 (file)
@@ -422,7 +422,7 @@ static const struct plat_smp_ops octeon_smp_ops = {
        .cpu_disable            = octeon_cpu_disable,
        .cpu_die                = octeon_cpu_die,
 #endif
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
        .kexec_nonboot_cpu      = kexec_nonboot_cpu_jump,
 #endif
 };
@@ -502,7 +502,7 @@ static const struct plat_smp_ops octeon_78xx_smp_ops = {
        .cpu_disable            = octeon_cpu_disable,
        .cpu_die                = octeon_cpu_die,
 #endif
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
        .kexec_nonboot_cpu      = kexec_nonboot_cpu_jump,
 #endif
 };
index d6d5fa5cc31dd7f20f9a729690d4ef40af4c545f..69e579e41e6623e8c2fd26d6ca9daf8438e4469c 100644 (file)
@@ -31,7 +31,7 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
                prepare_frametrace(newregs);
 }
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 struct kimage;
 extern unsigned long kexec_args[4];
 extern int (*_machine_kexec_prepare)(struct kimage *);
index 5719ff49eff1c88f0e3b44ee6f23287c6c4862e8..0c59e168f8008ca88685cf298f44053e097af1df 100644 (file)
@@ -35,7 +35,7 @@ struct plat_smp_ops {
        void (*cpu_die)(unsigned int cpu);
        void (*cleanup_dead_cpu)(unsigned cpu);
 #endif
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
        void (*kexec_nonboot_cpu)(void);
 #endif
 };
index a40d8c0e4b879b2a12ad055c1940b0f63f3112fb..901bc61fa7ae922619728b29ecf066bb19a6755b 100644 (file)
@@ -93,7 +93,7 @@ static inline void __cpu_die(unsigned int cpu)
 extern void __noreturn play_dead(void);
 #endif
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 static inline void kexec_nonboot_cpu(void)
 {
        extern const struct plat_smp_ops *mp_ops;       /* private */
index 853a43ee4b446ebaf323480d0fab337b462ce2c5..ecf3278a32f7077f29bee3b5f1b535eb8b2c5d06 100644 (file)
@@ -90,7 +90,7 @@ obj-$(CONFIG_GPIO_TXX9)               += gpio_txx9.o
 
 obj-$(CONFIG_RELOCATABLE)      += relocate.o
 
-obj-$(CONFIG_KEXEC)            += machine_kexec.o relocate_kernel.o crash.o
+obj-$(CONFIG_KEXEC_CORE)       += machine_kexec.o relocate_kernel.o crash.o
 obj-$(CONFIG_CRASH_DUMP)       += crash_dump.o
 obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
 obj-$(CONFIG_EARLY_PRINTK_8250)        += early_printk_8250.o
index c074ecce3fbf29a313c1ddc9573967d21ce5d7e3..b3dbf9ecb0d63ea81102114b1886b0cd88b23cd8 100644 (file)
@@ -434,7 +434,7 @@ const struct plat_smp_ops bmips43xx_smp_ops = {
        .cpu_disable            = bmips_cpu_disable,
        .cpu_die                = bmips_cpu_die,
 #endif
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
        .kexec_nonboot_cpu      = kexec_nonboot_cpu_jump,
 #endif
 };
@@ -451,7 +451,7 @@ const struct plat_smp_ops bmips5000_smp_ops = {
        .cpu_disable            = bmips_cpu_disable,
        .cpu_die                = bmips_cpu_die,
 #endif
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
        .kexec_nonboot_cpu      = kexec_nonboot_cpu_jump,
 #endif
 };
index dd55d59b88db34e07924e1f64b7e139a8e56274b..f6c37d407f365fc3df4dbaf807a17550856a8c36 100644 (file)
@@ -392,7 +392,7 @@ static void cps_smp_finish(void)
        local_irq_enable();
 }
 
-#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_KEXEC)
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_KEXEC_CORE)
 
 enum cpu_death {
        CPU_DEATH_HALT,
@@ -429,7 +429,7 @@ static void cps_shutdown_this_cpu(enum cpu_death death)
        }
 }
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 
 static void cps_kexec_nonboot_cpu(void)
 {
@@ -439,9 +439,9 @@ static void cps_kexec_nonboot_cpu(void)
                cps_shutdown_this_cpu(CPU_DEATH_POWER);
 }
 
-#endif /* CONFIG_KEXEC */
+#endif /* CONFIG_KEXEC_CORE */
 
-#endif /* CONFIG_HOTPLUG_CPU || CONFIG_KEXEC */
+#endif /* CONFIG_HOTPLUG_CPU || CONFIG_KEXEC_CORE */
 
 #ifdef CONFIG_HOTPLUG_CPU
 
@@ -610,7 +610,7 @@ static const struct plat_smp_ops cps_smp_ops = {
        .cpu_die                = cps_cpu_die,
        .cleanup_dead_cpu       = cps_cleanup_dead_cpu,
 #endif
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
        .kexec_nonboot_cpu      = cps_kexec_nonboot_cpu,
 #endif
 };
index e420800043b0897b70f0775a452233db6f50d810..e01c8d4a805a91586e9ba09a686fa1ca89672280 100644 (file)
@@ -53,7 +53,7 @@ static void loongson_halt(void)
        }
 }
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 
 /* 0X80000000~0X80200000 is safe */
 #define MAX_ARGS       64
@@ -158,7 +158,7 @@ static int __init mips_reboot_setup(void)
        _machine_halt = loongson_halt;
        pm_power_off = loongson_poweroff;
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
        kexec_argv = kmalloc(KEXEC_ARGV_SIZE, GFP_KERNEL);
        if (WARN_ON(!kexec_argv))
                return -ENOMEM;
index e015a26a40f7a55388da15033ad0b2ff08cf4777..498bdc1bb0ede8aafbf1767065a9002fb2e4b26f 100644 (file)
@@ -864,7 +864,7 @@ const struct plat_smp_ops loongson3_smp_ops = {
        .cpu_disable = loongson3_cpu_disable,
        .cpu_die = loongson3_cpu_die,
 #endif
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
        .kexec_nonboot_cpu = kexec_nonboot_cpu_jump,
 #endif
 };
index 8d3eacb50d56013c49ededc48f77c26d245d2ea9..9d44e6630908d2657e102d81501b574671fb0fd4 100644 (file)
@@ -301,7 +301,6 @@ CONFIG_WQ_WATCHDOG=y
 CONFIG_DEBUG_SG=y
 CONFIG_DEBUG_NOTIFIERS=y
 CONFIG_BUG_ON_DATA_CORRUPTION=y
-CONFIG_DEBUG_CREDENTIALS=y
 # CONFIG_FTRACE is not set
 CONFIG_XMON=y
 # CONFIG_RUNTIME_TESTING_MENU is not set
index b1f25bac280b4e824e68315265a2dabab8164b15..71d52a670d951be33d7fb0e3e3219ef3e21ec971 100644 (file)
@@ -385,11 +385,15 @@ static struct vas_window *vas_allocate_window(int vas_id, u64 flags,
         * same fault IRQ is not freed by the OS before.
         */
        mutex_lock(&vas_pseries_mutex);
-       if (migration_in_progress)
+       if (migration_in_progress) {
                rc = -EBUSY;
-       else
+       } else {
                rc = allocate_setup_window(txwin, (u64 *)&domain[0],
                                   cop_feat_caps->win_type);
+               if (!rc)
+                       caps->nr_open_wins_progress++;
+       }
+
        mutex_unlock(&vas_pseries_mutex);
        if (rc)
                goto out;
@@ -404,8 +408,17 @@ static struct vas_window *vas_allocate_window(int vas_id, u64 flags,
                goto out_free;
 
        txwin->win_type = cop_feat_caps->win_type;
-       mutex_lock(&vas_pseries_mutex);
+
        /*
+        * The migration SUSPEND thread sets migration_in_progress and
+        * closes all open windows from the list. But the window is
+        * added to the list after open and modify HCALLs. So possible
+        * that migration_in_progress is set before modify HCALL which
+        * may cause some windows are still open when the hypervisor
+        * initiates the migration.
+        * So checks the migration_in_progress flag again and close all
+        * open windows.
+        *
         * Possible to lose the acquired credit with DLPAR core
         * removal after the window is opened. So if there are any
         * closed windows (means with lost credits), do not give new
@@ -413,9 +426,11 @@ static struct vas_window *vas_allocate_window(int vas_id, u64 flags,
         * after the existing windows are reopened when credits are
         * available.
         */
-       if (!caps->nr_close_wins) {
+       mutex_lock(&vas_pseries_mutex);
+       if (!caps->nr_close_wins && !migration_in_progress) {
                list_add(&txwin->win_list, &caps->list);
                caps->nr_open_windows++;
+               caps->nr_open_wins_progress--;
                mutex_unlock(&vas_pseries_mutex);
                vas_user_win_add_mm_context(&txwin->vas_win.task_ref);
                return &txwin->vas_win;
@@ -433,6 +448,12 @@ out_free:
         */
        free_irq_setup(txwin);
        h_deallocate_vas_window(txwin->vas_win.winid);
+       /*
+        * Hold mutex and reduce nr_open_wins_progress counter.
+        */
+       mutex_lock(&vas_pseries_mutex);
+       caps->nr_open_wins_progress--;
+       mutex_unlock(&vas_pseries_mutex);
 out:
        atomic_dec(&cop_feat_caps->nr_used_credits);
        kfree(txwin);
@@ -937,14 +958,14 @@ int vas_migration_handler(int action)
        struct vas_caps *vcaps;
        int i, rc = 0;
 
+       pr_info("VAS migration event %d\n", action);
+
        /*
         * NX-GZIP is not enabled. Nothing to do for migration.
         */
        if (!copypaste_feat)
                return rc;
 
-       mutex_lock(&vas_pseries_mutex);
-
        if (action == VAS_SUSPEND)
                migration_in_progress = true;
        else
@@ -990,12 +1011,27 @@ int vas_migration_handler(int action)
 
                switch (action) {
                case VAS_SUSPEND:
+                       mutex_lock(&vas_pseries_mutex);
                        rc = reconfig_close_windows(vcaps, vcaps->nr_open_windows,
                                                        true);
+                       /*
+                        * Windows are included in the list after successful
+                        * open. So wait for closing these in-progress open
+                        * windows in vas_allocate_window() which will be
+                        * done if the migration_in_progress is set.
+                        */
+                       while (vcaps->nr_open_wins_progress) {
+                               mutex_unlock(&vas_pseries_mutex);
+                               msleep(10);
+                               mutex_lock(&vas_pseries_mutex);
+                       }
+                       mutex_unlock(&vas_pseries_mutex);
                        break;
                case VAS_RESUME:
+                       mutex_lock(&vas_pseries_mutex);
                        atomic_set(&caps->nr_total_credits, new_nr_creds);
                        rc = reconfig_open_windows(vcaps, new_nr_creds, true);
+                       mutex_unlock(&vas_pseries_mutex);
                        break;
                default:
                        /* should not happen */
@@ -1011,8 +1047,9 @@ int vas_migration_handler(int action)
                        goto out;
        }
 
+       pr_info("VAS migration event (%d) successful\n", action);
+
 out:
-       mutex_unlock(&vas_pseries_mutex);
        return rc;
 }
 
index 7115043ec488307658e9a9a8fdb9b653848abaad..45567cd1317837ac069be2b20b44ac789494be7b 100644 (file)
@@ -91,6 +91,8 @@ struct vas_cop_feat_caps {
 struct vas_caps {
        struct vas_cop_feat_caps caps;
        struct list_head list;  /* List of open windows */
+       int nr_open_wins_progress;      /* Number of open windows in */
+                                       /* progress. Used in migration */
        int nr_close_wins;      /* closed windows in the hypervisor for DLPAR */
        int nr_open_windows;    /* Number of successful open windows */
        u8 feat;                /* Feature type */
index 95a2a06acc6a62412894e491c3bfd5d4a161d15b..24c1799e2ec4905dc9c38148a66b6866fe20e59b 100644 (file)
@@ -685,7 +685,7 @@ config RISCV_BOOT_SPINWAIT
          If unsure what to do here, say N.
 
 config ARCH_SUPPORTS_KEXEC
-       def_bool MMU
+       def_bool y
 
 config ARCH_SELECTS_KEXEC
        def_bool y
@@ -693,7 +693,7 @@ config ARCH_SELECTS_KEXEC
        select HOTPLUG_CPU if SMP
 
 config ARCH_SUPPORTS_KEXEC_FILE
-       def_bool 64BIT && MMU
+       def_bool 64BIT
 
 config ARCH_SELECTS_KEXEC_FILE
        def_bool y
index 294044429e8e15d9230f3b96c7c5579be68857f2..ab00235b018f899e0ca0d0de297a4f14cc9d5c13 100644 (file)
@@ -899,7 +899,7 @@ static inline pte_t pte_swp_clear_exclusive(pte_t pte)
 #define PAGE_KERNEL            __pgprot(0)
 #define swapper_pg_dir         NULL
 #define TASK_SIZE              0xffffffffUL
-#define VMALLOC_START          0
+#define VMALLOC_START          _AC(0, UL)
 #define VMALLOC_END            TASK_SIZE
 
 #endif /* !CONFIG_MMU */
index 55f1d7856b5448c9242df00be2d49d061d4d15b2..8706736fd4e2dca53d096d1caa5117da9fc08873 100644 (file)
@@ -5,17 +5,19 @@
 
 void arch_crash_save_vmcoreinfo(void)
 {
-       VMCOREINFO_NUMBER(VA_BITS);
        VMCOREINFO_NUMBER(phys_ram_base);
 
        vmcoreinfo_append_str("NUMBER(PAGE_OFFSET)=0x%lx\n", PAGE_OFFSET);
        vmcoreinfo_append_str("NUMBER(VMALLOC_START)=0x%lx\n", VMALLOC_START);
        vmcoreinfo_append_str("NUMBER(VMALLOC_END)=0x%lx\n", VMALLOC_END);
+#ifdef CONFIG_MMU
+       VMCOREINFO_NUMBER(VA_BITS);
        vmcoreinfo_append_str("NUMBER(VMEMMAP_START)=0x%lx\n", VMEMMAP_START);
        vmcoreinfo_append_str("NUMBER(VMEMMAP_END)=0x%lx\n", VMEMMAP_END);
 #ifdef CONFIG_64BIT
        vmcoreinfo_append_str("NUMBER(MODULES_VADDR)=0x%lx\n", MODULES_VADDR);
        vmcoreinfo_append_str("NUMBER(MODULES_END)=0x%lx\n", MODULES_END);
+#endif
 #endif
        vmcoreinfo_append_str("NUMBER(KERNEL_LINK_ADDR)=0x%lx\n", KERNEL_LINK_ADDR);
        vmcoreinfo_append_str("NUMBER(va_kernel_pa_offset)=0x%lx\n",
index 438cd92e60801bd3c12cd1f891c5a9009fe115f8..dd06086293106ed963268d0c6c95fdc8c58ef694 100644 (file)
@@ -834,7 +834,6 @@ CONFIG_DEBUG_IRQFLAGS=y
 CONFIG_DEBUG_LIST=y
 CONFIG_DEBUG_SG=y
 CONFIG_DEBUG_NOTIFIERS=y
-CONFIG_DEBUG_CREDENTIALS=y
 CONFIG_RCU_TORTURE_TEST=m
 CONFIG_RCU_REF_SCALE_TEST=m
 CONFIG_RCU_CPU_STALL_TIMEOUT=300
index 927d80ba2332a73dd5ebfb3760b2b2b5137c86bb..76631714673ca8540985b0a1c5cd4bea18ad697c 100644 (file)
@@ -28,7 +28,7 @@
 /* The native architecture */
 #define KEXEC_ARCH KEXEC_ARCH_SH
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 /* arch/sh/kernel/machine_kexec.c */
 void reserve_crashkernel(void);
 
@@ -67,6 +67,6 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
 }
 #else
 static inline void reserve_crashkernel(void) { }
-#endif /* CONFIG_KEXEC */
+#endif /* CONFIG_KEXEC_CORE */
 
 #endif /* __ASM_SH_KEXEC_H */
index 69cd9ac4b2ab8a55c290a42d52bb4cfc0f4926ba..2d7e70537de04c9b731de0ffcadc807c62238754 100644 (file)
@@ -33,7 +33,7 @@ obj-$(CONFIG_SMP)             += smp.o
 obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o
 obj-$(CONFIG_KGDB)             += kgdb.o
 obj-$(CONFIG_MODULES)          += sh_ksyms_32.o module.o
-obj-$(CONFIG_KEXEC)            += machine_kexec.o relocate_kernel.o
+obj-$(CONFIG_KEXEC_CORE)       += machine_kexec.o relocate_kernel.o
 obj-$(CONFIG_CRASH_DUMP)       += crash_dump.o
 obj-$(CONFIG_STACKTRACE)       += stacktrace.o
 obj-$(CONFIG_IO_TRAPPED)       += io_trapped.o
index e8eeedc9b1822d5963cb2df4ce17439835f88e81..1de006b1c3393463632dd66d9a929c9a30d166ef 100644 (file)
@@ -63,7 +63,7 @@ struct machine_ops machine_ops = {
        .shutdown       = native_machine_shutdown,
        .restart        = native_machine_restart,
        .halt           = native_machine_halt,
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
        .crash_shutdown = native_machine_crash_shutdown,
 #endif
 };
@@ -88,7 +88,7 @@ void machine_halt(void)
        machine_ops.halt();
 }
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 void machine_crash_shutdown(struct pt_regs *regs)
 {
        machine_ops.crash_shutdown(regs);
index 3d80515298d268e77f4684bb37782c1c589fc182..d3175f09b3aad9579fc16ceceb800a3d4af7320d 100644 (file)
@@ -220,7 +220,7 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn,
        request_resource(res, &code_resource);
        request_resource(res, &data_resource);
        request_resource(res, &bss_resource);
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
        request_resource(res, &crashk_res);
 #endif
 
index 55c98fdd67d2b7f599ab333d5f1fa1c517c3e4eb..18d15d1ce87d5993946c31579b006594e9c4e9da 100644 (file)
@@ -178,7 +178,7 @@ static unsigned long get_cmdline_acpi_rsdp(void)
 {
        unsigned long addr = 0;
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
        char val[MAX_ADDR_LEN] = { };
        int ret;
 
index 4ccf1994b97adbf8e8f9add7e3ff67d3bb5b3567..d530384f8d60704d474817baa076699af2f24e2d 100644 (file)
 
 #define ICB_0_1_IRQ_MASK ((((u64)ICB_1_IRQ_MASK) << 32) | ICB_0_IRQ_MASK)
 
-#define BUTTRESS_IRQ_MASK ((REG_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, FREQ_CHANGE)) | \
-                          (REG_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, ATS_ERR)) | \
+#define BUTTRESS_IRQ_MASK ((REG_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, ATS_ERR)) | \
                           (REG_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, UFI_ERR)))
 
+#define BUTTRESS_ALL_IRQ_MASK (BUTTRESS_IRQ_MASK | \
+                              (REG_FLD(VPU_37XX_BUTTRESS_INTERRUPT_STAT, FREQ_CHANGE)))
+
 #define BUTTRESS_IRQ_ENABLE_MASK ((u32)~BUTTRESS_IRQ_MASK)
 #define BUTTRESS_IRQ_DISABLE_MASK ((u32)-1)
 
@@ -74,8 +76,12 @@ static void ivpu_hw_wa_init(struct ivpu_device *vdev)
        vdev->wa.clear_runtime_mem = false;
        vdev->wa.d3hot_after_power_off = true;
 
-       if (ivpu_device_id(vdev) == PCI_DEVICE_ID_MTL && ivpu_revision(vdev) < 4)
+       REGB_WR32(VPU_37XX_BUTTRESS_INTERRUPT_STAT, BUTTRESS_ALL_IRQ_MASK);
+       if (REGB_RD32(VPU_37XX_BUTTRESS_INTERRUPT_STAT) == BUTTRESS_ALL_IRQ_MASK) {
+               /* Writing 1s does not clear the interrupt status register */
                vdev->wa.interrupt_clear_with_0 = true;
+               REGB_WR32(VPU_37XX_BUTTRESS_INTERRUPT_STAT, 0x0);
+       }
 
        IVPU_PRINT_WA(punit_disabled);
        IVPU_PRINT_WA(clear_runtime_mem);
index 94fbc3abe60e6a714c546bc2e8c6dce321742bbe..d3c30a28c410eaea470ea797b1114f57e8f6ea10 100644 (file)
@@ -449,9 +449,9 @@ static ssize_t console_show(struct device *dev, struct device_attribute *attr,
        struct sk_buff *skb;
        unsigned int len;
 
-       spin_lock(&card->cli_queue_lock);
+       spin_lock_bh(&card->cli_queue_lock);
        skb = skb_dequeue(&card->cli_queue[SOLOS_CHAN(atmdev)]);
-       spin_unlock(&card->cli_queue_lock);
+       spin_unlock_bh(&card->cli_queue_lock);
        if(skb == NULL)
                return sprintf(buf, "No data.\n");
 
@@ -956,14 +956,14 @@ static void pclose(struct atm_vcc *vcc)
        struct pkt_hdr *header;
 
        /* Remove any yet-to-be-transmitted packets from the pending queue */
-       spin_lock(&card->tx_queue_lock);
+       spin_lock_bh(&card->tx_queue_lock);
        skb_queue_walk_safe(&card->tx_queue[port], skb, tmpskb) {
                if (SKB_CB(skb)->vcc == vcc) {
                        skb_unlink(skb, &card->tx_queue[port]);
                        solos_pop(vcc, skb);
                }
        }
-       spin_unlock(&card->tx_queue_lock);
+       spin_unlock_bh(&card->tx_queue_lock);
 
        skb = alloc_skb(sizeof(*header), GFP_KERNEL);
        if (!skb) {
index ad1acd9b7426b11228004c9a3916c1b119a6b7d0..dbc3950c5960905926d3aaaba205466e70eaf68a 100644 (file)
@@ -767,6 +767,7 @@ config SM_CAMCC_8450
 
 config SM_CAMCC_8550
        tristate "SM8550 Camera Clock Controller"
+       depends on ARM64 || COMPILE_TEST
        select SM_GCC_8550
        help
          Support for the camera clock controller on SM8550 devices.
index aa53797dbfc145b2e921e9d2007e129485df7b29..75071e0cd3216e94c279992c6c90800b5747cbac 100644 (file)
@@ -138,7 +138,7 @@ PNAME(mux_pll_src_5plls_p)  = { "cpll", "gpll", "gpll_div2", "gpll_div3", "usb480
 PNAME(mux_pll_src_4plls_p)     = { "cpll", "gpll", "gpll_div2", "usb480m" };
 PNAME(mux_pll_src_3plls_p)     = { "cpll", "gpll", "gpll_div2" };
 
-PNAME(mux_aclk_peri_src_p)     = { "gpll_peri", "cpll_peri", "gpll_div2_peri", "gpll_div3_peri" };
+PNAME(mux_clk_peri_src_p)      = { "gpll", "cpll", "gpll_div2", "gpll_div3" };
 PNAME(mux_mmc_src_p)           = { "cpll", "gpll", "gpll_div2", "xin24m" };
 PNAME(mux_clk_cif_out_src_p)           = { "clk_cif_src", "xin24m" };
 PNAME(mux_sclk_vop_src_p)      = { "cpll", "gpll", "gpll_div2", "gpll_div3" };
@@ -275,23 +275,17 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
                        RK2928_CLKGATE_CON(0), 11, GFLAGS),
 
        /* PD_PERI */
-       GATE(0, "gpll_peri", "gpll", CLK_IGNORE_UNUSED,
+       COMPOSITE(0, "clk_peri_src", mux_clk_peri_src_p, 0,
+                       RK2928_CLKSEL_CON(10), 14, 2, MFLAGS, 0, 5, DFLAGS,
                        RK2928_CLKGATE_CON(2), 0, GFLAGS),
-       GATE(0, "cpll_peri", "cpll", CLK_IGNORE_UNUSED,
-                       RK2928_CLKGATE_CON(2), 0, GFLAGS),
-       GATE(0, "gpll_div2_peri", "gpll_div2", CLK_IGNORE_UNUSED,
-                       RK2928_CLKGATE_CON(2), 0, GFLAGS),
-       GATE(0, "gpll_div3_peri", "gpll_div3", CLK_IGNORE_UNUSED,
-                       RK2928_CLKGATE_CON(2), 0, GFLAGS),
-       COMPOSITE_NOGATE(0, "aclk_peri_src", mux_aclk_peri_src_p, 0,
-                       RK2928_CLKSEL_CON(10), 14, 2, MFLAGS, 0, 5, DFLAGS),
-       COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "aclk_peri_src", 0,
+
+       COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "clk_peri_src", 0,
                        RK2928_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
                        RK2928_CLKGATE_CON(2), 3, GFLAGS),
-       COMPOSITE_NOMUX(HCLK_PERI, "hclk_peri", "aclk_peri_src", 0,
+       COMPOSITE_NOMUX(HCLK_PERI, "hclk_peri", "clk_peri_src", 0,
                        RK2928_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
                        RK2928_CLKGATE_CON(2), 2, GFLAGS),
-       GATE(ACLK_PERI, "aclk_peri", "aclk_peri_src", 0,
+       GATE(ACLK_PERI, "aclk_peri", "clk_peri_src", 0,
                        RK2928_CLKGATE_CON(2), 1, GFLAGS),
 
        GATE(SCLK_TIMER0, "sclk_timer0", "xin24m", 0,
@@ -316,7 +310,7 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
        GATE(SCLK_MIPI_24M, "clk_mipi_24m", "xin24m", CLK_IGNORE_UNUSED,
                        RK2928_CLKGATE_CON(2), 15, GFLAGS),
 
-       COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0,
+       COMPOSITE(SCLK_SDMMC, "sclk_sdmmc", mux_mmc_src_p, 0,
                        RK2928_CLKSEL_CON(11), 6, 2, MFLAGS, 0, 6, DFLAGS,
                        RK2928_CLKGATE_CON(2), 11, GFLAGS),
 
@@ -490,7 +484,7 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
        GATE(HCLK_I2S_2CH, "hclk_i2s_2ch", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS),
        GATE(0, "hclk_usb_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 13, GFLAGS),
        GATE(HCLK_HOST2, "hclk_host2", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS),
-       GATE(HCLK_OTG, "hclk_otg", "hclk_peri", 0, RK2928_CLKGATE_CON(3), 13, GFLAGS),
+       GATE(HCLK_OTG, "hclk_otg", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 13, GFLAGS),
        GATE(0, "hclk_peri_ahb", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 14, GFLAGS),
        GATE(HCLK_SPDIF, "hclk_spdif", "hclk_peri", 0, RK2928_CLKGATE_CON(10), 9, GFLAGS),
        GATE(HCLK_TSP, "hclk_tsp", "hclk_peri", 0, RK2928_CLKGATE_CON(10), 12, GFLAGS),
index 16dabe2b9c47f483c772ab3b366464ada70df062..db713e1526cdc3cc12298cdc72adb076acd9379b 100644 (file)
@@ -72,6 +72,7 @@ static struct rockchip_pll_rate_table rk3568_pll_rates[] = {
        RK3036_PLL_RATE(408000000, 1, 68, 2, 2, 1, 0),
        RK3036_PLL_RATE(312000000, 1, 78, 6, 1, 1, 0),
        RK3036_PLL_RATE(297000000, 2, 99, 4, 1, 1, 0),
+       RK3036_PLL_RATE(292500000, 1, 195, 4, 4, 1, 0),
        RK3036_PLL_RATE(241500000, 2, 161, 4, 2, 1, 0),
        RK3036_PLL_RATE(216000000, 1, 72, 4, 2, 1, 0),
        RK3036_PLL_RATE(200000000, 1, 100, 3, 4, 1, 0),
index 1cc9be85ba4cd1679838714b91953938b3aeddfc..7d97790b893d709b74fef1d66c05a6ca4150401f 100644 (file)
@@ -363,10 +363,9 @@ resource_size_t cxl_dpa_resource_start(struct cxl_endpoint_decoder *cxled)
 {
        resource_size_t base = -1;
 
-       down_read(&cxl_dpa_rwsem);
+       lockdep_assert_held(&cxl_dpa_rwsem);
        if (cxled->dpa_res)
                base = cxled->dpa_res->start;
-       up_read(&cxl_dpa_rwsem);
 
        return base;
 }
@@ -839,6 +838,8 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
                        cxld->target_type = CXL_DECODER_HOSTONLYMEM;
                else
                        cxld->target_type = CXL_DECODER_DEVMEM;
+
+               guard(rwsem_write)(&cxl_region_rwsem);
                if (cxld->id != cxl_num_decoders_committed(port)) {
                        dev_warn(&port->dev,
                                 "decoder%d.%d: Committed out of order\n",
index fc5c2b414793bb351ae0077857b78e72e153e902..2f43d368ba07308c27a2aba69a3a3330f7413325 100644 (file)
@@ -227,10 +227,16 @@ int cxl_trigger_poison_list(struct cxl_memdev *cxlmd)
        if (!port || !is_cxl_endpoint(port))
                return -EINVAL;
 
-       rc = down_read_interruptible(&cxl_dpa_rwsem);
+       rc = down_read_interruptible(&cxl_region_rwsem);
        if (rc)
                return rc;
 
+       rc = down_read_interruptible(&cxl_dpa_rwsem);
+       if (rc) {
+               up_read(&cxl_region_rwsem);
+               return rc;
+       }
+
        if (cxl_num_decoders_committed(port) == 0) {
                /* No regions mapped to this memdev */
                rc = cxl_get_poison_by_memdev(cxlmd);
@@ -239,6 +245,7 @@ int cxl_trigger_poison_list(struct cxl_memdev *cxlmd)
                rc =  cxl_get_poison_by_endpoint(port);
        }
        up_read(&cxl_dpa_rwsem);
+       up_read(&cxl_region_rwsem);
 
        return rc;
 }
@@ -324,10 +331,16 @@ int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)
        if (!IS_ENABLED(CONFIG_DEBUG_FS))
                return 0;
 
-       rc = down_read_interruptible(&cxl_dpa_rwsem);
+       rc = down_read_interruptible(&cxl_region_rwsem);
        if (rc)
                return rc;
 
+       rc = down_read_interruptible(&cxl_dpa_rwsem);
+       if (rc) {
+               up_read(&cxl_region_rwsem);
+               return rc;
+       }
+
        rc = cxl_validate_poison_dpa(cxlmd, dpa);
        if (rc)
                goto out;
@@ -355,6 +368,7 @@ int cxl_inject_poison(struct cxl_memdev *cxlmd, u64 dpa)
        trace_cxl_poison(cxlmd, cxlr, &record, 0, 0, CXL_POISON_TRACE_INJECT);
 out:
        up_read(&cxl_dpa_rwsem);
+       up_read(&cxl_region_rwsem);
 
        return rc;
 }
@@ -372,10 +386,16 @@ int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa)
        if (!IS_ENABLED(CONFIG_DEBUG_FS))
                return 0;
 
-       rc = down_read_interruptible(&cxl_dpa_rwsem);
+       rc = down_read_interruptible(&cxl_region_rwsem);
        if (rc)
                return rc;
 
+       rc = down_read_interruptible(&cxl_dpa_rwsem);
+       if (rc) {
+               up_read(&cxl_region_rwsem);
+               return rc;
+       }
+
        rc = cxl_validate_poison_dpa(cxlmd, dpa);
        if (rc)
                goto out;
@@ -412,6 +432,7 @@ int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa)
        trace_cxl_poison(cxlmd, cxlr, &record, 0, 0, CXL_POISON_TRACE_CLEAR);
 out:
        up_read(&cxl_dpa_rwsem);
+       up_read(&cxl_region_rwsem);
 
        return rc;
 }
index eff20e83d0a64e8ba791a214f8fb4564135baded..37e1652afbc7eac56fffbb0a5692ea2a1cd82411 100644 (file)
@@ -620,7 +620,7 @@ void read_cdat_data(struct cxl_port *port)
        struct pci_dev *pdev = NULL;
        struct cxl_memdev *cxlmd;
        size_t cdat_length;
-       void *cdat_table;
+       void *cdat_table, *cdat_buf;
        int rc;
 
        if (is_cxl_memdev(uport)) {
@@ -651,16 +651,15 @@ void read_cdat_data(struct cxl_port *port)
                return;
        }
 
-       cdat_table = devm_kzalloc(dev, cdat_length + sizeof(__le32),
-                                 GFP_KERNEL);
-       if (!cdat_table)
+       cdat_buf = devm_kzalloc(dev, cdat_length + sizeof(__le32), GFP_KERNEL);
+       if (!cdat_buf)
                return;
 
-       rc = cxl_cdat_read_table(dev, cdat_doe, cdat_table, &cdat_length);
+       rc = cxl_cdat_read_table(dev, cdat_doe, cdat_buf, &cdat_length);
        if (rc)
                goto err;
 
-       cdat_table = cdat_table + sizeof(__le32);
+       cdat_table = cdat_buf + sizeof(__le32);
        if (cdat_checksum(cdat_table, cdat_length))
                goto err;
 
@@ -670,7 +669,7 @@ void read_cdat_data(struct cxl_port *port)
 
 err:
        /* Don't leave table data allocated on error */
-       devm_kfree(dev, cdat_table);
+       devm_kfree(dev, cdat_buf);
        dev_err(dev, "Failed to read/validate CDAT.\n");
 }
 EXPORT_SYMBOL_NS_GPL(read_cdat_data, CXL);
index 7684c843e5a59c51c6d41556bfb18150c9cbfd26..5d8e06b0ba6e88f383953982cf836c1da8099ec6 100644 (file)
@@ -23,7 +23,7 @@ const struct device_type cxl_pmu_type = {
 
 static void remove_dev(void *dev)
 {
-       device_del(dev);
+       device_unregister(dev);
 }
 
 int devm_cxl_pmu_add(struct device *parent, struct cxl_pmu_regs *regs,
index 38441634e4c68371fa7fc03aee8979e581303fde..b7c93bb18f6e75adfb129e175be5afcba98b10de 100644 (file)
@@ -226,9 +226,9 @@ static ssize_t dpa_resource_show(struct device *dev, struct device_attribute *at
                            char *buf)
 {
        struct cxl_endpoint_decoder *cxled = to_cxl_endpoint_decoder(dev);
-       u64 base = cxl_dpa_resource_start(cxled);
 
-       return sysfs_emit(buf, "%#llx\n", base);
+       guard(rwsem_read)(&cxl_dpa_rwsem);
+       return sysfs_emit(buf, "%#llx\n", (u64)cxl_dpa_resource_start(cxled));
 }
 static DEVICE_ATTR_RO(dpa_resource);
 
index 56e575c79bb49187f909aa87d4f6c5d9894c3b75..3e817a6f94c6a4d2ac5113558a6c7633f7120821 100644 (file)
@@ -2467,10 +2467,6 @@ int cxl_get_poison_by_endpoint(struct cxl_port *port)
        struct cxl_poison_context ctx;
        int rc = 0;
 
-       rc = down_read_interruptible(&cxl_region_rwsem);
-       if (rc)
-               return rc;
-
        ctx = (struct cxl_poison_context) {
                .port = port
        };
@@ -2480,7 +2476,6 @@ int cxl_get_poison_by_endpoint(struct cxl_port *port)
                rc = cxl_get_poison_unmapped(to_cxl_memdev(port->uport_dev),
                                             &ctx);
 
-       up_read(&cxl_region_rwsem);
        return rc;
 }
 
index 6a3abe5b17908dc3fbbfa4812fdc8e6c6ebbb504..b53f46245c377f05520c8275c95bf10c59be34d7 100644 (file)
@@ -828,6 +828,7 @@ void fsl_edma_free_chan_resources(struct dma_chan *chan)
        dma_pool_destroy(fsl_chan->tcd_pool);
        fsl_chan->tcd_pool = NULL;
        fsl_chan->is_sw = false;
+       fsl_chan->srcid = 0;
 }
 
 void fsl_edma_cleanup_vchan(struct dma_device *dmadev)
index 4635e16d7705e9036d644d95159bee216415fff6..238a69bd0d6f5d3ba6d8329543c49d3a750dba21 100644 (file)
@@ -396,9 +396,8 @@ static int fsl_edma3_attach_pd(struct platform_device *pdev, struct fsl_edma_eng
                link = device_link_add(dev, pd_chan, DL_FLAG_STATELESS |
                                             DL_FLAG_PM_RUNTIME |
                                             DL_FLAG_RPM_ACTIVE);
-               if (IS_ERR(link)) {
-                       dev_err(dev, "Failed to add device_link to %d: %ld\n", i,
-                               PTR_ERR(link));
+               if (!link) {
+                       dev_err(dev, "Failed to add device_link to %d\n", i);
                        return -EINVAL;
                }
 
@@ -631,6 +630,8 @@ static int fsl_edma_suspend_late(struct device *dev)
 
        for (i = 0; i < fsl_edma->n_chans; i++) {
                fsl_chan = &fsl_edma->chans[i];
+               if (fsl_edma->chan_masked & BIT(i))
+                       continue;
                spin_lock_irqsave(&fsl_chan->vchan.lock, flags);
                /* Make sure chan is idle or will force disable. */
                if (unlikely(!fsl_chan->idle)) {
@@ -655,13 +656,16 @@ static int fsl_edma_resume_early(struct device *dev)
 
        for (i = 0; i < fsl_edma->n_chans; i++) {
                fsl_chan = &fsl_edma->chans[i];
+               if (fsl_edma->chan_masked & BIT(i))
+                       continue;
                fsl_chan->pm_state = RUNNING;
                edma_write_tcdreg(fsl_chan, 0, csr);
                if (fsl_chan->slave_id != 0)
                        fsl_edma_chan_mux(fsl_chan, fsl_chan->slave_id, true);
        }
 
-       edma_writel(fsl_edma, EDMA_CR_ERGA | EDMA_CR_ERCA, regs->cr);
+       if (!(fsl_edma->drvdata->flags & FSL_EDMA_DRV_SPLIT_REG))
+               edma_writel(fsl_edma, EDMA_CR_ERGA | EDMA_CR_ERCA, regs->cr);
 
        return 0;
 }
index 7b54a3939ea135613f652535433582755220c4cb..315c004f58e4757558dac20cd4536a4fb4a9edd3 100644 (file)
@@ -440,12 +440,14 @@ union wqcfg {
 /*
  * This macro calculates the offset into the GRPCFG register
  * idxd - struct idxd *
- * n - wq id
- * ofs - the index of the 32b dword for the config register
+ * n - group id
+ * ofs - the index of the 64b qword for the config register
  *
- * The WQCFG register block is divided into groups per each wq. The n index
- * allows us to move to the register group that's for that particular wq.
- * Each register is 32bits. The ofs gives us the number of register to access.
+ * The GRPCFG register block is divided into three sub-registers, which
+ * are GRPWQCFG, GRPENGCFG and GRPFLGCFG. The n index allows us to move
+ * to the register block that contains the three sub-registers.
+ * Each register block is 64bits. And the ofs gives us the offset
+ * within the GRPWQCFG register to access.
  */
 #define GRPWQCFG_OFFSET(idxd_dev, n, ofs) ((idxd_dev)->grpcfg_offset +\
                                           (n) * GRPCFG_SIZE + sizeof(u64) * (ofs))
index c01db23e3333f70316ea1bfbca99930fabfdc1cf..3f922518e3a525f22b49c56ae655a670c63aa10e 100644 (file)
@@ -182,13 +182,6 @@ int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc)
 
        portal = idxd_wq_portal_addr(wq);
 
-       /*
-        * The wmb() flushes writes to coherent DMA data before
-        * possibly triggering a DMA read. The wmb() is necessary
-        * even on UP because the recipient is a device.
-        */
-       wmb();
-
        /*
         * Pending the descriptor to the lockless list for the irq_entry
         * that we designated the descriptor to.
@@ -199,6 +192,13 @@ int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc)
                llist_add(&desc->llnode, &ie->pending_llist);
        }
 
+       /*
+        * The wmb() flushes writes to coherent DMA data before
+        * possibly triggering a DMA read. The wmb() is necessary
+        * even on UP because the recipient is a device.
+        */
+       wmb();
+
        if (wq_dedicated(wq)) {
                iosubmit_cmds512(portal, desc->hw, 1);
        } else {
index 72d83cd9ed6bcd41aa8050c00cc41393f01693e5..90857d08a1a7435fc130b168eb155cd2f6e94242 100644 (file)
@@ -1246,8 +1246,8 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_memcpy(
        enum dma_slave_buswidth max_width;
        struct stm32_dma_desc *desc;
        size_t xfer_count, offset;
-       u32 num_sgs, best_burst, dma_burst, threshold;
-       int i;
+       u32 num_sgs, best_burst, threshold;
+       int dma_burst, i;
 
        num_sgs = DIV_ROUND_UP(len, STM32_DMA_ALIGNED_MAX_DATA_ITEMS);
        desc = kzalloc(struct_size(desc, sg_req, num_sgs), GFP_NOWAIT);
@@ -1266,6 +1266,10 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_memcpy(
                best_burst = stm32_dma_get_best_burst(len, STM32_DMA_MAX_BURST,
                                                      threshold, max_width);
                dma_burst = stm32_dma_get_burst(chan, best_burst);
+               if (dma_burst < 0) {
+                       kfree(desc);
+                       return NULL;
+               }
 
                stm32_dma_clear_reg(&desc->sg_req[i].chan_reg);
                desc->sg_req[i].chan_reg.dma_scr =
index 2b6fd6e37c610741563ca80d6372bb3d21225a40..1272b1541f61e2a3e8103c37318bf262a61e4ffa 100644 (file)
@@ -74,7 +74,9 @@ static struct psil_ep am62_src_ep_map[] = {
        PSIL_SAUL(0x7505, 21, 35, 8, 36, 0),
        PSIL_SAUL(0x7506, 22, 43, 8, 43, 0),
        PSIL_SAUL(0x7507, 23, 43, 8, 44, 0),
-       /* PDMA_MAIN0 - SPI0-3 */
+       /* PDMA_MAIN0 - SPI0-2 */
+       PSIL_PDMA_XY_PKT(0x4300),
+       PSIL_PDMA_XY_PKT(0x4301),
        PSIL_PDMA_XY_PKT(0x4302),
        PSIL_PDMA_XY_PKT(0x4303),
        PSIL_PDMA_XY_PKT(0x4304),
@@ -85,8 +87,6 @@ static struct psil_ep am62_src_ep_map[] = {
        PSIL_PDMA_XY_PKT(0x4309),
        PSIL_PDMA_XY_PKT(0x430a),
        PSIL_PDMA_XY_PKT(0x430b),
-       PSIL_PDMA_XY_PKT(0x430c),
-       PSIL_PDMA_XY_PKT(0x430d),
        /* PDMA_MAIN1 - UART0-6 */
        PSIL_PDMA_XY_PKT(0x4400),
        PSIL_PDMA_XY_PKT(0x4401),
@@ -141,7 +141,9 @@ static struct psil_ep am62_dst_ep_map[] = {
        /* SAUL */
        PSIL_SAUL(0xf500, 27, 83, 8, 83, 1),
        PSIL_SAUL(0xf501, 28, 91, 8, 91, 1),
-       /* PDMA_MAIN0 - SPI0-3 */
+       /* PDMA_MAIN0 - SPI0-2 */
+       PSIL_PDMA_XY_PKT(0xc300),
+       PSIL_PDMA_XY_PKT(0xc301),
        PSIL_PDMA_XY_PKT(0xc302),
        PSIL_PDMA_XY_PKT(0xc303),
        PSIL_PDMA_XY_PKT(0xc304),
@@ -152,8 +154,6 @@ static struct psil_ep am62_dst_ep_map[] = {
        PSIL_PDMA_XY_PKT(0xc309),
        PSIL_PDMA_XY_PKT(0xc30a),
        PSIL_PDMA_XY_PKT(0xc30b),
-       PSIL_PDMA_XY_PKT(0xc30c),
-       PSIL_PDMA_XY_PKT(0xc30d),
        /* PDMA_MAIN1 - UART0-6 */
        PSIL_PDMA_XY_PKT(0xc400),
        PSIL_PDMA_XY_PKT(0xc401),
index ca9d71f914220a63bed00563d7bfa51df91fbfc8..4cf9123b0e932640f0974aacc6486b8df00fc656 100644 (file)
@@ -84,7 +84,9 @@ static struct psil_ep am62a_src_ep_map[] = {
        PSIL_SAUL(0x7505, 21, 35, 8, 36, 0),
        PSIL_SAUL(0x7506, 22, 43, 8, 43, 0),
        PSIL_SAUL(0x7507, 23, 43, 8, 44, 0),
-       /* PDMA_MAIN0 - SPI0-3 */
+       /* PDMA_MAIN0 - SPI0-2 */
+       PSIL_PDMA_XY_PKT(0x4300),
+       PSIL_PDMA_XY_PKT(0x4301),
        PSIL_PDMA_XY_PKT(0x4302),
        PSIL_PDMA_XY_PKT(0x4303),
        PSIL_PDMA_XY_PKT(0x4304),
@@ -95,8 +97,6 @@ static struct psil_ep am62a_src_ep_map[] = {
        PSIL_PDMA_XY_PKT(0x4309),
        PSIL_PDMA_XY_PKT(0x430a),
        PSIL_PDMA_XY_PKT(0x430b),
-       PSIL_PDMA_XY_PKT(0x430c),
-       PSIL_PDMA_XY_PKT(0x430d),
        /* PDMA_MAIN1 - UART0-6 */
        PSIL_PDMA_XY_PKT(0x4400),
        PSIL_PDMA_XY_PKT(0x4401),
@@ -151,7 +151,9 @@ static struct psil_ep am62a_dst_ep_map[] = {
        /* SAUL */
        PSIL_SAUL(0xf500, 27, 83, 8, 83, 1),
        PSIL_SAUL(0xf501, 28, 91, 8, 91, 1),
-       /* PDMA_MAIN0 - SPI0-3 */
+       /* PDMA_MAIN0 - SPI0-2 */
+       PSIL_PDMA_XY_PKT(0xc300),
+       PSIL_PDMA_XY_PKT(0xc301),
        PSIL_PDMA_XY_PKT(0xc302),
        PSIL_PDMA_XY_PKT(0xc303),
        PSIL_PDMA_XY_PKT(0xc304),
@@ -162,8 +164,6 @@ static struct psil_ep am62a_dst_ep_map[] = {
        PSIL_PDMA_XY_PKT(0xc309),
        PSIL_PDMA_XY_PKT(0xc30a),
        PSIL_PDMA_XY_PKT(0xc30b),
-       PSIL_PDMA_XY_PKT(0xc30c),
-       PSIL_PDMA_XY_PKT(0xc30d),
        /* PDMA_MAIN1 - UART0-6 */
        PSIL_PDMA_XY_PKT(0xc400),
        PSIL_PDMA_XY_PKT(0xc401),
index 442a0ebeb953e983d053d4c70d919e3a8aee213e..ce7cf736f0208466a1623520ab80cb5eed62cb8f 100644 (file)
@@ -925,7 +925,6 @@ dpll_pin_parent_pin_set(struct dpll_pin *pin, struct nlattr *parent_nest,
                        struct netlink_ext_ack *extack)
 {
        struct nlattr *tb[DPLL_A_PIN_MAX + 1];
-       enum dpll_pin_state state;
        u32 ppin_idx;
        int ret;
 
@@ -936,10 +935,14 @@ dpll_pin_parent_pin_set(struct dpll_pin *pin, struct nlattr *parent_nest,
                return -EINVAL;
        }
        ppin_idx = nla_get_u32(tb[DPLL_A_PIN_PARENT_ID]);
-       state = nla_get_u32(tb[DPLL_A_PIN_STATE]);
-       ret = dpll_pin_on_pin_state_set(pin, ppin_idx, state, extack);
-       if (ret)
-               return ret;
+
+       if (tb[DPLL_A_PIN_STATE]) {
+               enum dpll_pin_state state = nla_get_u32(tb[DPLL_A_PIN_STATE]);
+
+               ret = dpll_pin_on_pin_state_set(pin, ppin_idx, state, extack);
+               if (ret)
+                       return ret;
+       }
 
        return 0;
 }
index 87e730dfefa08d89cae6487726e264d6dd945451..8625de20fc71752018c261445f250d4abc492f1e 100644 (file)
@@ -966,10 +966,10 @@ static int mc_probe(struct platform_device *pdev)
        edac_mc_id = emif_get_id(pdev->dev.of_node);
 
        regval = readl(ddrmc_baseaddr + XDDR_REG_CONFIG0_OFFSET);
-       num_chans = FIELD_PREP(XDDR_REG_CONFIG0_NUM_CHANS_MASK, regval);
+       num_chans = FIELD_GET(XDDR_REG_CONFIG0_NUM_CHANS_MASK, regval);
        num_chans++;
 
-       num_csrows = FIELD_PREP(XDDR_REG_CONFIG0_NUM_RANKS_MASK, regval);
+       num_csrows = FIELD_GET(XDDR_REG_CONFIG0_NUM_RANKS_MASK, regval);
        num_csrows *= 2;
        if (!num_csrows)
                num_csrows = 1;
index 72c71ae201f0dad34ab0b035c7af8eeb525d66ba..d6ec5d4b8dbe0878e029a349e6f7110d6e22bc19 100644 (file)
@@ -35,9 +35,9 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
        return status;
 }
 
-unsigned long kernel_entry_address(void)
+unsigned long kernel_entry_address(unsigned long kernel_addr)
 {
        unsigned long base = (unsigned long)&kernel_offset - kernel_offset;
 
-       return (unsigned long)&kernel_entry - base + VMLINUX_LOAD_ADDRESS;
+       return (unsigned long)&kernel_entry - base + kernel_addr;
 }
index 807cba2693fc177abd3255073a0b56121182ac86..0e0aa6cda73f7c9fbcce5ab354e05e1623583710 100644 (file)
@@ -37,9 +37,9 @@ static efi_status_t exit_boot_func(struct efi_boot_memmap *map, void *priv)
        return EFI_SUCCESS;
 }
 
-unsigned long __weak kernel_entry_address(void)
+unsigned long __weak kernel_entry_address(unsigned long kernel_addr)
 {
-       return *(unsigned long *)(PHYSADDR(VMLINUX_LOAD_ADDRESS) + 8);
+       return *(unsigned long *)(kernel_addr + 8) - VMLINUX_LOAD_ADDRESS + kernel_addr;
 }
 
 efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image,
@@ -73,7 +73,7 @@ efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image,
        csr_write64(CSR_DMW0_INIT, LOONGARCH_CSR_DMWIN0);
        csr_write64(CSR_DMW1_INIT, LOONGARCH_CSR_DMWIN1);
 
-       real_kernel_entry = (void *)kernel_entry_address();
+       real_kernel_entry = (void *)kernel_entry_address(kernel_addr);
 
        real_kernel_entry(true, (unsigned long)cmdline_ptr,
                          (unsigned long)efi_system_table);
index 1bfdae34df3934ecf7cb5e375718b9a687da6976..da9b7b8d0716df3dfbfb8c15160de9828bea4f92 100644 (file)
@@ -307,17 +307,20 @@ static void setup_unaccepted_memory(void)
                efi_err("Memory acceptance protocol failed\n");
 }
 
+static efi_char16_t *efistub_fw_vendor(void)
+{
+       unsigned long vendor = efi_table_attr(efi_system_table, fw_vendor);
+
+       return (efi_char16_t *)vendor;
+}
+
 static const efi_char16_t apple[] = L"Apple";
 
 static void setup_quirks(struct boot_params *boot_params)
 {
-       efi_char16_t *fw_vendor = (efi_char16_t *)(unsigned long)
-               efi_table_attr(efi_system_table, fw_vendor);
-
-       if (!memcmp(fw_vendor, apple, sizeof(apple))) {
-               if (IS_ENABLED(CONFIG_APPLE_PROPERTIES))
-                       retrieve_apple_device_properties(boot_params);
-       }
+       if (IS_ENABLED(CONFIG_APPLE_PROPERTIES) &&
+           !memcmp(efistub_fw_vendor(), apple, sizeof(apple)))
+               retrieve_apple_device_properties(boot_params);
 }
 
 /*
@@ -765,11 +768,25 @@ static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry)
 
        if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && !efi_nokaslr) {
                u64 range = KERNEL_IMAGE_SIZE - LOAD_PHYSICAL_ADDR - kernel_total_size;
+               static const efi_char16_t ami[] = L"American Megatrends";
 
                efi_get_seed(seed, sizeof(seed));
 
                virt_addr += (range * seed[1]) >> 32;
                virt_addr &= ~(CONFIG_PHYSICAL_ALIGN - 1);
+
+               /*
+                * Older Dell systems with AMI UEFI firmware v2.0 may hang
+                * while decompressing the kernel if physical address
+                * randomization is enabled.
+                *
+                * https://bugzilla.kernel.org/show_bug.cgi?id=218173
+                */
+               if (efi_system_table->hdr.revision <= EFI_2_00_SYSTEM_TABLE_REVISION &&
+                   !memcmp(efistub_fw_vendor(), ami, sizeof(ami))) {
+                       efi_debug("AMI firmware v2.0 or older detected - disabling physical KASLR\n");
+                       seed[0] = 0;
+               }
        }
 
        status = efi_random_alloc(alloc_size, CONFIG_PHYSICAL_ALIGN, &addr,
index 1f64d8cbb14df8cd210271107b8cf8bb045249df..8dee52ce26d0cb07d5787218a5ec5b1ea4ba501b 100644 (file)
@@ -4516,8 +4516,6 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
 
        amdgpu_ras_suspend(adev);
 
-       amdgpu_ttm_set_buffer_funcs_status(adev, false);
-
        amdgpu_device_ip_suspend_phase1(adev);
 
        if (!adev->in_s0ix)
index d79b4ca1ecfc4a0028bceb48703ea2cf3d989067..5ad03f2afdb45aa5233c5c48b3e12276513be831 100644 (file)
@@ -1343,6 +1343,8 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo)
 
        abo = ttm_to_amdgpu_bo(bo);
 
+       WARN_ON(abo->vm_bo);
+
        if (abo->kfd_bo)
                amdgpu_amdkfd_release_notify(abo);
 
index a2287bb252235e8eb9a906a9216bbf568a68fd33..a160265ddc07c141ecde4c6bc973655c1a812563 100644 (file)
@@ -642,13 +642,14 @@ static void amdgpu_vm_pt_free(struct amdgpu_vm_bo_base *entry)
 
        if (!entry->bo)
                return;
+
+       entry->bo->vm_bo = NULL;
        shadow = amdgpu_bo_shadowed(entry->bo);
        if (shadow) {
                ttm_bo_set_bulk_move(&shadow->tbo, NULL);
                amdgpu_bo_unref(&shadow);
        }
        ttm_bo_set_bulk_move(&entry->bo->tbo, NULL);
-       entry->bo->vm_bo = NULL;
 
        spin_lock(&entry->vm->status_lock);
        list_del(&entry->vm_status);
index 9df011323d4b975f46053d3aedb269915fb75588..6ede85b28cc8c0bbfd6a7e94c6a3d1a677e958bf 100644 (file)
@@ -155,13 +155,6 @@ static int jpeg_v4_0_5_hw_init(void *handle)
        struct amdgpu_ring *ring = adev->jpeg.inst->ring_dec;
        int r;
 
-       adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
-                               (adev->doorbell_index.vcn.vcn_ring0_1 << 1), 0);
-
-       WREG32_SOC15(VCN, 0, regVCN_JPEG_DB_CTRL,
-               ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT |
-               VCN_JPEG_DB_CTRL__EN_MASK);
-
        r = amdgpu_ring_test_helper(ring);
        if (r)
                return r;
@@ -336,6 +329,14 @@ static int jpeg_v4_0_5_start(struct amdgpu_device *adev)
        if (adev->pm.dpm_enabled)
                amdgpu_dpm_enable_jpeg(adev, true);
 
+       /* doorbell programming is done for every playback */
+       adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
+                               (adev->doorbell_index.vcn.vcn_ring0_1 << 1), 0);
+
+       WREG32_SOC15(VCN, 0, regVCN_JPEG_DB_CTRL,
+               ring->doorbell_index << VCN_JPEG_DB_CTRL__OFFSET__SHIFT |
+               VCN_JPEG_DB_CTRL__EN_MASK);
+
        /* disable power gating */
        r = jpeg_v4_0_5_disable_static_power_gating(adev);
        if (r)
index 45377a1752503b6d69b632b42a78036b524f2f7a..8d5d86675a7fea5e4e5e8bc4e49cdbb580ae17a6 100644 (file)
@@ -813,12 +813,12 @@ static int sdma_v2_4_early_init(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        int r;
 
+       adev->sdma.num_instances = SDMA_MAX_INSTANCE;
+
        r = sdma_v2_4_init_microcode(adev);
        if (r)
                return r;
 
-       adev->sdma.num_instances = SDMA_MAX_INSTANCE;
-
        sdma_v2_4_set_ring_funcs(adev);
        sdma_v2_4_set_buffer_funcs(adev);
        sdma_v2_4_set_vm_pte_funcs(adev);
index 83c240f741b51951f92bbbf11341b3324702ba71..0058f3f7cf6e438b28062722687b52dc8fd67242 100644 (file)
@@ -1643,6 +1643,32 @@ static void sdma_v5_2_get_clockgating_state(void *handle, u64 *flags)
                *flags |= AMD_CG_SUPPORT_SDMA_LS;
 }
 
+static void sdma_v5_2_ring_begin_use(struct amdgpu_ring *ring)
+{
+       struct amdgpu_device *adev = ring->adev;
+
+       /* SDMA 5.2.3 (RMB) FW doesn't seem to properly
+        * disallow GFXOFF in some cases leading to
+        * hangs in SDMA.  Disallow GFXOFF while SDMA is active.
+        * We can probably just limit this to 5.2.3,
+        * but it shouldn't hurt for other parts since
+        * this GFXOFF will be disallowed anyway when SDMA is
+        * active, this just makes it explicit.
+        */
+       amdgpu_gfx_off_ctrl(adev, false);
+}
+
+static void sdma_v5_2_ring_end_use(struct amdgpu_ring *ring)
+{
+       struct amdgpu_device *adev = ring->adev;
+
+       /* SDMA 5.2.3 (RMB) FW doesn't seem to properly
+        * disallow GFXOFF in some cases leading to
+        * hangs in SDMA.  Allow GFXOFF when SDMA is complete.
+        */
+       amdgpu_gfx_off_ctrl(adev, true);
+}
+
 const struct amd_ip_funcs sdma_v5_2_ip_funcs = {
        .name = "sdma_v5_2",
        .early_init = sdma_v5_2_early_init,
@@ -1690,6 +1716,8 @@ static const struct amdgpu_ring_funcs sdma_v5_2_ring_funcs = {
        .test_ib = sdma_v5_2_ring_test_ib,
        .insert_nop = sdma_v5_2_ring_insert_nop,
        .pad_ib = sdma_v5_2_ring_pad_ib,
+       .begin_use = sdma_v5_2_ring_begin_use,
+       .end_use = sdma_v5_2_ring_end_use,
        .emit_wreg = sdma_v5_2_ring_emit_wreg,
        .emit_reg_wait = sdma_v5_2_ring_emit_reg_wait,
        .emit_reg_write_reg_wait = sdma_v5_2_ring_emit_reg_write_reg_wait,
index b452796fc6d39ea6e203346e0218d19adb6e829d..c8c00c2a5224a75989d1a83a5048c63b41d86683 100644 (file)
@@ -5182,6 +5182,9 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
        if (plane->type == DRM_PLANE_TYPE_CURSOR)
                return;
 
+       if (new_plane_state->rotation != DRM_MODE_ROTATE_0)
+               goto ffu;
+
        num_clips = drm_plane_get_damage_clips_count(new_plane_state);
        clips = drm_plane_get_damage_clips(new_plane_state);
 
index 9649934ea186d6484ce8bc44155541f2f6fbc78e..e2a3aa8812df496e7286e9fcd2601ae27767e487 100644 (file)
@@ -465,6 +465,7 @@ struct dc_cursor_mi_param {
        struct fixed31_32 v_scale_ratio;
        enum dc_rotation_angle rotation;
        bool mirror;
+       struct dc_stream_state *stream;
 };
 
 /* IPP related types */
index 139cf31d2e456f0546be62ade92f5cd06a49ac12..89c3bf0fe0c9916d3d725f4d4a72cce2ef349077 100644 (file)
@@ -1077,8 +1077,16 @@ void hubp2_cursor_set_position(
        if (src_y_offset < 0)
                src_y_offset = 0;
        /* Save necessary cursor info x, y position. w, h is saved in attribute func. */
-       hubp->cur_rect.x = src_x_offset + param->viewport.x;
-       hubp->cur_rect.y = src_y_offset + param->viewport.y;
+       if (param->stream->link->psr_settings.psr_version >= DC_PSR_VERSION_SU_1 &&
+           param->rotation != ROTATION_ANGLE_0) {
+               hubp->cur_rect.x = 0;
+               hubp->cur_rect.y = 0;
+               hubp->cur_rect.w = param->stream->timing.h_addressable;
+               hubp->cur_rect.h = param->stream->timing.v_addressable;
+       } else {
+               hubp->cur_rect.x = src_x_offset + param->viewport.x;
+               hubp->cur_rect.y = src_y_offset + param->viewport.y;
+       }
 }
 
 void hubp2_clk_cntl(struct hubp *hubp, bool enable)
index 39cf1ae3a3e16238f59e16db69556a6156cef067..f154a3eb1d1a0ae03252dde817b57627595bc33b 100644 (file)
@@ -124,7 +124,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_5_soc = {
                        .phyclk_mhz = 600.0,
                        .phyclk_d18_mhz = 667.0,
                        .dscclk_mhz = 186.0,
-                       .dtbclk_mhz = 625.0,
+                       .dtbclk_mhz = 600.0,
                },
                {
                        .state = 1,
@@ -133,7 +133,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_5_soc = {
                        .phyclk_mhz = 810.0,
                        .phyclk_d18_mhz = 667.0,
                        .dscclk_mhz = 209.0,
-                       .dtbclk_mhz = 625.0,
+                       .dtbclk_mhz = 600.0,
                },
                {
                        .state = 2,
@@ -142,7 +142,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_5_soc = {
                        .phyclk_mhz = 810.0,
                        .phyclk_d18_mhz = 667.0,
                        .dscclk_mhz = 209.0,
-                       .dtbclk_mhz = 625.0,
+                       .dtbclk_mhz = 600.0,
                },
                {
                        .state = 3,
@@ -151,7 +151,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_5_soc = {
                        .phyclk_mhz = 810.0,
                        .phyclk_d18_mhz = 667.0,
                        .dscclk_mhz = 371.0,
-                       .dtbclk_mhz = 625.0,
+                       .dtbclk_mhz = 600.0,
                },
                {
                        .state = 4,
@@ -160,7 +160,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_5_soc = {
                        .phyclk_mhz = 810.0,
                        .phyclk_d18_mhz = 667.0,
                        .dscclk_mhz = 417.0,
-                       .dtbclk_mhz = 625.0,
+                       .dtbclk_mhz = 600.0,
                },
        },
        .num_states = 5,
@@ -348,6 +348,8 @@ void dcn35_update_bw_bounding_box_fpu(struct dc *dc,
                                clock_limits[i].socclk_mhz;
                        dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].memclk_mhz =
                                clk_table->entries[i].memclk_mhz * clk_table->entries[i].wck_ratio;
+                       dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dtbclk_mhz =
+                               clock_limits[i].dtbclk_mhz;
                        dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dcfclk_levels =
                                clk_table->num_entries;
                        dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_fclk_levels =
@@ -360,6 +362,8 @@ void dcn35_update_bw_bounding_box_fpu(struct dc *dc,
                                clk_table->num_entries;
                        dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_memclk_levels =
                                clk_table->num_entries;
+                       dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dtbclk_levels =
+                               clk_table->num_entries;
                }
        }
 
index 4d1336e5afc2c38c6bb5fa7dbbe363383f75e20d..180f8a98a361a4d07f01c4a7d207ce3ad3196fdf 100644 (file)
@@ -6329,7 +6329,7 @@ static void dml_prefetch_check(struct display_mode_lib_st *mode_lib)
                                mode_lib->ms.NoOfDPPThisState,
                                mode_lib->ms.dpte_group_bytes,
                                s->HostVMInefficiencyFactor,
-                               mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024,
+                               mode_lib->ms.soc.hostvm_min_page_size_kbytes,
                                mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels);
 
                s->NextMaxVStartup = s->MaxVStartupAllPlanes[j];
@@ -6542,7 +6542,7 @@ static void dml_prefetch_check(struct display_mode_lib_st *mode_lib)
                                                mode_lib->ms.cache_display_cfg.plane.HostVMEnable,
                                                mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels,
                                                mode_lib->ms.cache_display_cfg.plane.GPUVMEnable,
-                                               mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024,
+                                               mode_lib->ms.soc.hostvm_min_page_size_kbytes,
                                                mode_lib->ms.PDEAndMetaPTEBytesPerFrame[j][k],
                                                mode_lib->ms.MetaRowBytes[j][k],
                                                mode_lib->ms.DPTEBytesPerRow[j][k],
@@ -7687,7 +7687,7 @@ dml_bool_t dml_core_mode_support(struct display_mode_lib_st *mode_lib)
                CalculateVMRowAndSwath_params->HostVMMaxNonCachedPageTableLevels = mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels;
                CalculateVMRowAndSwath_params->GPUVMMaxPageTableLevels = mode_lib->ms.cache_display_cfg.plane.GPUVMMaxPageTableLevels;
                CalculateVMRowAndSwath_params->GPUVMMinPageSizeKBytes = mode_lib->ms.cache_display_cfg.plane.GPUVMMinPageSizeKBytes;
-               CalculateVMRowAndSwath_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024;
+               CalculateVMRowAndSwath_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes;
                CalculateVMRowAndSwath_params->PTEBufferModeOverrideEn = mode_lib->ms.cache_display_cfg.plane.PTEBufferModeOverrideEn;
                CalculateVMRowAndSwath_params->PTEBufferModeOverrideVal = mode_lib->ms.cache_display_cfg.plane.PTEBufferMode;
                CalculateVMRowAndSwath_params->PTEBufferSizeNotExceeded = mode_lib->ms.PTEBufferSizeNotExceededPerState;
@@ -7957,7 +7957,7 @@ dml_bool_t dml_core_mode_support(struct display_mode_lib_st *mode_lib)
                UseMinimumDCFCLK_params->GPUVMMaxPageTableLevels = mode_lib->ms.cache_display_cfg.plane.GPUVMMaxPageTableLevels;
                UseMinimumDCFCLK_params->HostVMEnable = mode_lib->ms.cache_display_cfg.plane.HostVMEnable;
                UseMinimumDCFCLK_params->NumberOfActiveSurfaces = mode_lib->ms.num_active_planes;
-               UseMinimumDCFCLK_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024;
+               UseMinimumDCFCLK_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes;
                UseMinimumDCFCLK_params->HostVMMaxNonCachedPageTableLevels = mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels;
                UseMinimumDCFCLK_params->DynamicMetadataVMEnabled = mode_lib->ms.ip.dynamic_metadata_vm_enabled;
                UseMinimumDCFCLK_params->ImmediateFlipRequirement = s->ImmediateFlipRequiredFinal;
@@ -8699,7 +8699,7 @@ void dml_core_mode_programming(struct display_mode_lib_st *mode_lib, const struc
        CalculateVMRowAndSwath_params->HostVMMaxNonCachedPageTableLevels = mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels;
        CalculateVMRowAndSwath_params->GPUVMMaxPageTableLevels = mode_lib->ms.cache_display_cfg.plane.GPUVMMaxPageTableLevels;
        CalculateVMRowAndSwath_params->GPUVMMinPageSizeKBytes = mode_lib->ms.cache_display_cfg.plane.GPUVMMinPageSizeKBytes;
-       CalculateVMRowAndSwath_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024;
+       CalculateVMRowAndSwath_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes;
        CalculateVMRowAndSwath_params->PTEBufferModeOverrideEn = mode_lib->ms.cache_display_cfg.plane.PTEBufferModeOverrideEn;
        CalculateVMRowAndSwath_params->PTEBufferModeOverrideVal = mode_lib->ms.cache_display_cfg.plane.PTEBufferMode;
        CalculateVMRowAndSwath_params->PTEBufferSizeNotExceeded = s->dummy_boolean_array[0];
@@ -8805,7 +8805,7 @@ void dml_core_mode_programming(struct display_mode_lib_st *mode_lib, const struc
                        mode_lib->ms.cache_display_cfg.hw.DPPPerSurface,
                        locals->dpte_group_bytes,
                        s->HostVMInefficiencyFactor,
-                       mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024,
+                       mode_lib->ms.soc.hostvm_min_page_size_kbytes,
                        mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels);
 
        locals->TCalc = 24.0 / locals->DCFCLKDeepSleep;
@@ -8995,7 +8995,7 @@ void dml_core_mode_programming(struct display_mode_lib_st *mode_lib, const struc
                        CalculatePrefetchSchedule_params->GPUVMEnable = mode_lib->ms.cache_display_cfg.plane.GPUVMEnable;
                        CalculatePrefetchSchedule_params->HostVMEnable = mode_lib->ms.cache_display_cfg.plane.HostVMEnable;
                        CalculatePrefetchSchedule_params->HostVMMaxNonCachedPageTableLevels = mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels;
-                       CalculatePrefetchSchedule_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024;
+                       CalculatePrefetchSchedule_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes;
                        CalculatePrefetchSchedule_params->DynamicMetadataEnable = mode_lib->ms.cache_display_cfg.plane.DynamicMetadataEnable[k];
                        CalculatePrefetchSchedule_params->DynamicMetadataVMEnabled = mode_lib->ms.ip.dynamic_metadata_vm_enabled;
                        CalculatePrefetchSchedule_params->DynamicMetadataLinesBeforeActiveRequired = mode_lib->ms.cache_display_cfg.plane.DynamicMetadataLinesBeforeActiveRequired[k];
@@ -9240,7 +9240,7 @@ void dml_core_mode_programming(struct display_mode_lib_st *mode_lib, const struc
                                                mode_lib->ms.cache_display_cfg.plane.HostVMEnable,
                                                mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels,
                                                mode_lib->ms.cache_display_cfg.plane.GPUVMEnable,
-                                               mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024,
+                                               mode_lib->ms.soc.hostvm_min_page_size_kbytes,
                                                locals->PDEAndMetaPTEBytesFrame[k],
                                                locals->MetaRowByte[k],
                                                locals->PixelPTEBytesPerRow[k],
index fa8fe5bf7e57566fdb897dfe891692a9d2db781c..db06a5b749b408d04fad1e7df947a08e5b3e096c 100644 (file)
@@ -423,8 +423,9 @@ void dml2_init_soc_states(struct dml2_context *dml2, const struct dc *in_dc,
                }
 
                for (i = 0; i < dml2->config.bbox_overrides.clks_table.num_entries_per_clk.num_dtbclk_levels; i++) {
-                       p->in_states->state_array[i].dtbclk_mhz =
-                               dml2->config.bbox_overrides.clks_table.clk_entries[i].dtbclk_mhz;
+                       if (dml2->config.bbox_overrides.clks_table.clk_entries[i].dtbclk_mhz > 0)
+                               p->in_states->state_array[i].dtbclk_mhz =
+                                       dml2->config.bbox_overrides.clks_table.clk_entries[i].dtbclk_mhz;
                }
 
                for (i = 0; i < dml2->config.bbox_overrides.clks_table.num_entries_per_clk.num_dispclk_levels; i++) {
index 2b8b8366538e96a9dd99b3b6a51a7d08f22b0453..cdb903116eb7ca54e91746324f47ffe18abe70db 100644 (file)
@@ -3417,7 +3417,8 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
                .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz,
                .v_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.vert,
                .rotation = pipe_ctx->plane_state->rotation,
-               .mirror = pipe_ctx->plane_state->horizontal_mirror
+               .mirror = pipe_ctx->plane_state->horizontal_mirror,
+               .stream = pipe_ctx->stream,
        };
        bool pipe_split_on = false;
        bool odm_combine_on = (pipe_ctx->next_odm_pipe != NULL) ||
index 996e4ee99023a8b283219b7cc08537a256db1025..e5cfaaef70b3f7ad01da7d2b4a2359c601e9d19f 100644 (file)
@@ -287,8 +287,8 @@ bool set_default_brightness_aux(struct dc_link *link)
        if (link && link->dpcd_sink_ext_caps.bits.oled == 1) {
                if (!read_default_bl_aux(link, &default_backlight))
                        default_backlight = 150000;
-               // if > 5000, it might be wrong readback
-               if (default_backlight > 5000000)
+               // if < 1 nits or > 5000, it might be wrong readback
+               if (default_backlight < 1000 || default_backlight > 5000000)
                        default_backlight = 150000;
 
                return edp_set_backlight_level_nits(link, true,
index a522a7c0291108cd3ad2f2f57822aa3f758070b6..1675314a3ff20856519666689fb56d36a27c60b8 100644 (file)
@@ -839,6 +839,8 @@ bool is_psr_su_specific_panel(struct dc_link *link)
                                ((dpcd_caps->sink_dev_id_str[1] == 0x08 && dpcd_caps->sink_dev_id_str[0] == 0x08) ||
                                (dpcd_caps->sink_dev_id_str[1] == 0x08 && dpcd_caps->sink_dev_id_str[0] == 0x07)))
                                isPSRSUSupported = false;
+                       else if (dpcd_caps->sink_dev_id_str[1] == 0x08 && dpcd_caps->sink_dev_id_str[0] == 0x03)
+                               isPSRSUSupported = false;
                        else if (dpcd_caps->psr_info.force_psrsu_cap == 0x1)
                                isPSRSUSupported = true;
                }
index ca2ece24e1e07bf97fc4a66e3baf25f0ea5acd13..49028dde0f87b13be19c093d13df7e539c91a2b4 100644 (file)
@@ -2198,10 +2198,10 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_
        } else if (DEVICE_ATTR_IS(xgmi_plpd_policy)) {
                if (amdgpu_dpm_get_xgmi_plpd_mode(adev, NULL) == XGMI_PLPD_NONE)
                        *states = ATTR_STATE_UNSUPPORTED;
-       } else if (DEVICE_ATTR_IS(pp_dpm_mclk_od)) {
+       } else if (DEVICE_ATTR_IS(pp_mclk_od)) {
                if (amdgpu_dpm_get_mclk_od(adev) == -EOPNOTSUPP)
                        *states = ATTR_STATE_UNSUPPORTED;
-       } else if (DEVICE_ATTR_IS(pp_dpm_sclk_od)) {
+       } else if (DEVICE_ATTR_IS(pp_sclk_od)) {
                if (amdgpu_dpm_get_sclk_od(adev) == -EOPNOTSUPP)
                        *states = ATTR_STATE_UNSUPPORTED;
        } else if (DEVICE_ATTR_IS(apu_thermal_cap)) {
index 2ed2585ded3784882dd90260e070e27017a6d1f2..6899b3dc1f12a553c52043c2b73c985e72f627b9 100644 (file)
@@ -236,7 +236,7 @@ static int
 drm_master_check_perm(struct drm_device *dev, struct drm_file *file_priv)
 {
        if (file_priv->was_master &&
-           rcu_access_pointer(file_priv->pid) == task_pid(current))
+           rcu_access_pointer(file_priv->pid) == task_tgid(current))
                return 0;
 
        if (!capable(CAP_SYS_ADMIN))
index df9bf3c9206e717bdb7409ee0c99574df947ed0b..cb90e70d85e862a495f2e8691813161a93b7a030 100644 (file)
@@ -715,8 +715,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
        struct drm_mode_set set;
        uint32_t __user *set_connectors_ptr;
        struct drm_modeset_acquire_ctx ctx;
-       int ret;
-       int i;
+       int ret, i, num_connectors = 0;
 
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return -EOPNOTSUPP;
@@ -871,6 +870,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
                                        connector->name);
 
                        connector_set[i] = connector;
+                       num_connectors++;
                }
        }
 
@@ -879,7 +879,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
        set.y = crtc_req->y;
        set.mode = mode;
        set.connectors = connector_set;
-       set.num_connectors = crtc_req->count_connectors;
+       set.num_connectors = num_connectors;
        set.fb = fb;
 
        if (drm_drv_uses_atomic_modeset(dev))
@@ -892,7 +892,7 @@ out:
                drm_framebuffer_put(fb);
 
        if (connector_set) {
-               for (i = 0; i < crtc_req->count_connectors; i++) {
+               for (i = 0; i < num_connectors; i++) {
                        if (connector_set[i])
                                drm_connector_put(connector_set[i]);
                }
index 39db08f803eac2c08167bb14d2403957ffb0ca0f..3b40650998728cbf70d8ec2aadfc671d31e71612 100644 (file)
@@ -2309,7 +2309,8 @@ int drm_edid_override_connector_update(struct drm_connector *connector)
 
        override = drm_edid_override_get(connector);
        if (override) {
-               num_modes = drm_edid_connector_update(connector, override);
+               if (drm_edid_connector_update(connector, override) == 0)
+                       num_modes = drm_edid_connector_add_modes(connector);
 
                drm_edid_free(override);
 
index dbc1b66c8ee4859edd37450b945959a228832459..1abfafbbfa7571e936f2c839ce0f4377bfda6677 100644 (file)
@@ -650,19 +650,30 @@ intel_dp_update_link_bw_set(struct intel_dp *intel_dp,
                            const struct intel_crtc_state *crtc_state,
                            u8 link_bw, u8 rate_select)
 {
-       u8 link_config[2];
+       u8 lane_count = crtc_state->lane_count;
 
-       /* Write the link configuration data */
-       link_config[0] = link_bw;
-       link_config[1] = crtc_state->lane_count;
        if (crtc_state->enhanced_framing)
-               link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
-       drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_BW_SET, link_config, 2);
+               lane_count |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+
+       if (link_bw) {
+               /* DP and eDP v1.3 and earlier link bw set method. */
+               u8 link_config[] = { link_bw, lane_count };
 
-       /* eDP 1.4 rate select method. */
-       if (!link_bw)
-               drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_RATE_SET,
-                                 &rate_select, 1);
+               drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_BW_SET, link_config,
+                                 ARRAY_SIZE(link_config));
+       } else {
+               /*
+                * eDP v1.4 and later link rate set method.
+                *
+                * eDP v1.4x sinks shall ignore DP_LINK_RATE_SET if
+                * DP_LINK_BW_SET is set. Avoid writing DP_LINK_BW_SET.
+                *
+                * eDP v1.5 sinks allow choosing either, and the last choice
+                * shall be active.
+                */
+               drm_dp_dpcd_writeb(&intel_dp->aux, DP_LANE_COUNT_SET, lane_count);
+               drm_dp_dpcd_writeb(&intel_dp->aux, DP_LINK_RATE_SET, rate_select);
+       }
 }
 
 /*
index 19b35ece31f1b7b245681ea7f58d75a4417b5668..646f367a13f5a064949cfbc91d176c572b9bfc99 100644 (file)
@@ -1374,7 +1374,8 @@ plane_view_scanout_stride(const struct intel_framebuffer *fb, int color_plane,
        struct drm_i915_private *i915 = to_i915(fb->base.dev);
        unsigned int stride_tiles;
 
-       if (IS_ALDERLAKE_P(i915) || DISPLAY_VER(i915) >= 14)
+       if ((IS_ALDERLAKE_P(i915) || DISPLAY_VER(i915) >= 14) &&
+           src_stride_tiles < dst_stride_tiles)
                stride_tiles = src_stride_tiles;
        else
                stride_tiles = dst_stride_tiles;
@@ -1501,8 +1502,20 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p
 
                        size += remap_info->size;
                } else {
-                       unsigned int dst_stride = plane_view_dst_stride_tiles(fb, color_plane,
-                                                                             remap_info->width);
+                       unsigned int dst_stride;
+
+                       /*
+                        * The hardware automagically calculates the CCS AUX surface
+                        * stride from the main surface stride so can't really remap a
+                        * smaller subset (unless we'd remap in whole AUX page units).
+                        */
+                       if (intel_fb_needs_pot_stride_remap(fb) &&
+                           intel_fb_is_ccs_modifier(fb->base.modifier))
+                               dst_stride = remap_info->src_stride;
+                       else
+                               dst_stride = remap_info->width;
+
+                       dst_stride = plane_view_dst_stride_tiles(fb, color_plane, dst_stride);
 
                        assign_chk_ovf(i915, remap_info->dst_stride, dst_stride);
                        color_plane_info->mapping_stride = dst_stride *
index 1e7c97243fcf558611b338ae50d81a33bc552954..8a934bada6245defe0e808ba968d5d24fffdea7c 100644 (file)
@@ -504,7 +504,6 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
 {
        struct drm_plane *plane = NULL;
        struct intel_plane *intel_plane;
-       struct intel_plane_state *plane_state = NULL;
        struct intel_crtc_scaler_state *scaler_state =
                &crtc_state->scaler_state;
        struct drm_atomic_state *drm_state = crtc_state->uapi.state;
@@ -536,6 +535,7 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
 
        /* walkthrough scaler_users bits and start assigning scalers */
        for (i = 0; i < sizeof(scaler_state->scaler_users) * 8; i++) {
+               struct intel_plane_state *plane_state = NULL;
                int *scaler_id;
                const char *name;
                int idx, ret;
index d5ed904f355d5addffa56446f4be412c7b1a385d..6801f8b95c53d1ed989f6bb7c72205b2d7cd236a 100644 (file)
@@ -1293,7 +1293,7 @@ int __intel_engine_reset_bh(struct intel_engine_cs *engine, const char *msg)
        if (msg)
                drm_notice(&engine->i915->drm,
                           "Resetting %s for %s\n", engine->name, msg);
-       atomic_inc(&engine->i915->gpu_error.reset_engine_count[engine->uabi_class]);
+       i915_increase_reset_engine_count(&engine->i915->gpu_error, engine);
 
        ret = intel_gt_reset_engine(engine);
        if (ret) {
index d37698bd6b91aeb1b39ffe729a1cbd76463d361e..17df71117cc70de27e057af8d1b0ac392db3aa5c 100644 (file)
@@ -5001,7 +5001,8 @@ static void capture_error_state(struct intel_guc *guc,
                        if (match) {
                                intel_engine_set_hung_context(e, ce);
                                engine_mask |= e->mask;
-                               atomic_inc(&i915->gpu_error.reset_engine_count[e->uabi_class]);
+                               i915_increase_reset_engine_count(&i915->gpu_error,
+                                                                e);
                        }
                }
 
@@ -5013,7 +5014,7 @@ static void capture_error_state(struct intel_guc *guc,
        } else {
                intel_engine_set_hung_context(ce->engine, ce);
                engine_mask = ce->engine->mask;
-               atomic_inc(&i915->gpu_error.reset_engine_count[ce->engine->uabi_class]);
+               i915_increase_reset_engine_count(&i915->gpu_error, ce->engine);
        }
 
        with_intel_runtime_pm(&i915->runtime_pm, wakeref)
index 9f5971f5e980145d940bb5c59701471071d393cd..48f6c00402c47a255d2cd0fc56fc5b5be3e80a38 100644 (file)
@@ -16,6 +16,7 @@
 
 #include "display/intel_display_device.h"
 #include "gt/intel_engine.h"
+#include "gt/intel_engine_types.h"
 #include "gt/intel_gt_types.h"
 #include "gt/uc/intel_uc_fw.h"
 
@@ -232,7 +233,7 @@ struct i915_gpu_error {
        atomic_t reset_count;
 
        /** Number of times an engine has been reset */
-       atomic_t reset_engine_count[I915_NUM_ENGINES];
+       atomic_t reset_engine_count[MAX_ENGINE_CLASS];
 };
 
 struct drm_i915_error_state_buf {
@@ -255,7 +256,14 @@ static inline u32 i915_reset_count(struct i915_gpu_error *error)
 static inline u32 i915_reset_engine_count(struct i915_gpu_error *error,
                                          const struct intel_engine_cs *engine)
 {
-       return atomic_read(&error->reset_engine_count[engine->uabi_class]);
+       return atomic_read(&error->reset_engine_count[engine->class]);
+}
+
+static inline void
+i915_increase_reset_engine_count(struct i915_gpu_error *error,
+                                const struct intel_engine_cs *engine)
+{
+       atomic_inc(&error->reset_engine_count[engine->class]);
 }
 
 #define CORE_DUMP_FLAG_NONE           0x0
index 4ddc6d902752af31341e03867e74053c2befbbcd..7d41874a49c589a9b14140559e28d8fde58c013e 100644 (file)
@@ -37,8 +37,9 @@ int igt_live_test_begin(struct igt_live_test *t,
                }
 
                for_each_engine(engine, gt, id)
-                       t->reset_engine[id] =
-                       i915_reset_engine_count(&i915->gpu_error, engine);
+                       t->reset_engine[i][id] =
+                               i915_reset_engine_count(&i915->gpu_error,
+                                                       engine);
        }
 
        t->reset_global = i915_reset_count(&i915->gpu_error);
@@ -66,14 +67,14 @@ int igt_live_test_end(struct igt_live_test *t)
 
        for_each_gt(gt, i915, i) {
                for_each_engine(engine, gt, id) {
-                       if (t->reset_engine[id] ==
+                       if (t->reset_engine[i][id] ==
                            i915_reset_engine_count(&i915->gpu_error, engine))
                                continue;
 
                        gt_err(gt, "%s(%s): engine '%s' was reset %d times!\n",
                               t->func, t->name, engine->name,
                               i915_reset_engine_count(&i915->gpu_error, engine) -
-                              t->reset_engine[id]);
+                              t->reset_engine[i][id]);
                        return -EIO;
                }
        }
index 36ed42736c52169e1a4f407ce3de97fbebbde3c5..83e3ad430922fe798ec5098ce15dda4ff3ed4a94 100644 (file)
@@ -7,6 +7,7 @@
 #ifndef IGT_LIVE_TEST_H
 #define IGT_LIVE_TEST_H
 
+#include "gt/intel_gt_defines.h" /* for I915_MAX_GT */
 #include "gt/intel_engine.h" /* for I915_NUM_ENGINES */
 
 struct drm_i915_private;
@@ -17,7 +18,7 @@ struct igt_live_test {
        const char *name;
 
        unsigned int reset_global;
-       unsigned int reset_engine[I915_NUM_ENGINES];
+       unsigned int reset_engine[I915_MAX_GT][I915_NUM_ENGINES];
 };
 
 /*
index f81dc34c9c3ef47c42f82ce4704f144fff7b9296..c1bc8b00d9380ce8f320cb106ca17f461257036b 100644 (file)
@@ -203,7 +203,7 @@ void mtk_gamma_set(struct device *dev, struct drm_crtc_state *state)
        /* Disable RELAY mode to pass the processed image */
        cfg_val &= ~GAMMA_RELAY_MODE;
 
-       cfg_val = readl(gamma->regs + DISP_GAMMA_CFG);
+       writel(cfg_val, gamma->regs + DISP_GAMMA_CFG);
 }
 
 void mtk_gamma_config(struct device *dev, unsigned int w,
index c277b9fae950206d818edcbaab963a83b77615d5..db43f9dff912e40a9dc411d8d7154f0c1261baca 100644 (file)
@@ -788,6 +788,7 @@ static void mtk_drm_crtc_atomic_begin(struct drm_crtc *crtc,
                                                                          crtc);
        struct mtk_crtc_state *mtk_crtc_state = to_mtk_crtc_state(crtc_state);
        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
+       unsigned long flags;
 
        if (mtk_crtc->event && mtk_crtc_state->base.event)
                DRM_ERROR("new event while there is still a pending event\n");
@@ -795,7 +796,11 @@ static void mtk_drm_crtc_atomic_begin(struct drm_crtc *crtc,
        if (mtk_crtc_state->base.event) {
                mtk_crtc_state->base.event->pipe = drm_crtc_index(crtc);
                WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+               spin_lock_irqsave(&crtc->dev->event_lock, flags);
                mtk_crtc->event = mtk_crtc_state->base.event;
+               spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+
                mtk_crtc_state->base.event = NULL;
        }
 }
@@ -921,7 +926,14 @@ static int mtk_drm_crtc_init_comp_planes(struct drm_device *drm_dev,
 
 struct device *mtk_drm_crtc_dma_dev_get(struct drm_crtc *crtc)
 {
-       struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
+       struct mtk_drm_crtc *mtk_crtc = NULL;
+
+       if (!crtc)
+               return NULL;
+
+       mtk_crtc = to_mtk_crtc(crtc);
+       if (!mtk_crtc)
+               return NULL;
 
        return mtk_crtc->dma_dev;
 }
index 2dfaa613276a6d7ef836b2bcbfc2ecac730466f1..2b0c35cacbc6da24b1ff20820e3afaa48256788f 100644 (file)
@@ -443,6 +443,7 @@ static int mtk_drm_kms_init(struct drm_device *drm)
        struct mtk_drm_private *private = drm->dev_private;
        struct mtk_drm_private *priv_n;
        struct device *dma_dev = NULL;
+       struct drm_crtc *crtc;
        int ret, i, j;
 
        if (drm_firmware_drivers_only())
@@ -519,7 +520,9 @@ static int mtk_drm_kms_init(struct drm_device *drm)
        }
 
        /* Use OVL device for all DMA memory allocations */
-       dma_dev = mtk_drm_crtc_dma_dev_get(drm_crtc_from_index(drm, 0));
+       crtc = drm_crtc_from_index(drm, 0);
+       if (crtc)
+               dma_dev = mtk_drm_crtc_dma_dev_get(crtc);
        if (!dma_dev) {
                ret = -ENODEV;
                dev_err(drm->dev, "Need at least one OVL device\n");
index e4279f1772a1b7c8ba53a31a0df941081f4849fc..377d0e0cef8481f33a1a066a87e687f8352ca6f7 100644 (file)
@@ -385,7 +385,7 @@ nvkm_uoutp_mthd_inherit(struct nvkm_outp *outp, void *argv, u32 argc)
 
        /* Ensure an ior is hooked up to this outp already */
        ior = outp->func->inherit(outp);
-       if (!ior)
+       if (!ior || !ior->arm.head)
                return -ENODEV;
 
        /* With iors, there will be a separate output path for each type of connector - and all of
index 1b811d6972a16df8c4335552b2655578510d38f8..201022ae9214a0d508b8240f9b77b8ddb60a126c 100644 (file)
 #include <subdev/mmu.h>
 
 struct gk20a_instobj {
-       struct nvkm_memory memory;
+       struct nvkm_instobj base;
        struct nvkm_mm_node *mn;
        struct gk20a_instmem *imem;
 
        /* CPU mapping */
        u32 *vaddr;
 };
-#define gk20a_instobj(p) container_of((p), struct gk20a_instobj, memory)
+#define gk20a_instobj(p) container_of((p), struct gk20a_instobj, base.memory)
 
 /*
  * Used for objects allocated using the DMA API
@@ -148,7 +148,7 @@ gk20a_instobj_iommu_recycle_vaddr(struct gk20a_instobj_iommu *obj)
        list_del(&obj->vaddr_node);
        vunmap(obj->base.vaddr);
        obj->base.vaddr = NULL;
-       imem->vaddr_use -= nvkm_memory_size(&obj->base.memory);
+       imem->vaddr_use -= nvkm_memory_size(&obj->base.base.memory);
        nvkm_debug(&imem->base.subdev, "vaddr used: %x/%x\n", imem->vaddr_use,
                   imem->vaddr_max);
 }
@@ -283,7 +283,7 @@ gk20a_instobj_map(struct nvkm_memory *memory, u64 offset, struct nvkm_vmm *vmm,
 {
        struct gk20a_instobj *node = gk20a_instobj(memory);
        struct nvkm_vmm_map map = {
-               .memory = &node->memory,
+               .memory = &node->base.memory,
                .offset = offset,
                .mem = node->mn,
        };
@@ -391,8 +391,8 @@ gk20a_instobj_ctor_dma(struct gk20a_instmem *imem, u32 npages, u32 align,
                return -ENOMEM;
        *_node = &node->base;
 
-       nvkm_memory_ctor(&gk20a_instobj_func_dma, &node->base.memory);
-       node->base.memory.ptrs = &gk20a_instobj_ptrs;
+       nvkm_memory_ctor(&gk20a_instobj_func_dma, &node->base.base.memory);
+       node->base.base.memory.ptrs = &gk20a_instobj_ptrs;
 
        node->base.vaddr = dma_alloc_attrs(dev, npages << PAGE_SHIFT,
                                           &node->handle, GFP_KERNEL,
@@ -438,8 +438,8 @@ gk20a_instobj_ctor_iommu(struct gk20a_instmem *imem, u32 npages, u32 align,
        *_node = &node->base;
        node->dma_addrs = (void *)(node->pages + npages);
 
-       nvkm_memory_ctor(&gk20a_instobj_func_iommu, &node->base.memory);
-       node->base.memory.ptrs = &gk20a_instobj_ptrs;
+       nvkm_memory_ctor(&gk20a_instobj_func_iommu, &node->base.base.memory);
+       node->base.base.memory.ptrs = &gk20a_instobj_ptrs;
 
        /* Allocate backing memory */
        for (i = 0; i < npages; i++) {
@@ -533,7 +533,7 @@ gk20a_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero,
        else
                ret = gk20a_instobj_ctor_dma(imem, size >> PAGE_SHIFT,
                                             align, &node);
-       *pmemory = node ? &node->memory : NULL;
+       *pmemory = node ? &node->base.memory : NULL;
        if (ret)
                return ret;
 
index 6e3670508e3a5a48fea062f74c8d3d4abbe413c9..30919c872ac8d50fc638c468cd968e52bc61855e 100644 (file)
@@ -326,7 +326,7 @@ static const struct drm_display_mode ltk050h3148w_mode = {
 static const struct ltk050h3146w_desc ltk050h3148w_data = {
        .mode = &ltk050h3148w_mode,
        .init = ltk050h3148w_init_sequence,
-       .mode_flags = MIPI_DSI_MODE_VIDEO_SYNC_PULSE,
+       .mode_flags = MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_VIDEO_BURST,
 };
 
 static int ltk050h3146w_init_sequence(struct ltk050h3146w *ctx)
index d9e9829b22001aa468c1fd837fc692ce807d313f..b9c7c0ed7bcc37e426f460d8292659fc3246b126 100644 (file)
@@ -347,6 +347,8 @@ static const struct apple_non_apple_keyboard non_apple_keyboards[] = {
        { "Hailuck" },
        { "Jamesdonkey" },
        { "A3R" },
+       { "hfd.cn" },
+       { "WKB603" },
 };
 
 static bool apple_is_non_apple_keyboard(struct hid_device *hdev)
index c6e4e0d1f2147e6221c10e607859354d2c1a32be..72046039d1be755784de32d22b12cdca76f0c9bf 100644 (file)
 
 #define USB_VENDOR_ID_LABTEC           0x1020
 #define USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD 0x0006
+#define USB_DEVICE_ID_LABTEC_ODDOR_HANDBRAKE   0x8888
 
 #define USB_VENDOR_ID_LAVIEW           0x22D4
 #define USB_DEVICE_ID_GLORIOUS_MODEL_I 0x1503
index 7c1b33be9d1343e90a75651daa2b9afc163c5656..149a3c74346b4f28b0f97fba19b99427e85cd89a 100644 (file)
@@ -692,7 +692,8 @@ static int lenovo_event_cptkbd(struct hid_device *hdev,
                 * so set middlebutton_state to 3
                 * to never apply workaround anymore
                 */
-               if (cptkbd_data->middlebutton_state == 1 &&
+               if (hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD &&
+                               cptkbd_data->middlebutton_state == 1 &&
                                usage->type == EV_REL &&
                                (usage->code == REL_X || usage->code == REL_Y)) {
                        cptkbd_data->middlebutton_state = 3;
index ea472923fab07841ba6ee136da95a4a060690c4d..e0bbf0c6345d68ff1b348dde11421ac292fdae78 100644 (file)
@@ -121,6 +121,7 @@ static const struct hid_device_id hid_quirks[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M406XE), HID_QUIRK_MULTI_INPUT },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2), HID_QUIRK_MULTI_INPUT },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_T609A), HID_QUIRK_MULTI_INPUT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_ODDOR_HANDBRAKE), HID_QUIRK_ALWAYS_POLL },
        { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_OPTICAL_USB_MOUSE_600E), HID_QUIRK_ALWAYS_POLL },
        { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D), HID_QUIRK_ALWAYS_POLL },
        { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6019), HID_QUIRK_ALWAYS_POLL },
index ac918a9ea8d34440df8ad9c6a009d60a4ffdbbf0..1b49243adb16a5606038d239be963c35c5b205a3 100644 (file)
@@ -40,6 +40,11 @@ static const struct acpi_device_id i2c_hid_acpi_blacklist[] = {
         * ICN8505 controller, has a _CID of PNP0C50 but is not HID compatible.
         */
        { "CHPN0001" },
+       /*
+        * The IDEA5002 ACPI device causes high interrupt usage and spurious
+        * wakeups from suspend.
+        */
+       { "IDEA5002" },
        { }
 };
 
index 3d6f0a466a9ed48c32915899359ac103b254c1ab..f9f886289b970ab2b351fec3b4c589437e5c101e 100644 (file)
@@ -328,9 +328,6 @@ static int ena_com_create_and_store_tx_meta_desc(struct ena_com_io_sq *io_sq,
         * compare it to the stored version, just create the meta
         */
        if (io_sq->disable_meta_caching) {
-               if (unlikely(!ena_tx_ctx->meta_valid))
-                       return -EINVAL;
-
                *have_meta = true;
                return ena_com_create_meta(io_sq, ena_meta);
        }
index b5bca48148309993402f7ef0b215e94ba66676ed..c44c44e26ddfe74a93b7f1fb3c3ca90f978909e2 100644 (file)
@@ -74,6 +74,8 @@ static void ena_unmap_tx_buff(struct ena_ring *tx_ring,
                              struct ena_tx_buffer *tx_info);
 static int ena_create_io_tx_queues_in_range(struct ena_adapter *adapter,
                                            int first_index, int count);
+static void ena_free_all_io_tx_resources_in_range(struct ena_adapter *adapter,
+                                                 int first_index, int count);
 
 /* Increase a stat by cnt while holding syncp seqlock on 32bit machines */
 static void ena_increase_stat(u64 *statp, u64 cnt,
@@ -457,23 +459,22 @@ static void ena_init_all_xdp_queues(struct ena_adapter *adapter)
 
 static int ena_setup_and_create_all_xdp_queues(struct ena_adapter *adapter)
 {
+       u32 xdp_first_ring = adapter->xdp_first_ring;
+       u32 xdp_num_queues = adapter->xdp_num_queues;
        int rc = 0;
 
-       rc = ena_setup_tx_resources_in_range(adapter, adapter->xdp_first_ring,
-                                            adapter->xdp_num_queues);
+       rc = ena_setup_tx_resources_in_range(adapter, xdp_first_ring, xdp_num_queues);
        if (rc)
                goto setup_err;
 
-       rc = ena_create_io_tx_queues_in_range(adapter,
-                                             adapter->xdp_first_ring,
-                                             adapter->xdp_num_queues);
+       rc = ena_create_io_tx_queues_in_range(adapter, xdp_first_ring, xdp_num_queues);
        if (rc)
                goto create_err;
 
        return 0;
 
 create_err:
-       ena_free_all_io_tx_resources(adapter);
+       ena_free_all_io_tx_resources_in_range(adapter, xdp_first_ring, xdp_num_queues);
 setup_err:
        return rc;
 }
@@ -1492,11 +1493,6 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring,
                if (unlikely(!skb))
                        return NULL;
 
-               /* sync this buffer for CPU use */
-               dma_sync_single_for_cpu(rx_ring->dev,
-                                       dma_unmap_addr(&rx_info->ena_buf, paddr) + pkt_offset,
-                                       len,
-                                       DMA_FROM_DEVICE);
                skb_copy_to_linear_data(skb, buf_addr + buf_offset, len);
                dma_sync_single_for_device(rx_ring->dev,
                                           dma_unmap_addr(&rx_info->ena_buf, paddr) + pkt_offset,
@@ -1515,17 +1511,10 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring,
 
        buf_len = SKB_DATA_ALIGN(len + buf_offset + tailroom);
 
-       pre_reuse_paddr = dma_unmap_addr(&rx_info->ena_buf, paddr);
-
        /* If XDP isn't loaded try to reuse part of the RX buffer */
        reuse_rx_buf_page = !is_xdp_loaded &&
                            ena_try_rx_buf_page_reuse(rx_info, buf_len, len, pkt_offset);
 
-       dma_sync_single_for_cpu(rx_ring->dev,
-                               pre_reuse_paddr + pkt_offset,
-                               len,
-                               DMA_FROM_DEVICE);
-
        if (!reuse_rx_buf_page)
                ena_unmap_rx_buff_attrs(rx_ring, rx_info, DMA_ATTR_SKIP_CPU_SYNC);
 
@@ -1671,20 +1660,23 @@ static void ena_set_rx_hash(struct ena_ring *rx_ring,
        }
 }
 
-static int ena_xdp_handle_buff(struct ena_ring *rx_ring, struct xdp_buff *xdp)
+static int ena_xdp_handle_buff(struct ena_ring *rx_ring, struct xdp_buff *xdp, u16 num_descs)
 {
        struct ena_rx_buffer *rx_info;
        int ret;
 
+       /* XDP multi-buffer packets not supported */
+       if (unlikely(num_descs > 1)) {
+               netdev_err_once(rx_ring->adapter->netdev,
+                               "xdp: dropped unsupported multi-buffer packets\n");
+               ena_increase_stat(&rx_ring->rx_stats.xdp_drop, 1, &rx_ring->syncp);
+               return ENA_XDP_DROP;
+       }
+
        rx_info = &rx_ring->rx_buffer_info[rx_ring->ena_bufs[0].req_id];
        xdp_prepare_buff(xdp, page_address(rx_info->page),
                         rx_info->buf_offset,
                         rx_ring->ena_bufs[0].len, false);
-       /* If for some reason we received a bigger packet than
-        * we expect, then we simply drop it
-        */
-       if (unlikely(rx_ring->ena_bufs[0].len > ENA_XDP_MAX_MTU))
-               return ENA_XDP_DROP;
 
        ret = ena_xdp_execute(rx_ring, xdp);
 
@@ -1719,6 +1711,7 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi,
        int xdp_flags = 0;
        int total_len = 0;
        int xdp_verdict;
+       u8 pkt_offset;
        int rc = 0;
        int i;
 
@@ -1745,15 +1738,21 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi,
 
                /* First descriptor might have an offset set by the device */
                rx_info = &rx_ring->rx_buffer_info[rx_ring->ena_bufs[0].req_id];
-               rx_info->buf_offset += ena_rx_ctx.pkt_offset;
+               pkt_offset = ena_rx_ctx.pkt_offset;
+               rx_info->buf_offset += pkt_offset;
 
                netif_dbg(rx_ring->adapter, rx_status, rx_ring->netdev,
                          "rx_poll: q %d got packet from ena. descs #: %d l3 proto %d l4 proto %d hash: %x\n",
                          rx_ring->qid, ena_rx_ctx.descs, ena_rx_ctx.l3_proto,
                          ena_rx_ctx.l4_proto, ena_rx_ctx.hash);
 
+               dma_sync_single_for_cpu(rx_ring->dev,
+                                       dma_unmap_addr(&rx_info->ena_buf, paddr) + pkt_offset,
+                                       rx_ring->ena_bufs[0].len,
+                                       DMA_FROM_DEVICE);
+
                if (ena_xdp_present_ring(rx_ring))
-                       xdp_verdict = ena_xdp_handle_buff(rx_ring, &xdp);
+                       xdp_verdict = ena_xdp_handle_buff(rx_ring, &xdp, ena_rx_ctx.descs);
 
                /* allocate skb and fill it */
                if (xdp_verdict == ENA_XDP_PASS)
@@ -1777,7 +1776,7 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi,
                                if (xdp_verdict & ENA_XDP_FORWARDED) {
                                        ena_unmap_rx_buff_attrs(rx_ring,
                                                                &rx_ring->rx_buffer_info[req_id],
-                                                               0);
+                                                               DMA_ATTR_SKIP_CPU_SYNC);
                                        rx_ring->rx_buffer_info[req_id].page = NULL;
                                }
                        }
index 694daeaf3e6150b3c0581f354bad9ce5a93eed0b..e1885c1eb100a1fa67c0588832a991718728562c 100644 (file)
@@ -938,11 +938,14 @@ void aq_ring_free(struct aq_ring_s *self)
                return;
 
        kfree(self->buff_ring);
+       self->buff_ring = NULL;
 
-       if (self->dx_ring)
+       if (self->dx_ring) {
                dma_free_coherent(aq_nic_get_dev(self->aq_nic),
                                  self->size * self->dx_size, self->dx_ring,
                                  self->dx_ring_pa);
+               self->dx_ring = NULL;
+       }
 }
 
 unsigned int aq_ring_fill_stats_data(struct aq_ring_s *self, u64 *data)
index d0359b569afeb17e3ef1340bac5b3645636af237..579eebb6fc566364dc94c4b7c890d8f547e200d5 100644 (file)
@@ -1748,16 +1748,32 @@ static void bnxt_tpa_agg(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
 static void bnxt_deliver_skb(struct bnxt *bp, struct bnxt_napi *bnapi,
                             struct sk_buff *skb)
 {
+       skb_mark_for_recycle(skb);
+
        if (skb->dev != bp->dev) {
                /* this packet belongs to a vf-rep */
                bnxt_vf_rep_rx(bp, skb);
                return;
        }
        skb_record_rx_queue(skb, bnapi->index);
-       skb_mark_for_recycle(skb);
        napi_gro_receive(&bnapi->napi, skb);
 }
 
+static bool bnxt_rx_ts_valid(struct bnxt *bp, u32 flags,
+                            struct rx_cmp_ext *rxcmp1, u32 *cmpl_ts)
+{
+       u32 ts = le32_to_cpu(rxcmp1->rx_cmp_timestamp);
+
+       if (BNXT_PTP_RX_TS_VALID(flags))
+               goto ts_valid;
+       if (!bp->ptp_all_rx_tstamp || !ts || !BNXT_ALL_RX_TS_VALID(flags))
+               return false;
+
+ts_valid:
+       *cmpl_ts = ts;
+       return true;
+}
+
 /* returns the following:
  * 1       - 1 packet successfully received
  * 0       - successful TPA_START, packet not completed yet
@@ -1783,6 +1799,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
        struct sk_buff *skb;
        struct xdp_buff xdp;
        u32 flags, misc;
+       u32 cmpl_ts;
        void *data;
        int rc = 0;
 
@@ -2005,10 +2022,8 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
                }
        }
 
-       if (unlikely((flags & RX_CMP_FLAGS_ITYPES_MASK) ==
-                    RX_CMP_FLAGS_ITYPE_PTP_W_TS) || bp->ptp_all_rx_tstamp) {
+       if (bnxt_rx_ts_valid(bp, flags, rxcmp1, &cmpl_ts)) {
                if (bp->flags & BNXT_FLAG_CHIP_P5) {
-                       u32 cmpl_ts = le32_to_cpu(rxcmp1->rx_cmp_timestamp);
                        u64 ns, ts;
 
                        if (!bnxt_get_rx_ts_p5(bp, &ts, cmpl_ts)) {
@@ -10731,10 +10746,8 @@ static void __bnxt_close_nic(struct bnxt *bp, bool irq_re_init,
        bnxt_free_mem(bp, irq_re_init);
 }
 
-int bnxt_close_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
+void bnxt_close_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
 {
-       int rc = 0;
-
        if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) {
                /* If we get here, it means firmware reset is in progress
                 * while we are trying to close.  We can safely proceed with
@@ -10749,15 +10762,18 @@ int bnxt_close_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
 
 #ifdef CONFIG_BNXT_SRIOV
        if (bp->sriov_cfg) {
+               int rc;
+
                rc = wait_event_interruptible_timeout(bp->sriov_cfg_wait,
                                                      !bp->sriov_cfg,
                                                      BNXT_SRIOV_CFG_WAIT_TMO);
-               if (rc)
-                       netdev_warn(bp->dev, "timeout waiting for SRIOV config operation to complete!\n");
+               if (!rc)
+                       netdev_warn(bp->dev, "timeout waiting for SRIOV config operation to complete, proceeding to close!\n");
+               else if (rc < 0)
+                       netdev_warn(bp->dev, "SRIOV config operation interrupted, proceeding to close!\n");
        }
 #endif
        __bnxt_close_nic(bp, irq_re_init, link_re_init);
-       return rc;
 }
 
 static int bnxt_close(struct net_device *dev)
@@ -13940,6 +13956,8 @@ static int bnxt_resume(struct device *device)
        if (rc)
                goto resume_exit;
 
+       bnxt_clear_reservations(bp, true);
+
        if (bnxt_hwrm_func_drv_rgtr(bp, NULL, 0, false)) {
                rc = -ENODEV;
                goto resume_exit;
index e702dbc3e6b131d1bf622be3ae781201a9f8e5f3..a7d7b09ea16202579794baad15cde8e4764f89e9 100644 (file)
@@ -161,7 +161,7 @@ struct rx_cmp {
        #define RX_CMP_FLAGS_ERROR                              (1 << 6)
        #define RX_CMP_FLAGS_PLACEMENT                          (7 << 7)
        #define RX_CMP_FLAGS_RSS_VALID                          (1 << 10)
-       #define RX_CMP_FLAGS_UNUSED                             (1 << 11)
+       #define RX_CMP_FLAGS_PKT_METADATA_PRESENT               (1 << 11)
         #define RX_CMP_FLAGS_ITYPES_SHIFT                       12
         #define RX_CMP_FLAGS_ITYPES_MASK                        0xf000
         #define RX_CMP_FLAGS_ITYPE_UNKNOWN                      (0 << 12)
@@ -188,6 +188,12 @@ struct rx_cmp {
        __le32 rx_cmp_rss_hash;
 };
 
+#define BNXT_PTP_RX_TS_VALID(flags)                            \
+       (((flags) & RX_CMP_FLAGS_ITYPES_MASK) == RX_CMP_FLAGS_ITYPE_PTP_W_TS)
+
+#define BNXT_ALL_RX_TS_VALID(flags)                            \
+       !((flags) & RX_CMP_FLAGS_PKT_METADATA_PRESENT)
+
 #define RX_CMP_HASH_VALID(rxcmp)                               \
        ((rxcmp)->rx_cmp_len_flags_type & cpu_to_le32(RX_CMP_FLAGS_RSS_VALID))
 
@@ -2375,7 +2381,7 @@ int bnxt_open_nic(struct bnxt *, bool, bool);
 int bnxt_half_open_nic(struct bnxt *bp);
 void bnxt_half_close_nic(struct bnxt *bp);
 void bnxt_reenable_sriov(struct bnxt *bp);
-int bnxt_close_nic(struct bnxt *, bool, bool);
+void bnxt_close_nic(struct bnxt *, bool, bool);
 void bnxt_get_ring_err_stats(struct bnxt *bp,
                             struct bnxt_total_ring_err_stats *stats);
 int bnxt_dbg_hwrm_rd_reg(struct bnxt *bp, u32 reg_off, u16 num_words,
index f302dac565996d11f7d6f1f35d8100fd6aad9896..89809f1b129c0e6c4a19394599003cabdb25caf5 100644 (file)
@@ -449,15 +449,8 @@ static int bnxt_dl_reload_down(struct devlink *dl, bool netns_change,
                        return -ENODEV;
                }
                bnxt_ulp_stop(bp);
-               if (netif_running(bp->dev)) {
-                       rc = bnxt_close_nic(bp, true, true);
-                       if (rc) {
-                               NL_SET_ERR_MSG_MOD(extack, "Failed to close");
-                               dev_close(bp->dev);
-                               rtnl_unlock();
-                               break;
-                       }
-               }
+               if (netif_running(bp->dev))
+                       bnxt_close_nic(bp, true, true);
                bnxt_vf_reps_free(bp);
                rc = bnxt_hwrm_func_drv_unrgtr(bp);
                if (rc) {
index f3f384773ac038ada07b65a357bc411df2ffdfe8..5f67a7f94e7d1f3a72d037b94743c5531fc105d3 100644 (file)
@@ -165,9 +165,8 @@ static int bnxt_set_coalesce(struct net_device *dev,
 reset_coalesce:
        if (test_bit(BNXT_STATE_OPEN, &bp->state)) {
                if (update_stats) {
-                       rc = bnxt_close_nic(bp, true, false);
-                       if (!rc)
-                               rc = bnxt_open_nic(bp, true, false);
+                       bnxt_close_nic(bp, true, false);
+                       rc = bnxt_open_nic(bp, true, false);
                } else {
                        rc = bnxt_hwrm_set_coal(bp);
                }
@@ -972,12 +971,7 @@ static int bnxt_set_channels(struct net_device *dev,
                         * before PF unload
                         */
                }
-               rc = bnxt_close_nic(bp, true, false);
-               if (rc) {
-                       netdev_err(bp->dev, "Set channel failure rc :%x\n",
-                                  rc);
-                       return rc;
-               }
+               bnxt_close_nic(bp, true, false);
        }
 
        if (sh) {
@@ -4042,12 +4036,7 @@ static void bnxt_self_test(struct net_device *dev, struct ethtool_test *etest,
                bnxt_run_fw_tests(bp, test_mask, &test_results);
        } else {
                bnxt_ulp_stop(bp);
-               rc = bnxt_close_nic(bp, true, false);
-               if (rc) {
-                       etest->flags |= ETH_TEST_FL_FAILED;
-                       bnxt_ulp_start(bp, rc);
-                       return;
-               }
+               bnxt_close_nic(bp, true, false);
                bnxt_run_fw_tests(bp, test_mask, &test_results);
 
                buf[BNXT_MACLPBK_TEST_IDX] = 1;
index f3886710e77873a83e8b8aad3eb2f3e2ba7d465e..6e3da3362bd6177765dd5c9ebd888c2c387d7338 100644 (file)
@@ -521,9 +521,8 @@ static int bnxt_hwrm_ptp_cfg(struct bnxt *bp)
 
        if (netif_running(bp->dev)) {
                if (ptp->rx_filter == HWTSTAMP_FILTER_ALL) {
-                       rc = bnxt_close_nic(bp, false, false);
-                       if (!rc)
-                               rc = bnxt_open_nic(bp, false, false);
+                       bnxt_close_nic(bp, false, false);
+                       rc = bnxt_open_nic(bp, false, false);
                } else {
                        bnxt_ptp_cfg_tstamp_filters(bp);
                }
index 4798fb7fe35d14070acf82e25ae5d63a8d1bb3e5..b6a534a3e0b123007070ce4511d300bb20186951 100644 (file)
@@ -139,7 +139,8 @@ int dpaa2_switch_acl_entry_add(struct dpaa2_switch_filter_block *filter_block,
        err = dpsw_acl_add_entry(ethsw->mc_io, 0, ethsw->dpsw_handle,
                                 filter_block->acl_id, acl_entry_cfg);
 
-       dma_unmap_single(dev, acl_entry_cfg->key_iova, sizeof(cmd_buff),
+       dma_unmap_single(dev, acl_entry_cfg->key_iova,
+                        DPAA2_ETHSW_PORT_ACL_CMD_BUF_SIZE,
                         DMA_TO_DEVICE);
        if (err) {
                dev_err(dev, "dpsw_acl_add_entry() failed %d\n", err);
@@ -181,8 +182,8 @@ dpaa2_switch_acl_entry_remove(struct dpaa2_switch_filter_block *block,
        err = dpsw_acl_remove_entry(ethsw->mc_io, 0, ethsw->dpsw_handle,
                                    block->acl_id, acl_entry_cfg);
 
-       dma_unmap_single(dev, acl_entry_cfg->key_iova, sizeof(cmd_buff),
-                        DMA_TO_DEVICE);
+       dma_unmap_single(dev, acl_entry_cfg->key_iova,
+                        DPAA2_ETHSW_PORT_ACL_CMD_BUF_SIZE, DMA_TO_DEVICE);
        if (err) {
                dev_err(dev, "dpsw_acl_remove_entry() failed %d\n", err);
                kfree(cmd_buff);
index 97d3151076d534d51cde377c98348f30acf459f9..e01a246124ac69955476f20bd42a1e6ab9032871 100644 (file)
@@ -1998,9 +1998,6 @@ static int dpaa2_switch_port_attr_set_event(struct net_device *netdev,
        return notifier_from_errno(err);
 }
 
-static struct notifier_block dpaa2_switch_port_switchdev_nb;
-static struct notifier_block dpaa2_switch_port_switchdev_blocking_nb;
-
 static int dpaa2_switch_port_bridge_join(struct net_device *netdev,
                                         struct net_device *upper_dev,
                                         struct netlink_ext_ack *extack)
@@ -2043,9 +2040,7 @@ static int dpaa2_switch_port_bridge_join(struct net_device *netdev,
                goto err_egress_flood;
 
        err = switchdev_bridge_port_offload(netdev, netdev, NULL,
-                                           &dpaa2_switch_port_switchdev_nb,
-                                           &dpaa2_switch_port_switchdev_blocking_nb,
-                                           false, extack);
+                                           NULL, NULL, false, extack);
        if (err)
                goto err_switchdev_offload;
 
@@ -2079,9 +2074,7 @@ static int dpaa2_switch_port_restore_rxvlan(struct net_device *vdev, int vid, vo
 
 static void dpaa2_switch_port_pre_bridge_leave(struct net_device *netdev)
 {
-       switchdev_bridge_port_unoffload(netdev, NULL,
-                                       &dpaa2_switch_port_switchdev_nb,
-                                       &dpaa2_switch_port_switchdev_blocking_nb);
+       switchdev_bridge_port_unoffload(netdev, NULL, NULL, NULL);
 }
 
 static int dpaa2_switch_port_bridge_leave(struct net_device *netdev)
index c3b7694a74851c1a9bb2e84ca7621b6bb72b40ba..e08c7b572497d386a8cc90a09ef4cf2caad18810 100644 (file)
@@ -3731,31 +3731,26 @@ static int fec_set_features(struct net_device *netdev,
        return 0;
 }
 
-static u16 fec_enet_get_raw_vlan_tci(struct sk_buff *skb)
-{
-       struct vlan_ethhdr *vhdr;
-       unsigned short vlan_TCI = 0;
-
-       if (skb->protocol == htons(ETH_P_ALL)) {
-               vhdr = (struct vlan_ethhdr *)(skb->data);
-               vlan_TCI = ntohs(vhdr->h_vlan_TCI);
-       }
-
-       return vlan_TCI;
-}
-
 static u16 fec_enet_select_queue(struct net_device *ndev, struct sk_buff *skb,
                                 struct net_device *sb_dev)
 {
        struct fec_enet_private *fep = netdev_priv(ndev);
-       u16 vlan_tag;
+       u16 vlan_tag = 0;
 
        if (!(fep->quirks & FEC_QUIRK_HAS_AVB))
                return netdev_pick_tx(ndev, skb, NULL);
 
-       vlan_tag = fec_enet_get_raw_vlan_tci(skb);
-       if (!vlan_tag)
+       /* VLAN is present in the payload.*/
+       if (eth_type_vlan(skb->protocol)) {
+               struct vlan_ethhdr *vhdr = skb_vlan_eth_hdr(skb);
+
+               vlan_tag = ntohs(vhdr->h_vlan_TCI);
+       /*  VLAN is present in the skb but not yet pushed in the payload.*/
+       } else if (skb_vlan_tag_present(skb)) {
+               vlan_tag = skb->vlan_tci;
+       } else {
                return vlan_tag;
+       }
 
        return fec_enet_vlan_pri_to_queue[vlan_tag >> 13];
 }
index e7ab89dc883aa63927e15e1e1383ae271e38348f..63b45c61cc4aa3631a3e5715af64d60c9b48d326 100644 (file)
@@ -292,6 +292,7 @@ struct iavf_adapter {
 #define IAVF_FLAG_QUEUES_DISABLED              BIT(17)
 #define IAVF_FLAG_SETUP_NETDEV_FEATURES                BIT(18)
 #define IAVF_FLAG_REINIT_MSIX_NEEDED           BIT(20)
+#define IAVF_FLAG_FDIR_ENABLED                 BIT(21)
 /* duplicates for common code */
 #define IAVF_FLAG_DCB_ENABLED                  0
        /* flags for admin queue service task */
index 19cbfe554689f4718f8366d0792b2d19c678f2e3..dc499fe7734ec9afee6c5794f568e7e6d189f721 100644 (file)
@@ -1061,7 +1061,7 @@ iavf_get_ethtool_fdir_entry(struct iavf_adapter *adapter,
        struct iavf_fdir_fltr *rule = NULL;
        int ret = 0;
 
-       if (!FDIR_FLTR_SUPPORT(adapter))
+       if (!(adapter->flags & IAVF_FLAG_FDIR_ENABLED))
                return -EOPNOTSUPP;
 
        spin_lock_bh(&adapter->fdir_fltr_lock);
@@ -1203,7 +1203,7 @@ iavf_get_fdir_fltr_ids(struct iavf_adapter *adapter, struct ethtool_rxnfc *cmd,
        unsigned int cnt = 0;
        int val = 0;
 
-       if (!FDIR_FLTR_SUPPORT(adapter))
+       if (!(adapter->flags & IAVF_FLAG_FDIR_ENABLED))
                return -EOPNOTSUPP;
 
        cmd->data = IAVF_MAX_FDIR_FILTERS;
@@ -1395,7 +1395,7 @@ static int iavf_add_fdir_ethtool(struct iavf_adapter *adapter, struct ethtool_rx
        int count = 50;
        int err;
 
-       if (!FDIR_FLTR_SUPPORT(adapter))
+       if (!(adapter->flags & IAVF_FLAG_FDIR_ENABLED))
                return -EOPNOTSUPP;
 
        if (fsp->flow_type & FLOW_MAC_EXT)
@@ -1436,12 +1436,16 @@ static int iavf_add_fdir_ethtool(struct iavf_adapter *adapter, struct ethtool_rx
        spin_lock_bh(&adapter->fdir_fltr_lock);
        iavf_fdir_list_add_fltr(adapter, fltr);
        adapter->fdir_active_fltr++;
-       fltr->state = IAVF_FDIR_FLTR_ADD_REQUEST;
-       adapter->aq_required |= IAVF_FLAG_AQ_ADD_FDIR_FILTER;
+       if (adapter->link_up) {
+               fltr->state = IAVF_FDIR_FLTR_ADD_REQUEST;
+               adapter->aq_required |= IAVF_FLAG_AQ_ADD_FDIR_FILTER;
+       } else {
+               fltr->state = IAVF_FDIR_FLTR_INACTIVE;
+       }
        spin_unlock_bh(&adapter->fdir_fltr_lock);
 
-       mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0);
-
+       if (adapter->link_up)
+               mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0);
 ret:
        if (err && fltr)
                kfree(fltr);
@@ -1463,7 +1467,7 @@ static int iavf_del_fdir_ethtool(struct iavf_adapter *adapter, struct ethtool_rx
        struct iavf_fdir_fltr *fltr = NULL;
        int err = 0;
 
-       if (!FDIR_FLTR_SUPPORT(adapter))
+       if (!(adapter->flags & IAVF_FLAG_FDIR_ENABLED))
                return -EOPNOTSUPP;
 
        spin_lock_bh(&adapter->fdir_fltr_lock);
@@ -1472,6 +1476,11 @@ static int iavf_del_fdir_ethtool(struct iavf_adapter *adapter, struct ethtool_rx
                if (fltr->state == IAVF_FDIR_FLTR_ACTIVE) {
                        fltr->state = IAVF_FDIR_FLTR_DEL_REQUEST;
                        adapter->aq_required |= IAVF_FLAG_AQ_DEL_FDIR_FILTER;
+               } else if (fltr->state == IAVF_FDIR_FLTR_INACTIVE) {
+                       list_del(&fltr->list);
+                       kfree(fltr);
+                       adapter->fdir_active_fltr--;
+                       fltr = NULL;
                } else {
                        err = -EBUSY;
                }
@@ -1780,7 +1789,7 @@ static int iavf_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,
                ret = 0;
                break;
        case ETHTOOL_GRXCLSRLCNT:
-               if (!FDIR_FLTR_SUPPORT(adapter))
+               if (!(adapter->flags & IAVF_FLAG_FDIR_ENABLED))
                        break;
                spin_lock_bh(&adapter->fdir_fltr_lock);
                cmd->rule_cnt = adapter->fdir_active_fltr;
index 9eb9f73f6adf3a52b42d0751032adff5fad9bcc0..d31bd923ba8cbf2d86272f6955847cc92d2db5e6 100644 (file)
@@ -6,12 +6,25 @@
 
 struct iavf_adapter;
 
-/* State of Flow Director filter */
+/* State of Flow Director filter
+ *
+ * *_REQUEST states are used to mark filter to be sent to PF driver to perform
+ * an action (either add or delete filter). *_PENDING states are an indication
+ * that request was sent to PF and the driver is waiting for response.
+ *
+ * Both DELETE and DISABLE states are being used to delete a filter in PF.
+ * The difference is that after a successful response filter in DEL_PENDING
+ * state is being deleted from VF driver as well and filter in DIS_PENDING state
+ * is being changed to INACTIVE state.
+ */
 enum iavf_fdir_fltr_state_t {
        IAVF_FDIR_FLTR_ADD_REQUEST,     /* User requests to add filter */
        IAVF_FDIR_FLTR_ADD_PENDING,     /* Filter pending add by the PF */
        IAVF_FDIR_FLTR_DEL_REQUEST,     /* User requests to delete filter */
        IAVF_FDIR_FLTR_DEL_PENDING,     /* Filter pending delete by the PF */
+       IAVF_FDIR_FLTR_DIS_REQUEST,     /* Filter scheduled to be disabled */
+       IAVF_FDIR_FLTR_DIS_PENDING,     /* Filter pending disable by the PF */
+       IAVF_FDIR_FLTR_INACTIVE,        /* Filter inactive on link down */
        IAVF_FDIR_FLTR_ACTIVE,          /* Filter is active */
 };
 
index c862ebcd2e392ef0a086c4033fadfae9fc8ceb63..e8d5b889addcb4489eb00cd077c7165618a245b7 100644 (file)
@@ -276,27 +276,6 @@ void iavf_free_virt_mem(struct iavf_hw *hw, struct iavf_virt_mem *mem)
        kfree(mem->va);
 }
 
-/**
- * iavf_lock_timeout - try to lock mutex but give up after timeout
- * @lock: mutex that should be locked
- * @msecs: timeout in msecs
- *
- * Returns 0 on success, negative on failure
- **/
-static int iavf_lock_timeout(struct mutex *lock, unsigned int msecs)
-{
-       unsigned int wait, delay = 10;
-
-       for (wait = 0; wait < msecs; wait += delay) {
-               if (mutex_trylock(lock))
-                       return 0;
-
-               msleep(delay);
-       }
-
-       return -1;
-}
-
 /**
  * iavf_schedule_reset - Set the flags and schedule a reset event
  * @adapter: board private structure
@@ -1353,18 +1332,20 @@ static void iavf_clear_cloud_filters(struct iavf_adapter *adapter)
  **/
 static void iavf_clear_fdir_filters(struct iavf_adapter *adapter)
 {
-       struct iavf_fdir_fltr *fdir, *fdirtmp;
+       struct iavf_fdir_fltr *fdir;
 
        /* remove all Flow Director filters */
        spin_lock_bh(&adapter->fdir_fltr_lock);
-       list_for_each_entry_safe(fdir, fdirtmp, &adapter->fdir_list_head,
-                                list) {
+       list_for_each_entry(fdir, &adapter->fdir_list_head, list) {
                if (fdir->state == IAVF_FDIR_FLTR_ADD_REQUEST) {
-                       list_del(&fdir->list);
-                       kfree(fdir);
-                       adapter->fdir_active_fltr--;
-               } else {
-                       fdir->state = IAVF_FDIR_FLTR_DEL_REQUEST;
+                       /* Cancel a request, keep filter as inactive */
+                       fdir->state = IAVF_FDIR_FLTR_INACTIVE;
+               } else if (fdir->state == IAVF_FDIR_FLTR_ADD_PENDING ||
+                        fdir->state == IAVF_FDIR_FLTR_ACTIVE) {
+                       /* Disable filters which are active or have a pending
+                        * request to PF to be added
+                        */
+                       fdir->state = IAVF_FDIR_FLTR_DIS_REQUEST;
                }
        }
        spin_unlock_bh(&adapter->fdir_fltr_lock);
@@ -4112,6 +4093,33 @@ static int iavf_setup_tc(struct net_device *netdev, enum tc_setup_type type,
        }
 }
 
+/**
+ * iavf_restore_fdir_filters
+ * @adapter: board private structure
+ *
+ * Restore existing FDIR filters when VF netdev comes back up.
+ **/
+static void iavf_restore_fdir_filters(struct iavf_adapter *adapter)
+{
+       struct iavf_fdir_fltr *f;
+
+       spin_lock_bh(&adapter->fdir_fltr_lock);
+       list_for_each_entry(f, &adapter->fdir_list_head, list) {
+               if (f->state == IAVF_FDIR_FLTR_DIS_REQUEST) {
+                       /* Cancel a request, keep filter as active */
+                       f->state = IAVF_FDIR_FLTR_ACTIVE;
+               } else if (f->state == IAVF_FDIR_FLTR_DIS_PENDING ||
+                          f->state == IAVF_FDIR_FLTR_INACTIVE) {
+                       /* Add filters which are inactive or have a pending
+                        * request to PF to be deleted
+                        */
+                       f->state = IAVF_FDIR_FLTR_ADD_REQUEST;
+                       adapter->aq_required |= IAVF_FLAG_AQ_ADD_FDIR_FILTER;
+               }
+       }
+       spin_unlock_bh(&adapter->fdir_fltr_lock);
+}
+
 /**
  * iavf_open - Called when a network interface is made active
  * @netdev: network interface device structure
@@ -4179,8 +4187,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 */
+       /* Restore filters that were removed with IFF_DOWN */
        iavf_restore_filters(adapter);
+       iavf_restore_fdir_filters(adapter);
 
        iavf_configure(adapter);
 
@@ -4311,6 +4320,49 @@ static int iavf_change_mtu(struct net_device *netdev, int new_mtu)
        return ret;
 }
 
+/**
+ * iavf_disable_fdir - disable Flow Director and clear existing filters
+ * @adapter: board private structure
+ **/
+static void iavf_disable_fdir(struct iavf_adapter *adapter)
+{
+       struct iavf_fdir_fltr *fdir, *fdirtmp;
+       bool del_filters = false;
+
+       adapter->flags &= ~IAVF_FLAG_FDIR_ENABLED;
+
+       /* remove all Flow Director filters */
+       spin_lock_bh(&adapter->fdir_fltr_lock);
+       list_for_each_entry_safe(fdir, fdirtmp, &adapter->fdir_list_head,
+                                list) {
+               if (fdir->state == IAVF_FDIR_FLTR_ADD_REQUEST ||
+                   fdir->state == IAVF_FDIR_FLTR_INACTIVE) {
+                       /* Delete filters not registered in PF */
+                       list_del(&fdir->list);
+                       kfree(fdir);
+                       adapter->fdir_active_fltr--;
+               } else if (fdir->state == IAVF_FDIR_FLTR_ADD_PENDING ||
+                          fdir->state == IAVF_FDIR_FLTR_DIS_REQUEST ||
+                          fdir->state == IAVF_FDIR_FLTR_ACTIVE) {
+                       /* Filters registered in PF, schedule their deletion */
+                       fdir->state = IAVF_FDIR_FLTR_DEL_REQUEST;
+                       del_filters = true;
+               } else if (fdir->state == IAVF_FDIR_FLTR_DIS_PENDING) {
+                       /* Request to delete filter already sent to PF, change
+                        * state to DEL_PENDING to delete filter after PF's
+                        * response, not set as INACTIVE
+                        */
+                       fdir->state = IAVF_FDIR_FLTR_DEL_PENDING;
+               }
+       }
+       spin_unlock_bh(&adapter->fdir_fltr_lock);
+
+       if (del_filters) {
+               adapter->aq_required |= IAVF_FLAG_AQ_DEL_FDIR_FILTER;
+               mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0);
+       }
+}
+
 #define NETIF_VLAN_OFFLOAD_FEATURES    (NETIF_F_HW_VLAN_CTAG_RX | \
                                         NETIF_F_HW_VLAN_CTAG_TX | \
                                         NETIF_F_HW_VLAN_STAG_RX | \
@@ -4336,6 +4388,13 @@ static int iavf_set_features(struct net_device *netdev,
            ((netdev->features & NETIF_F_RXFCS) ^ (features & NETIF_F_RXFCS)))
                iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
 
+       if ((netdev->features & NETIF_F_NTUPLE) ^ (features & NETIF_F_NTUPLE)) {
+               if (features & NETIF_F_NTUPLE)
+                       adapter->flags |= IAVF_FLAG_FDIR_ENABLED;
+               else
+                       iavf_disable_fdir(adapter);
+       }
+
        return 0;
 }
 
@@ -4685,6 +4744,9 @@ static netdev_features_t iavf_fix_features(struct net_device *netdev,
 
        features = iavf_fix_netdev_vlan_features(adapter, features);
 
+       if (!FDIR_FLTR_SUPPORT(adapter))
+               features &= ~NETIF_F_NTUPLE;
+
        return iavf_fix_strip_features(adapter, features);
 }
 
@@ -4802,6 +4864,12 @@ int iavf_process_config(struct iavf_adapter *adapter)
        if (vfres->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN)
                netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
 
+       if (FDIR_FLTR_SUPPORT(adapter)) {
+               netdev->hw_features |= NETIF_F_NTUPLE;
+               netdev->features |= NETIF_F_NTUPLE;
+               adapter->flags |= IAVF_FLAG_FDIR_ENABLED;
+       }
+
        netdev->priv_flags |= IFF_UNICAST_FLT;
 
        /* Do not turn on offloads when they are requested to be turned off.
@@ -4825,34 +4893,6 @@ int iavf_process_config(struct iavf_adapter *adapter)
        return 0;
 }
 
-/**
- * iavf_shutdown - Shutdown the device in preparation for a reboot
- * @pdev: pci device structure
- **/
-static void iavf_shutdown(struct pci_dev *pdev)
-{
-       struct iavf_adapter *adapter = iavf_pdev_to_adapter(pdev);
-       struct net_device *netdev = adapter->netdev;
-
-       netif_device_detach(netdev);
-
-       if (netif_running(netdev))
-               iavf_close(netdev);
-
-       if (iavf_lock_timeout(&adapter->crit_lock, 5000))
-               dev_warn(&adapter->pdev->dev, "%s: failed to acquire crit_lock\n", __func__);
-       /* Prevent the watchdog from running. */
-       iavf_change_state(adapter, __IAVF_REMOVE);
-       adapter->aq_required = 0;
-       mutex_unlock(&adapter->crit_lock);
-
-#ifdef CONFIG_PM
-       pci_save_state(pdev);
-
-#endif
-       pci_disable_device(pdev);
-}
-
 /**
  * iavf_probe - Device Initialization Routine
  * @pdev: PCI device information struct
@@ -5063,16 +5103,21 @@ static int __maybe_unused iavf_resume(struct device *dev_d)
  **/
 static void iavf_remove(struct pci_dev *pdev)
 {
-       struct iavf_adapter *adapter = iavf_pdev_to_adapter(pdev);
        struct iavf_fdir_fltr *fdir, *fdirtmp;
        struct iavf_vlan_filter *vlf, *vlftmp;
        struct iavf_cloud_filter *cf, *cftmp;
        struct iavf_adv_rss *rss, *rsstmp;
        struct iavf_mac_filter *f, *ftmp;
+       struct iavf_adapter *adapter;
        struct net_device *netdev;
        struct iavf_hw *hw;
 
-       netdev = adapter->netdev;
+       /* Don't proceed with remove if netdev is already freed */
+       netdev = pci_get_drvdata(pdev);
+       if (!netdev)
+               return;
+
+       adapter = iavf_pdev_to_adapter(pdev);
        hw = &adapter->hw;
 
        if (test_and_set_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section))
@@ -5184,11 +5229,25 @@ static void iavf_remove(struct pci_dev *pdev)
 
        destroy_workqueue(adapter->wq);
 
+       pci_set_drvdata(pdev, NULL);
+
        free_netdev(netdev);
 
        pci_disable_device(pdev);
 }
 
+/**
+ * iavf_shutdown - Shutdown the device in preparation for a reboot
+ * @pdev: pci device structure
+ **/
+static void iavf_shutdown(struct pci_dev *pdev)
+{
+       iavf_remove(pdev);
+
+       if (system_state == SYSTEM_POWER_OFF)
+               pci_set_power_state(pdev, PCI_D3hot);
+}
+
 static SIMPLE_DEV_PM_OPS(iavf_pm_ops, iavf_suspend, iavf_resume);
 
 static struct pci_driver iavf_driver = {
index 64c4443dbef9caca468d919c4cf5b1a4c6dfa7ca..2d9366be0ec506c9b69c3b25d69044a4e47ab03b 100644 (file)
@@ -1735,8 +1735,8 @@ void iavf_add_fdir_filter(struct iavf_adapter *adapter)
  **/
 void iavf_del_fdir_filter(struct iavf_adapter *adapter)
 {
+       struct virtchnl_fdir_del f = {};
        struct iavf_fdir_fltr *fdir;
-       struct virtchnl_fdir_del f;
        bool process_fltr = false;
        int len;
 
@@ -1753,11 +1753,16 @@ void iavf_del_fdir_filter(struct iavf_adapter *adapter)
        list_for_each_entry(fdir, &adapter->fdir_list_head, list) {
                if (fdir->state == IAVF_FDIR_FLTR_DEL_REQUEST) {
                        process_fltr = true;
-                       memset(&f, 0, len);
                        f.vsi_id = fdir->vc_add_msg.vsi_id;
                        f.flow_id = fdir->flow_id;
                        fdir->state = IAVF_FDIR_FLTR_DEL_PENDING;
                        break;
+               } else if (fdir->state == IAVF_FDIR_FLTR_DIS_REQUEST) {
+                       process_fltr = true;
+                       f.vsi_id = fdir->vc_add_msg.vsi_id;
+                       f.flow_id = fdir->flow_id;
+                       fdir->state = IAVF_FDIR_FLTR_DIS_PENDING;
+                       break;
                }
        }
        spin_unlock_bh(&adapter->fdir_fltr_lock);
@@ -1901,6 +1906,48 @@ static void iavf_netdev_features_vlan_strip_set(struct net_device *netdev,
                netdev->features &= ~NETIF_F_HW_VLAN_CTAG_RX;
 }
 
+/**
+ * iavf_activate_fdir_filters - Reactivate all FDIR filters after a reset
+ * @adapter: private adapter structure
+ *
+ * Called after a reset to re-add all FDIR filters and delete some of them
+ * if they were pending to be deleted.
+ */
+static void iavf_activate_fdir_filters(struct iavf_adapter *adapter)
+{
+       struct iavf_fdir_fltr *f, *ftmp;
+       bool add_filters = false;
+
+       spin_lock_bh(&adapter->fdir_fltr_lock);
+       list_for_each_entry_safe(f, ftmp, &adapter->fdir_list_head, list) {
+               if (f->state == IAVF_FDIR_FLTR_ADD_REQUEST ||
+                   f->state == IAVF_FDIR_FLTR_ADD_PENDING ||
+                   f->state == IAVF_FDIR_FLTR_ACTIVE) {
+                       /* All filters and requests have been removed in PF,
+                        * restore them
+                        */
+                       f->state = IAVF_FDIR_FLTR_ADD_REQUEST;
+                       add_filters = true;
+               } else if (f->state == IAVF_FDIR_FLTR_DIS_REQUEST ||
+                          f->state == IAVF_FDIR_FLTR_DIS_PENDING) {
+                       /* Link down state, leave filters as inactive */
+                       f->state = IAVF_FDIR_FLTR_INACTIVE;
+               } else if (f->state == IAVF_FDIR_FLTR_DEL_REQUEST ||
+                          f->state == IAVF_FDIR_FLTR_DEL_PENDING) {
+                       /* Delete filters that were pending to be deleted, the
+                        * list on PF is already cleared after a reset
+                        */
+                       list_del(&f->list);
+                       kfree(f);
+                       adapter->fdir_active_fltr--;
+               }
+       }
+       spin_unlock_bh(&adapter->fdir_fltr_lock);
+
+       if (add_filters)
+               adapter->aq_required |= IAVF_FLAG_AQ_ADD_FDIR_FILTER;
+}
+
 /**
  * iavf_virtchnl_completion
  * @adapter: adapter structure
@@ -2078,7 +2125,8 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
                        spin_lock_bh(&adapter->fdir_fltr_lock);
                        list_for_each_entry(fdir, &adapter->fdir_list_head,
                                            list) {
-                               if (fdir->state == IAVF_FDIR_FLTR_DEL_PENDING) {
+                               if (fdir->state == IAVF_FDIR_FLTR_DEL_PENDING ||
+                                   fdir->state == IAVF_FDIR_FLTR_DIS_PENDING) {
                                        fdir->state = IAVF_FDIR_FLTR_ACTIVE;
                                        dev_info(&adapter->pdev->dev, "Failed to del Flow Director filter, error %s\n",
                                                 iavf_stat_str(&adapter->hw,
@@ -2214,6 +2262,8 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
 
                spin_unlock_bh(&adapter->mac_vlan_list_lock);
 
+               iavf_activate_fdir_filters(adapter);
+
                iavf_parse_vf_resource_msg(adapter);
 
                /* negotiated VIRTCHNL_VF_OFFLOAD_VLAN_V2, so wait for the
@@ -2390,7 +2440,9 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
                list_for_each_entry_safe(fdir, fdir_tmp, &adapter->fdir_list_head,
                                         list) {
                        if (fdir->state == IAVF_FDIR_FLTR_DEL_PENDING) {
-                               if (del_fltr->status == VIRTCHNL_FDIR_SUCCESS) {
+                               if (del_fltr->status == VIRTCHNL_FDIR_SUCCESS ||
+                                   del_fltr->status ==
+                                   VIRTCHNL_FDIR_FAILURE_RULE_NONEXIST) {
                                        dev_info(&adapter->pdev->dev, "Flow Director filter with location %u is deleted\n",
                                                 fdir->loc);
                                        list_del(&fdir->list);
@@ -2402,6 +2454,17 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
                                                 del_fltr->status);
                                        iavf_print_fdir_fltr(adapter, fdir);
                                }
+                       } else if (fdir->state == IAVF_FDIR_FLTR_DIS_PENDING) {
+                               if (del_fltr->status == VIRTCHNL_FDIR_SUCCESS ||
+                                   del_fltr->status ==
+                                   VIRTCHNL_FDIR_FAILURE_RULE_NONEXIST) {
+                                       fdir->state = IAVF_FDIR_FLTR_INACTIVE;
+                               } else {
+                                       fdir->state = IAVF_FDIR_FLTR_ACTIVE;
+                                       dev_info(&adapter->pdev->dev, "Failed to disable Flow Director filter with status: %d\n",
+                                                del_fltr->status);
+                                       iavf_print_fdir_fltr(adapter, fdir);
+                               }
                        }
                }
                spin_unlock_bh(&adapter->fdir_fltr_lock);
index 552970c7dec09715ece049a737ee32e2712e6b41..a9bdf3283a852f638d72396c8bf84dc5fe76f0b1 100644 (file)
@@ -1193,6 +1193,13 @@ int octep_device_setup(struct octep_device *oct)
        if (ret)
                return ret;
 
+       INIT_WORK(&oct->tx_timeout_task, octep_tx_timeout_task);
+       INIT_WORK(&oct->ctrl_mbox_task, octep_ctrl_mbox_task);
+       INIT_DELAYED_WORK(&oct->intr_poll_task, octep_intr_poll_task);
+       oct->poll_non_ioq_intr = true;
+       queue_delayed_work(octep_wq, &oct->intr_poll_task,
+                          msecs_to_jiffies(OCTEP_INTR_POLL_TIME_MSECS));
+
        atomic_set(&oct->hb_miss_cnt, 0);
        INIT_DELAYED_WORK(&oct->hb_task, octep_hb_timeout_task);
 
@@ -1258,7 +1265,8 @@ static bool get_fw_ready_status(struct pci_dev *pdev)
 
                pci_read_config_byte(pdev, (pos + 8), &status);
                dev_info(&pdev->dev, "Firmware ready status = %u\n", status);
-               return status;
+#define FW_STATUS_READY 1ULL
+               return status == FW_STATUS_READY;
        }
        return false;
 }
@@ -1325,21 +1333,18 @@ static int octep_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto err_octep_config;
        }
 
-       octep_ctrl_net_get_info(octep_dev, OCTEP_CTRL_NET_INVALID_VFID,
-                               &octep_dev->conf->fw_info);
+       err = octep_ctrl_net_get_info(octep_dev, OCTEP_CTRL_NET_INVALID_VFID,
+                                     &octep_dev->conf->fw_info);
+       if (err) {
+               dev_err(&pdev->dev, "Failed to get firmware info\n");
+               goto register_dev_err;
+       }
        dev_info(&octep_dev->pdev->dev, "Heartbeat interval %u msecs Heartbeat miss count %u\n",
                 octep_dev->conf->fw_info.hb_interval,
                 octep_dev->conf->fw_info.hb_miss_count);
        queue_delayed_work(octep_wq, &octep_dev->hb_task,
                           msecs_to_jiffies(octep_dev->conf->fw_info.hb_interval));
 
-       INIT_WORK(&octep_dev->tx_timeout_task, octep_tx_timeout_task);
-       INIT_WORK(&octep_dev->ctrl_mbox_task, octep_ctrl_mbox_task);
-       INIT_DELAYED_WORK(&octep_dev->intr_poll_task, octep_intr_poll_task);
-       octep_dev->poll_non_ioq_intr = true;
-       queue_delayed_work(octep_wq, &octep_dev->intr_poll_task,
-                          msecs_to_jiffies(OCTEP_INTR_POLL_TIME_MSECS));
-
        netdev->netdev_ops = &octep_netdev_ops;
        octep_set_ethtool_ops(netdev);
        netif_carrier_off(netdev);
index af21e2030cff28f258b45a9d88701ef0f5f6b1dd..4728ba34b0e34cc3f5741bfc62b2ba49e00c2b8f 100644 (file)
@@ -373,6 +373,11 @@ void rpm_lmac_pause_frm_config(void *rpmd, int lmac_id, bool enable)
        cfg |= RPMX_MTI_MAC100X_COMMAND_CONFIG_TX_P_DISABLE;
        rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg);
 
+       /* Disable forward pause to driver */
+       cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG);
+       cfg &= ~RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_FWD;
+       rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg);
+
        /* Enable channel mask for all LMACS */
        if (is_dev_rpm2(rpm))
                rpm_write(rpm, lmac_id, RPM2_CMR_CHAN_MSK_OR, 0xffff);
@@ -616,12 +621,10 @@ int rpm_lmac_pfc_config(void *rpmd, int lmac_id, u8 tx_pause, u8 rx_pause, u16 p
 
        if (rx_pause) {
                cfg &= ~(RPMX_MTI_MAC100X_COMMAND_CONFIG_RX_P_DISABLE |
-                               RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_IGNORE |
-                               RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_FWD);
+                        RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_IGNORE);
        } else {
                cfg |= (RPMX_MTI_MAC100X_COMMAND_CONFIG_RX_P_DISABLE |
-                               RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_IGNORE |
-                               RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_FWD);
+                       RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_IGNORE);
        }
 
        if (tx_pause) {
index 62780d8b4f9ac84758f3dc921d552217280d9469..21b5d71c1e37582fac1569fc6f79693f8f2ff0d2 100644 (file)
@@ -538,7 +538,7 @@ static int rvu_nix_register_reporters(struct rvu_devlink *rvu_dl)
 
        rvu_dl->devlink_wq = create_workqueue("rvu_devlink_wq");
        if (!rvu_dl->devlink_wq)
-               goto err;
+               return -ENOMEM;
 
        INIT_WORK(&rvu_reporters->intr_work, rvu_nix_intr_work);
        INIT_WORK(&rvu_reporters->gen_work, rvu_nix_gen_work);
@@ -546,9 +546,6 @@ static int rvu_nix_register_reporters(struct rvu_devlink *rvu_dl)
        INIT_WORK(&rvu_reporters->ras_work, rvu_nix_ras_work);
 
        return 0;
-err:
-       rvu_nix_health_reporters_destroy(rvu_dl);
-       return -ENOMEM;
 }
 
 static int rvu_nix_health_reporters_create(struct rvu_devlink *rvu_dl)
index f65805860c8d4ee486734a7be5be774e5ed9712c..0bcf3e559280650110d46d86be7f092e52ed2ba5 100644 (file)
@@ -671,6 +671,7 @@ void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
        int blkaddr, ucast_idx, index;
        struct nix_rx_action action = { 0 };
        u64 relaxed_mask;
+       u8 flow_key_alg;
 
        if (!hw->cap.nix_rx_multicast && is_cgx_vf(rvu, pcifunc))
                return;
@@ -701,6 +702,8 @@ void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
                action.op = NIX_RX_ACTIONOP_UCAST;
        }
 
+       flow_key_alg = action.flow_key_alg;
+
        /* RX_ACTION set to MCAST for CGX PF's */
        if (hw->cap.nix_rx_multicast && pfvf->use_mce_list &&
            is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc))) {
@@ -740,7 +743,7 @@ void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
        req.vf = pcifunc;
        req.index = action.index;
        req.match_id = action.match_id;
-       req.flow_key_alg = action.flow_key_alg;
+       req.flow_key_alg = flow_key_alg;
 
        rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp);
 }
@@ -854,6 +857,7 @@ void rvu_npc_install_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
        u8 mac_addr[ETH_ALEN] = { 0 };
        struct nix_rx_action action = { 0 };
        struct rvu_pfvf *pfvf;
+       u8 flow_key_alg;
        u16 vf_func;
 
        /* Only CGX PF/VF can add allmulticast entry */
@@ -888,6 +892,7 @@ void rvu_npc_install_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
                *(u64 *)&action = npc_get_mcam_action(rvu, mcam,
                                                        blkaddr, ucast_idx);
 
+       flow_key_alg = action.flow_key_alg;
        if (action.op != NIX_RX_ACTIONOP_RSS) {
                *(u64 *)&action = 0;
                action.op = NIX_RX_ACTIONOP_UCAST;
@@ -924,7 +929,7 @@ void rvu_npc_install_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
        req.vf = pcifunc | vf_func;
        req.index = action.index;
        req.match_id = action.match_id;
-       req.flow_key_alg = action.flow_key_alg;
+       req.flow_key_alg = flow_key_alg;
 
        rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp);
 }
@@ -990,11 +995,38 @@ static void npc_update_vf_flow_entry(struct rvu *rvu, struct npc_mcam *mcam,
        mutex_unlock(&mcam->lock);
 }
 
+static void npc_update_rx_action_with_alg_idx(struct rvu *rvu, struct nix_rx_action action,
+                                             struct rvu_pfvf *pfvf, int mcam_index, int blkaddr,
+                                             int alg_idx)
+
+{
+       struct npc_mcam *mcam = &rvu->hw->mcam;
+       struct rvu_hwinfo *hw = rvu->hw;
+       int bank, op_rss;
+
+       if (!is_mcam_entry_enabled(rvu, mcam, blkaddr, mcam_index))
+               return;
+
+       op_rss = (!hw->cap.nix_rx_multicast || !pfvf->use_mce_list);
+
+       bank = npc_get_bank(mcam, mcam_index);
+       mcam_index &= (mcam->banksize - 1);
+
+       /* If Rx action is MCAST update only RSS algorithm index */
+       if (!op_rss) {
+               *(u64 *)&action = rvu_read64(rvu, blkaddr,
+                               NPC_AF_MCAMEX_BANKX_ACTION(mcam_index, bank));
+
+               action.flow_key_alg = alg_idx;
+       }
+       rvu_write64(rvu, blkaddr,
+                   NPC_AF_MCAMEX_BANKX_ACTION(mcam_index, bank), *(u64 *)&action);
+}
+
 void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, u16 pcifunc, int nixlf,
                                    int group, int alg_idx, int mcam_index)
 {
        struct npc_mcam *mcam = &rvu->hw->mcam;
-       struct rvu_hwinfo *hw = rvu->hw;
        struct nix_rx_action action;
        int blkaddr, index, bank;
        struct rvu_pfvf *pfvf;
@@ -1050,15 +1082,16 @@ void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, u16 pcifunc, int nixlf,
        /* If PF's promiscuous entry is enabled,
         * Set RSS action for that entry as well
         */
-       if ((!hw->cap.nix_rx_multicast || !pfvf->use_mce_list) &&
-           is_mcam_entry_enabled(rvu, mcam, blkaddr, index)) {
-               bank = npc_get_bank(mcam, index);
-               index &= (mcam->banksize - 1);
+       npc_update_rx_action_with_alg_idx(rvu, action, pfvf, index, blkaddr,
+                                         alg_idx);
 
-               rvu_write64(rvu, blkaddr,
-                           NPC_AF_MCAMEX_BANKX_ACTION(index, bank),
-                           *(u64 *)&action);
-       }
+       index = npc_get_nixlf_mcam_index(mcam, pcifunc,
+                                        nixlf, NIXLF_ALLMULTI_ENTRY);
+       /* If PF's allmulti  entry is enabled,
+        * Set RSS action for that entry as well
+        */
+       npc_update_rx_action_with_alg_idx(rvu, action, pfvf, index, blkaddr,
+                                         alg_idx);
 }
 
 void npc_enadis_default_mce_entry(struct rvu *rvu, u16 pcifunc,
index 0c17ebdda148735b0e2954778ca8cb777696cc97..a57455aebff6fc58e24c4a4da2d60d78e59f439f 100644 (file)
@@ -1650,6 +1650,21 @@ static void otx2_free_hw_resources(struct otx2_nic *pf)
        mutex_unlock(&mbox->lock);
 }
 
+static bool otx2_promisc_use_mce_list(struct otx2_nic *pfvf)
+{
+       int vf;
+
+       /* The AF driver will determine whether to allow the VF netdev or not */
+       if (is_otx2_vf(pfvf->pcifunc))
+               return true;
+
+       /* check if there are any trusted VFs associated with the PF netdev */
+       for (vf = 0; vf < pci_num_vf(pfvf->pdev); vf++)
+               if (pfvf->vf_configs[vf].trusted)
+                       return true;
+       return false;
+}
+
 static void otx2_do_set_rx_mode(struct otx2_nic *pf)
 {
        struct net_device *netdev = pf->netdev;
@@ -1682,7 +1697,8 @@ static void otx2_do_set_rx_mode(struct otx2_nic *pf)
        if (netdev->flags & (IFF_ALLMULTI | IFF_MULTICAST))
                req->mode |= NIX_RX_MODE_ALLMULTI;
 
-       req->mode |= NIX_RX_MODE_USE_MCE;
+       if (otx2_promisc_use_mce_list(pf))
+               req->mode |= NIX_RX_MODE_USE_MCE;
 
        otx2_sync_mbox_msg(&pf->mbox);
        mutex_unlock(&pf->mbox.lock);
@@ -2691,11 +2707,14 @@ static int otx2_ndo_set_vf_trust(struct net_device *netdev, int vf,
        pf->vf_configs[vf].trusted = enable;
        rc = otx2_set_vf_permissions(pf, vf, OTX2_TRUSTED_VF);
 
-       if (rc)
+       if (rc) {
                pf->vf_configs[vf].trusted = !enable;
-       else
+       } else {
                netdev_info(pf->netdev, "VF %d is %strusted\n",
                            vf, enable ? "" : "not ");
+               otx2_set_rx_mode(netdev);
+       }
+
        return rc;
 }
 
index b2a5da9739d2b463e9565ffe943cb7ec1916b70a..729a11b5fb2524e23e91e599a9b9c74729d9da11 100644 (file)
@@ -826,6 +826,7 @@ enum {
        MLX5E_STATE_DESTROYING,
        MLX5E_STATE_XDP_TX_ENABLED,
        MLX5E_STATE_XDP_ACTIVE,
+       MLX5E_STATE_CHANNELS_ACTIVE,
 };
 
 struct mlx5e_modify_sq_param {
index 4e923a2874aefe089faa454dc4c8f04e4e776b3f..86bf007fd05b7327a79918b5de9beea9353b70e1 100644 (file)
@@ -83,6 +83,9 @@ mlx5e_tc_post_act_offload(struct mlx5e_post_act *post_act,
        struct mlx5_flow_spec *spec;
        int err;
 
+       if (IS_ERR(post_act))
+               return PTR_ERR(post_act);
+
        spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
        if (!spec)
                return -ENOMEM;
@@ -111,6 +114,9 @@ mlx5e_tc_post_act_add(struct mlx5e_post_act *post_act, struct mlx5_flow_attr *po
        struct mlx5e_post_act_handle *handle;
        int err;
 
+       if (IS_ERR(post_act))
+               return ERR_CAST(post_act);
+
        handle = kzalloc(sizeof(*handle), GFP_KERNEL);
        if (!handle)
                return ERR_PTR(-ENOMEM);
index 655496598c688496bb30e14c0a0d6e52e2d93040..161c5190c236a0d8d048bd6a253a36cdeb12b9bc 100644 (file)
@@ -121,7 +121,14 @@ static bool mlx5e_ipsec_update_esn_state(struct mlx5e_ipsec_sa_entry *sa_entry)
        if (x->xso.type == XFRM_DEV_OFFLOAD_CRYPTO)
                esn_msb = xfrm_replay_seqhi(x, htonl(seq_bottom));
 
-       sa_entry->esn_state.esn = esn;
+       if (sa_entry->esn_state.esn_msb)
+               sa_entry->esn_state.esn = esn;
+       else
+               /* According to RFC4303, section "3.3.3. Sequence Number Generation",
+                * the first packet sent using a given SA will contain a sequence
+                * number of 1.
+                */
+               sa_entry->esn_state.esn = max_t(u32, esn, 1);
        sa_entry->esn_state.esn_msb = esn_msb;
 
        if (unlikely(overlap && seq_bottom < MLX5E_IPSEC_ESN_SCOPE_MID)) {
@@ -335,6 +342,27 @@ void mlx5e_ipsec_build_accel_xfrm_attrs(struct mlx5e_ipsec_sa_entry *sa_entry,
                attrs->replay_esn.esn = sa_entry->esn_state.esn;
                attrs->replay_esn.esn_msb = sa_entry->esn_state.esn_msb;
                attrs->replay_esn.overlap = sa_entry->esn_state.overlap;
+               switch (x->replay_esn->replay_window) {
+               case 32:
+                       attrs->replay_esn.replay_window =
+                               MLX5_IPSEC_ASO_REPLAY_WIN_32BIT;
+                       break;
+               case 64:
+                       attrs->replay_esn.replay_window =
+                               MLX5_IPSEC_ASO_REPLAY_WIN_64BIT;
+                       break;
+               case 128:
+                       attrs->replay_esn.replay_window =
+                               MLX5_IPSEC_ASO_REPLAY_WIN_128BIT;
+                       break;
+               case 256:
+                       attrs->replay_esn.replay_window =
+                               MLX5_IPSEC_ASO_REPLAY_WIN_256BIT;
+                       break;
+               default:
+                       WARN_ON(true);
+                       return;
+               }
        }
 
        attrs->dir = x->xso.dir;
@@ -907,9 +935,11 @@ void mlx5e_ipsec_cleanup(struct mlx5e_priv *priv)
                return;
 
        mlx5e_accel_ipsec_fs_cleanup(ipsec);
-       if (mlx5_ipsec_device_caps(priv->mdev) & MLX5_IPSEC_CAP_TUNNEL)
+       if (ipsec->netevent_nb.notifier_call) {
                unregister_netevent_notifier(&ipsec->netevent_nb);
-       if (mlx5_ipsec_device_caps(priv->mdev) & MLX5_IPSEC_CAP_PACKET_OFFLOAD)
+               ipsec->netevent_nb.notifier_call = NULL;
+       }
+       if (ipsec->aso)
                mlx5e_ipsec_aso_cleanup(ipsec);
        destroy_workqueue(ipsec->wq);
        kfree(ipsec);
@@ -1018,6 +1048,12 @@ static int mlx5e_xfrm_validate_policy(struct mlx5_core_dev *mdev,
                }
        }
 
+       if (x->xdo.type == XFRM_DEV_OFFLOAD_PACKET &&
+           !(mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_PACKET_OFFLOAD)) {
+               NL_SET_ERR_MSG_MOD(extack, "Packet offload is not supported");
+               return -EINVAL;
+       }
+
        return 0;
 }
 
@@ -1113,14 +1149,6 @@ static const struct xfrmdev_ops mlx5e_ipsec_xfrmdev_ops = {
        .xdo_dev_state_free     = mlx5e_xfrm_free_state,
        .xdo_dev_offload_ok     = mlx5e_ipsec_offload_ok,
        .xdo_dev_state_advance_esn = mlx5e_xfrm_advance_esn_state,
-};
-
-static const struct xfrmdev_ops mlx5e_ipsec_packet_xfrmdev_ops = {
-       .xdo_dev_state_add      = mlx5e_xfrm_add_state,
-       .xdo_dev_state_delete   = mlx5e_xfrm_del_state,
-       .xdo_dev_state_free     = mlx5e_xfrm_free_state,
-       .xdo_dev_offload_ok     = mlx5e_ipsec_offload_ok,
-       .xdo_dev_state_advance_esn = mlx5e_xfrm_advance_esn_state,
 
        .xdo_dev_state_update_curlft = mlx5e_xfrm_update_curlft,
        .xdo_dev_policy_add = mlx5e_xfrm_add_policy,
@@ -1138,11 +1166,7 @@ void mlx5e_ipsec_build_netdev(struct mlx5e_priv *priv)
 
        mlx5_core_info(mdev, "mlx5e: IPSec ESP acceleration enabled\n");
 
-       if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_PACKET_OFFLOAD)
-               netdev->xfrmdev_ops = &mlx5e_ipsec_packet_xfrmdev_ops;
-       else
-               netdev->xfrmdev_ops = &mlx5e_ipsec_xfrmdev_ops;
-
+       netdev->xfrmdev_ops = &mlx5e_ipsec_xfrmdev_ops;
        netdev->features |= NETIF_F_HW_ESP;
        netdev->hw_enc_features |= NETIF_F_HW_ESP;
 
index 8f4a37bceaf455c7bea24f4a21349b543e33818c..adaea3493193ef05dcf148dfda376b520acc94b7 100644 (file)
@@ -189,11 +189,19 @@ struct mlx5e_ipsec_ft {
        u32 refcnt;
 };
 
+struct mlx5e_ipsec_drop {
+       struct mlx5_flow_handle *rule;
+       struct mlx5_fc *fc;
+};
+
 struct mlx5e_ipsec_rule {
        struct mlx5_flow_handle *rule;
        struct mlx5_modify_hdr *modify_hdr;
        struct mlx5_pkt_reformat *pkt_reformat;
        struct mlx5_fc *fc;
+       struct mlx5e_ipsec_drop replay;
+       struct mlx5e_ipsec_drop auth;
+       struct mlx5e_ipsec_drop trailer;
 };
 
 struct mlx5e_ipsec_miss {
@@ -201,19 +209,6 @@ struct mlx5e_ipsec_miss {
        struct mlx5_flow_handle *rule;
 };
 
-struct mlx5e_ipsec_rx {
-       struct mlx5e_ipsec_ft ft;
-       struct mlx5e_ipsec_miss pol;
-       struct mlx5e_ipsec_miss sa;
-       struct mlx5e_ipsec_rule status;
-       struct mlx5e_ipsec_miss status_drop;
-       struct mlx5_fc *status_drop_cnt;
-       struct mlx5e_ipsec_fc *fc;
-       struct mlx5_fs_chains *chains;
-       u8 allow_tunnel_mode : 1;
-       struct xarray ipsec_obj_id_map;
-};
-
 struct mlx5e_ipsec_tx_create_attr {
        int prio;
        int pol_level;
@@ -248,6 +243,7 @@ struct mlx5e_ipsec {
        struct mlx5_ipsec_fs *roce;
        u8 is_uplink_rep: 1;
        struct mlx5e_ipsec_mpv_work mpv_work;
+       struct xarray ipsec_obj_id_map;
 };
 
 struct mlx5e_ipsec_esn_state {
index f41c976dc33f931eb3ac19431684fbd206a9e413..c1e89dc77db965e24f54e85d431e8e3e6b7cc183 100644 (file)
@@ -32,6 +32,22 @@ struct mlx5e_ipsec_tx {
        u8 allow_tunnel_mode : 1;
 };
 
+struct mlx5e_ipsec_status_checks {
+       struct mlx5_flow_group *drop_all_group;
+       struct mlx5e_ipsec_drop all;
+};
+
+struct mlx5e_ipsec_rx {
+       struct mlx5e_ipsec_ft ft;
+       struct mlx5e_ipsec_miss pol;
+       struct mlx5e_ipsec_miss sa;
+       struct mlx5e_ipsec_rule status;
+       struct mlx5e_ipsec_status_checks status_drops;
+       struct mlx5e_ipsec_fc *fc;
+       struct mlx5_fs_chains *chains;
+       u8 allow_tunnel_mode : 1;
+};
+
 /* IPsec RX flow steering */
 static enum mlx5_traffic_types family2tt(u32 family)
 {
@@ -128,14 +144,37 @@ static struct mlx5_flow_table *ipsec_ft_create(struct mlx5_flow_namespace *ns,
        return mlx5_create_auto_grouped_flow_table(ns, &ft_attr);
 }
 
-static int ipsec_status_rule(struct mlx5_core_dev *mdev,
-                            struct mlx5e_ipsec_rx *rx,
-                            struct mlx5_flow_destination *dest)
+static void ipsec_rx_status_drop_destroy(struct mlx5e_ipsec *ipsec,
+                                        struct mlx5e_ipsec_rx *rx)
+{
+       mlx5_del_flow_rules(rx->status_drops.all.rule);
+       mlx5_fc_destroy(ipsec->mdev, rx->status_drops.all.fc);
+       mlx5_destroy_flow_group(rx->status_drops.drop_all_group);
+}
+
+static void ipsec_rx_status_pass_destroy(struct mlx5e_ipsec *ipsec,
+                                        struct mlx5e_ipsec_rx *rx)
 {
-       u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {};
+       mlx5_del_flow_rules(rx->status.rule);
+
+       if (rx != ipsec->rx_esw)
+               return;
+
+#ifdef CONFIG_MLX5_ESWITCH
+       mlx5_chains_put_table(esw_chains(ipsec->mdev->priv.eswitch), 0, 1, 0);
+#endif
+}
+
+static int rx_add_rule_drop_auth_trailer(struct mlx5e_ipsec_sa_entry *sa_entry,
+                                        struct mlx5e_ipsec_rx *rx)
+{
+       struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
+       struct mlx5_flow_table *ft = rx->ft.status;
+       struct mlx5_core_dev *mdev = ipsec->mdev;
+       struct mlx5_flow_destination dest = {};
        struct mlx5_flow_act flow_act = {};
-       struct mlx5_modify_hdr *modify_hdr;
-       struct mlx5_flow_handle *fte;
+       struct mlx5_flow_handle *rule;
+       struct mlx5_fc *flow_counter;
        struct mlx5_flow_spec *spec;
        int err;
 
@@ -143,48 +182,273 @@ static int ipsec_status_rule(struct mlx5_core_dev *mdev,
        if (!spec)
                return -ENOMEM;
 
-       /* Action to copy 7 bit ipsec_syndrome to regB[24:30] */
-       MLX5_SET(copy_action_in, action, action_type, MLX5_ACTION_TYPE_COPY);
-       MLX5_SET(copy_action_in, action, src_field, MLX5_ACTION_IN_FIELD_IPSEC_SYNDROME);
-       MLX5_SET(copy_action_in, action, src_offset, 0);
-       MLX5_SET(copy_action_in, action, length, 7);
-       MLX5_SET(copy_action_in, action, dst_field, MLX5_ACTION_IN_FIELD_METADATA_REG_B);
-       MLX5_SET(copy_action_in, action, dst_offset, 24);
+       flow_counter = mlx5_fc_create(mdev, true);
+       if (IS_ERR(flow_counter)) {
+               err = PTR_ERR(flow_counter);
+               mlx5_core_err(mdev,
+                             "Failed to add ipsec rx status drop rule counter, err=%d\n", err);
+               goto err_cnt;
+       }
+       sa_entry->ipsec_rule.auth.fc = flow_counter;
 
-       modify_hdr = mlx5_modify_header_alloc(mdev, MLX5_FLOW_NAMESPACE_KERNEL,
-                                             1, action);
+       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT;
+       flow_act.flags = FLOW_ACT_NO_APPEND;
+       dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
+       dest.counter_id = mlx5_fc_id(flow_counter);
+       if (rx == ipsec->rx_esw)
+               spec->flow_context.flow_source = MLX5_FLOW_CONTEXT_FLOW_SOURCE_UPLINK;
 
-       if (IS_ERR(modify_hdr)) {
-               err = PTR_ERR(modify_hdr);
+       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.ipsec_syndrome);
+       MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.ipsec_syndrome, 1);
+       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_2);
+       MLX5_SET(fte_match_param, spec->match_value,
+                misc_parameters_2.metadata_reg_c_2,
+                sa_entry->ipsec_obj_id | BIT(31));
+       spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
+       rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
+       if (IS_ERR(rule)) {
+               err = PTR_ERR(rule);
                mlx5_core_err(mdev,
-                             "fail to alloc ipsec copy modify_header_id err=%d\n", err);
-               goto out_spec;
+                             "Failed to add ipsec rx status drop rule, err=%d\n", err);
+               goto err_rule;
        }
+       sa_entry->ipsec_rule.auth.rule = rule;
 
-       /* create fte */
-       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_MOD_HDR |
-                         MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
+       flow_counter = mlx5_fc_create(mdev, true);
+       if (IS_ERR(flow_counter)) {
+               err = PTR_ERR(flow_counter);
+               mlx5_core_err(mdev,
+                             "Failed to add ipsec rx status drop rule counter, err=%d\n", err);
+               goto err_cnt_2;
+       }
+       sa_entry->ipsec_rule.trailer.fc = flow_counter;
+
+       dest.counter_id = mlx5_fc_id(flow_counter);
+       MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.ipsec_syndrome, 2);
+       rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
+       if (IS_ERR(rule)) {
+               err = PTR_ERR(rule);
+               mlx5_core_err(mdev,
+                             "Failed to add ipsec rx status drop rule, err=%d\n", err);
+               goto err_rule_2;
+       }
+       sa_entry->ipsec_rule.trailer.rule = rule;
+
+       kvfree(spec);
+       return 0;
+
+err_rule_2:
+       mlx5_fc_destroy(mdev, sa_entry->ipsec_rule.trailer.fc);
+err_cnt_2:
+       mlx5_del_flow_rules(sa_entry->ipsec_rule.auth.rule);
+err_rule:
+       mlx5_fc_destroy(mdev, sa_entry->ipsec_rule.auth.fc);
+err_cnt:
+       kvfree(spec);
+       return err;
+}
+
+static int rx_add_rule_drop_replay(struct mlx5e_ipsec_sa_entry *sa_entry, struct mlx5e_ipsec_rx *rx)
+{
+       struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
+       struct mlx5_flow_table *ft = rx->ft.status;
+       struct mlx5_core_dev *mdev = ipsec->mdev;
+       struct mlx5_flow_destination dest = {};
+       struct mlx5_flow_act flow_act = {};
+       struct mlx5_flow_handle *rule;
+       struct mlx5_fc *flow_counter;
+       struct mlx5_flow_spec *spec;
+       int err;
+
+       spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
+       if (!spec)
+               return -ENOMEM;
+
+       flow_counter = mlx5_fc_create(mdev, true);
+       if (IS_ERR(flow_counter)) {
+               err = PTR_ERR(flow_counter);
+               mlx5_core_err(mdev,
+                             "Failed to add ipsec rx status drop rule counter, err=%d\n", err);
+               goto err_cnt;
+       }
+
+       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT;
+       flow_act.flags = FLOW_ACT_NO_APPEND;
+       dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
+       dest.counter_id = mlx5_fc_id(flow_counter);
+       if (rx == ipsec->rx_esw)
+               spec->flow_context.flow_source = MLX5_FLOW_CONTEXT_FLOW_SOURCE_UPLINK;
+
+       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_4);
+       MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_4, 1);
+       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_2);
+       MLX5_SET(fte_match_param, spec->match_value,  misc_parameters_2.metadata_reg_c_2,
+                sa_entry->ipsec_obj_id | BIT(31));
+       spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
+       rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
+       if (IS_ERR(rule)) {
+               err = PTR_ERR(rule);
+               mlx5_core_err(mdev,
+                             "Failed to add ipsec rx status drop rule, err=%d\n", err);
+               goto err_rule;
+       }
+
+       sa_entry->ipsec_rule.replay.rule = rule;
+       sa_entry->ipsec_rule.replay.fc = flow_counter;
+
+       kvfree(spec);
+       return 0;
+
+err_rule:
+       mlx5_fc_destroy(mdev, flow_counter);
+err_cnt:
+       kvfree(spec);
+       return err;
+}
+
+static int ipsec_rx_status_drop_all_create(struct mlx5e_ipsec *ipsec,
+                                          struct mlx5e_ipsec_rx *rx)
+{
+       int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
+       struct mlx5_flow_table *ft = rx->ft.status;
+       struct mlx5_core_dev *mdev = ipsec->mdev;
+       struct mlx5_flow_destination dest = {};
+       struct mlx5_flow_act flow_act = {};
+       struct mlx5_flow_handle *rule;
+       struct mlx5_fc *flow_counter;
+       struct mlx5_flow_spec *spec;
+       struct mlx5_flow_group *g;
+       u32 *flow_group_in;
+       int err = 0;
+
+       flow_group_in = kvzalloc(inlen, GFP_KERNEL);
+       spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
+       if (!flow_group_in || !spec) {
+               err = -ENOMEM;
+               goto err_out;
+       }
+
+       MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, ft->max_fte - 1);
+       MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, ft->max_fte - 1);
+       g = mlx5_create_flow_group(ft, flow_group_in);
+       if (IS_ERR(g)) {
+               err = PTR_ERR(g);
+               mlx5_core_err(mdev,
+                             "Failed to add ipsec rx status drop flow group, err=%d\n", err);
+               goto err_out;
+       }
+
+       flow_counter = mlx5_fc_create(mdev, false);
+       if (IS_ERR(flow_counter)) {
+               err = PTR_ERR(flow_counter);
+               mlx5_core_err(mdev,
+                             "Failed to add ipsec rx status drop rule counter, err=%d\n", err);
+               goto err_cnt;
+       }
+
+       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT;
+       dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
+       dest.counter_id = mlx5_fc_id(flow_counter);
+       if (rx == ipsec->rx_esw)
+               spec->flow_context.flow_source = MLX5_FLOW_CONTEXT_FLOW_SOURCE_UPLINK;
+       rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
+       if (IS_ERR(rule)) {
+               err = PTR_ERR(rule);
+               mlx5_core_err(mdev,
+                             "Failed to add ipsec rx status drop rule, err=%d\n", err);
+               goto err_rule;
+       }
+
+       rx->status_drops.drop_all_group = g;
+       rx->status_drops.all.rule = rule;
+       rx->status_drops.all.fc = flow_counter;
+
+       kvfree(flow_group_in);
+       kvfree(spec);
+       return 0;
+
+err_rule:
+       mlx5_fc_destroy(mdev, flow_counter);
+err_cnt:
+       mlx5_destroy_flow_group(g);
+err_out:
+       kvfree(flow_group_in);
+       kvfree(spec);
+       return err;
+}
+
+static int ipsec_rx_status_pass_create(struct mlx5e_ipsec *ipsec,
+                                      struct mlx5e_ipsec_rx *rx,
+                                      struct mlx5_flow_destination *dest)
+{
+       struct mlx5_flow_act flow_act = {};
+       struct mlx5_flow_handle *rule;
+       struct mlx5_flow_spec *spec;
+       int err;
+
+       spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
+       if (!spec)
+               return -ENOMEM;
+
+       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
+                        misc_parameters_2.ipsec_syndrome);
+       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
+                        misc_parameters_2.metadata_reg_c_4);
+       MLX5_SET(fte_match_param, spec->match_value,
+                misc_parameters_2.ipsec_syndrome, 0);
+       MLX5_SET(fte_match_param, spec->match_value,
+                misc_parameters_2.metadata_reg_c_4, 0);
+       if (rx == ipsec->rx_esw)
+               spec->flow_context.flow_source = MLX5_FLOW_CONTEXT_FLOW_SOURCE_UPLINK;
+       spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
+       flow_act.flags = FLOW_ACT_NO_APPEND;
+       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
                          MLX5_FLOW_CONTEXT_ACTION_COUNT;
-       flow_act.modify_hdr = modify_hdr;
-       fte = mlx5_add_flow_rules(rx->ft.status, spec, &flow_act, dest, 2);
-       if (IS_ERR(fte)) {
-               err = PTR_ERR(fte);
-               mlx5_core_err(mdev, "fail to add ipsec rx err copy rule err=%d\n", err);
-               goto out;
+       rule = mlx5_add_flow_rules(rx->ft.status, spec, &flow_act, dest, 2);
+       if (IS_ERR(rule)) {
+               err = PTR_ERR(rule);
+               mlx5_core_warn(ipsec->mdev,
+                              "Failed to add ipsec rx status pass rule, err=%d\n", err);
+               goto err_rule;
        }
 
+       rx->status.rule = rule;
        kvfree(spec);
-       rx->status.rule = fte;
-       rx->status.modify_hdr = modify_hdr;
        return 0;
 
-out:
-       mlx5_modify_header_dealloc(mdev, modify_hdr);
-out_spec:
+err_rule:
        kvfree(spec);
        return err;
 }
 
+static void mlx5_ipsec_rx_status_destroy(struct mlx5e_ipsec *ipsec,
+                                        struct mlx5e_ipsec_rx *rx)
+{
+       ipsec_rx_status_pass_destroy(ipsec, rx);
+       ipsec_rx_status_drop_destroy(ipsec, rx);
+}
+
+static int mlx5_ipsec_rx_status_create(struct mlx5e_ipsec *ipsec,
+                                      struct mlx5e_ipsec_rx *rx,
+                                      struct mlx5_flow_destination *dest)
+{
+       int err;
+
+       err = ipsec_rx_status_drop_all_create(ipsec, rx);
+       if (err)
+               return err;
+
+       err = ipsec_rx_status_pass_create(ipsec, rx, dest);
+       if (err)
+               goto err_pass_create;
+
+       return 0;
+
+err_pass_create:
+       ipsec_rx_status_drop_destroy(ipsec, rx);
+       return err;
+}
+
 static int ipsec_miss_create(struct mlx5_core_dev *mdev,
                             struct mlx5_flow_table *ft,
                             struct mlx5e_ipsec_miss *miss,
@@ -333,12 +597,7 @@ static void rx_destroy(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec,
        mlx5_destroy_flow_table(rx->ft.sa);
        if (rx->allow_tunnel_mode)
                mlx5_eswitch_unblock_encap(mdev);
-       if (rx == ipsec->rx_esw) {
-               mlx5_esw_ipsec_rx_status_destroy(ipsec, rx);
-       } else {
-               mlx5_del_flow_rules(rx->status.rule);
-               mlx5_modify_header_dealloc(mdev, rx->status.modify_hdr);
-       }
+       mlx5_ipsec_rx_status_destroy(ipsec, rx);
        mlx5_destroy_flow_table(rx->ft.status);
 
        mlx5_ipsec_fs_roce_rx_destroy(ipsec->roce, family, mdev);
@@ -419,7 +678,7 @@ static int rx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec,
        if (err)
                return err;
 
-       ft = ipsec_ft_create(attr.ns, attr.status_level, attr.prio, 1, 0);
+       ft = ipsec_ft_create(attr.ns, attr.status_level, attr.prio, 3, 0);
        if (IS_ERR(ft)) {
                err = PTR_ERR(ft);
                goto err_fs_ft_status;
@@ -428,10 +687,7 @@ static int rx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec,
 
        dest[1].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
        dest[1].counter_id = mlx5_fc_id(rx->fc->cnt);
-       if (rx == ipsec->rx_esw)
-               err = mlx5_esw_ipsec_rx_status_create(ipsec, rx, dest);
-       else
-               err = ipsec_status_rule(mdev, rx, dest);
+       err = mlx5_ipsec_rx_status_create(ipsec, rx, dest);
        if (err)
                goto err_add;
 
@@ -956,13 +1212,22 @@ static void setup_fte_esp(struct mlx5_flow_spec *spec)
        MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_protocol, IPPROTO_ESP);
 }
 
-static void setup_fte_spi(struct mlx5_flow_spec *spec, u32 spi)
+static void setup_fte_spi(struct mlx5_flow_spec *spec, u32 spi, bool encap)
 {
        /* SPI number */
        spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS;
 
-       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters.outer_esp_spi);
-       MLX5_SET(fte_match_param, spec->match_value, misc_parameters.outer_esp_spi, spi);
+       if (encap) {
+               MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
+                                misc_parameters.inner_esp_spi);
+               MLX5_SET(fte_match_param, spec->match_value,
+                        misc_parameters.inner_esp_spi, spi);
+       } else {
+               MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
+                                misc_parameters.outer_esp_spi);
+               MLX5_SET(fte_match_param, spec->match_value,
+                        misc_parameters.outer_esp_spi, spi);
+       }
 }
 
 static void setup_fte_no_frags(struct mlx5_flow_spec *spec)
@@ -1052,29 +1317,48 @@ static int setup_modify_header(struct mlx5e_ipsec *ipsec, int type, u32 val, u8
                               struct mlx5_flow_act *flow_act)
 {
        enum mlx5_flow_namespace_type ns_type = ipsec_fs_get_ns(ipsec, type, dir);
-       u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {};
+       u8 action[3][MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {};
        struct mlx5_core_dev *mdev = ipsec->mdev;
        struct mlx5_modify_hdr *modify_hdr;
+       u8 num_of_actions = 1;
 
-       MLX5_SET(set_action_in, action, action_type, MLX5_ACTION_TYPE_SET);
+       MLX5_SET(set_action_in, action[0], action_type, MLX5_ACTION_TYPE_SET);
        switch (dir) {
        case XFRM_DEV_OFFLOAD_IN:
-               MLX5_SET(set_action_in, action, field,
+               MLX5_SET(set_action_in, action[0], field,
                         MLX5_ACTION_IN_FIELD_METADATA_REG_B);
+
+               num_of_actions++;
+               MLX5_SET(set_action_in, action[1], action_type, MLX5_ACTION_TYPE_SET);
+               MLX5_SET(set_action_in, action[1], field, MLX5_ACTION_IN_FIELD_METADATA_REG_C_2);
+               MLX5_SET(set_action_in, action[1], data, val);
+               MLX5_SET(set_action_in, action[1], offset, 0);
+               MLX5_SET(set_action_in, action[1], length, 32);
+
+               if (type == XFRM_DEV_OFFLOAD_CRYPTO) {
+                       num_of_actions++;
+                       MLX5_SET(set_action_in, action[2], action_type,
+                                MLX5_ACTION_TYPE_SET);
+                       MLX5_SET(set_action_in, action[2], field,
+                                MLX5_ACTION_IN_FIELD_METADATA_REG_C_4);
+                       MLX5_SET(set_action_in, action[2], data, 0);
+                       MLX5_SET(set_action_in, action[2], offset, 0);
+                       MLX5_SET(set_action_in, action[2], length, 32);
+               }
                break;
        case XFRM_DEV_OFFLOAD_OUT:
-               MLX5_SET(set_action_in, action, field,
+               MLX5_SET(set_action_in, action[0], field,
                         MLX5_ACTION_IN_FIELD_METADATA_REG_C_4);
                break;
        default:
                return -EINVAL;
        }
 
-       MLX5_SET(set_action_in, action, data, val);
-       MLX5_SET(set_action_in, action, offset, 0);
-       MLX5_SET(set_action_in, action, length, 32);
+       MLX5_SET(set_action_in, action[0], data, val);
+       MLX5_SET(set_action_in, action[0], offset, 0);
+       MLX5_SET(set_action_in, action[0], length, 32);
 
-       modify_hdr = mlx5_modify_header_alloc(mdev, ns_type, 1, action);
+       modify_hdr = mlx5_modify_header_alloc(mdev, ns_type, num_of_actions, action);
        if (IS_ERR(modify_hdr)) {
                mlx5_core_err(mdev, "Failed to allocate modify_header %ld\n",
                              PTR_ERR(modify_hdr));
@@ -1321,8 +1605,9 @@ static int rx_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry)
        else
                setup_fte_addr6(spec, attrs->saddr.a6, attrs->daddr.a6);
 
-       setup_fte_spi(spec, attrs->spi);
-       setup_fte_esp(spec);
+       setup_fte_spi(spec, attrs->spi, attrs->encap);
+       if (!attrs->encap)
+               setup_fte_esp(spec);
        setup_fte_no_frags(spec);
        setup_fte_upper_proto_match(spec, &attrs->upspec);
 
@@ -1372,6 +1657,15 @@ static int rx_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry)
                mlx5_core_err(mdev, "fail to add RX ipsec rule err=%d\n", err);
                goto err_add_flow;
        }
+       if (attrs->type == XFRM_DEV_OFFLOAD_PACKET)
+               err = rx_add_rule_drop_replay(sa_entry, rx);
+       if (err)
+               goto err_add_replay;
+
+       err = rx_add_rule_drop_auth_trailer(sa_entry, rx);
+       if (err)
+               goto err_drop_reason;
+
        kvfree(spec);
 
        sa_entry->ipsec_rule.rule = rule;
@@ -1380,6 +1674,13 @@ static int rx_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry)
        sa_entry->ipsec_rule.pkt_reformat = flow_act.pkt_reformat;
        return 0;
 
+err_drop_reason:
+       if (sa_entry->ipsec_rule.replay.rule) {
+               mlx5_del_flow_rules(sa_entry->ipsec_rule.replay.rule);
+               mlx5_fc_destroy(mdev, sa_entry->ipsec_rule.replay.fc);
+       }
+err_add_replay:
+       mlx5_del_flow_rules(rule);
 err_add_flow:
        mlx5_fc_destroy(mdev, counter);
 err_add_cnt:
@@ -1428,7 +1729,7 @@ static int tx_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry)
 
        switch (attrs->type) {
        case XFRM_DEV_OFFLOAD_CRYPTO:
-               setup_fte_spi(spec, attrs->spi);
+               setup_fte_spi(spec, attrs->spi, false);
                setup_fte_esp(spec);
                setup_fte_reg_a(spec);
                break;
@@ -1809,8 +2110,11 @@ static int mlx5e_ipsec_block_tc_offload(struct mlx5_core_dev *mdev)
        struct mlx5_eswitch *esw = mdev->priv.eswitch;
        int err = 0;
 
-       if (esw)
-               down_write(&esw->mode_lock);
+       if (esw) {
+               err = mlx5_esw_lock(esw);
+               if (err)
+                       return err;
+       }
 
        if (mdev->num_block_ipsec) {
                err = -EBUSY;
@@ -1821,7 +2125,7 @@ static int mlx5e_ipsec_block_tc_offload(struct mlx5_core_dev *mdev)
 
 unlock:
        if (esw)
-               up_write(&esw->mode_lock);
+               mlx5_esw_unlock(esw);
 
        return err;
 }
@@ -1887,6 +2191,17 @@ void mlx5e_accel_ipsec_fs_del_rule(struct mlx5e_ipsec_sa_entry *sa_entry)
 
        if (ipsec_rule->modify_hdr)
                mlx5_modify_header_dealloc(mdev, ipsec_rule->modify_hdr);
+
+       mlx5_del_flow_rules(ipsec_rule->trailer.rule);
+       mlx5_fc_destroy(mdev, ipsec_rule->trailer.fc);
+
+       mlx5_del_flow_rules(ipsec_rule->auth.rule);
+       mlx5_fc_destroy(mdev, ipsec_rule->auth.fc);
+
+       if (ipsec_rule->replay.rule) {
+               mlx5_del_flow_rules(ipsec_rule->replay.rule);
+               mlx5_fc_destroy(mdev, ipsec_rule->replay.fc);
+       }
        mlx5_esw_ipsec_rx_id_mapping_remove(sa_entry);
        rx_ft_put(sa_entry->ipsec, sa_entry->attrs.family, sa_entry->attrs.type);
 }
@@ -1957,7 +2272,7 @@ void mlx5e_accel_ipsec_fs_cleanup(struct mlx5e_ipsec *ipsec)
        kfree(ipsec->rx_ipv6);
 
        if (ipsec->is_uplink_rep) {
-               xa_destroy(&ipsec->rx_esw->ipsec_obj_id_map);
+               xa_destroy(&ipsec->ipsec_obj_id_map);
 
                mutex_destroy(&ipsec->tx_esw->ft.mutex);
                WARN_ON(ipsec->tx_esw->ft.refcnt);
@@ -2020,7 +2335,7 @@ int mlx5e_accel_ipsec_fs_init(struct mlx5e_ipsec *ipsec,
                mutex_init(&ipsec->tx_esw->ft.mutex);
                mutex_init(&ipsec->rx_esw->ft.mutex);
                ipsec->tx_esw->ns = ns_esw;
-               xa_init_flags(&ipsec->rx_esw->ipsec_obj_id_map, XA_FLAGS_ALLOC1);
+               xa_init_flags(&ipsec->ipsec_obj_id_map, XA_FLAGS_ALLOC1);
        } else if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_ROCE) {
                ipsec->roce = mlx5_ipsec_fs_roce_init(mdev, devcom);
        } else {
index a91f772dc981a15f3834409bb1f4f5973a9c2236..6e00afe4671b78ae48eb3eaaddf8456eb09ab0e4 100644 (file)
@@ -6,6 +6,8 @@
 #include "ipsec.h"
 #include "lib/crypto.h"
 #include "lib/ipsec_fs_roce.h"
+#include "fs_core.h"
+#include "eswitch.h"
 
 enum {
        MLX5_IPSEC_ASO_REMOVE_FLOW_PKT_CNT_OFFSET,
@@ -38,7 +40,10 @@ u32 mlx5_ipsec_device_caps(struct mlx5_core_dev *mdev)
            MLX5_CAP_ETH(mdev, insert_trailer) && MLX5_CAP_ETH(mdev, swp))
                caps |= MLX5_IPSEC_CAP_CRYPTO;
 
-       if (MLX5_CAP_IPSEC(mdev, ipsec_full_offload)) {
+       if (MLX5_CAP_IPSEC(mdev, ipsec_full_offload) &&
+           (mdev->priv.steering->mode == MLX5_FLOW_STEERING_MODE_DMFS ||
+            (mdev->priv.steering->mode == MLX5_FLOW_STEERING_MODE_SMFS &&
+            is_mdev_legacy_mode(mdev)))) {
                if (MLX5_CAP_FLOWTABLE_NIC_TX(mdev,
                                              reformat_add_esp_trasport) &&
                    MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
@@ -95,7 +100,7 @@ static void mlx5e_ipsec_packet_setup(void *obj, u32 pdn,
 
                if (attrs->dir == XFRM_DEV_OFFLOAD_IN) {
                        MLX5_SET(ipsec_aso, aso_ctx, window_sz,
-                                attrs->replay_esn.replay_window / 64);
+                                attrs->replay_esn.replay_window);
                        MLX5_SET(ipsec_aso, aso_ctx, mode,
                                 MLX5_IPSEC_ASO_REPLAY_PROTECTION);
                }
@@ -559,6 +564,7 @@ void mlx5e_ipsec_aso_cleanup(struct mlx5e_ipsec *ipsec)
        dma_unmap_single(pdev, aso->dma_addr, sizeof(aso->ctx),
                         DMA_BIDIRECTIONAL);
        kfree(aso);
+       ipsec->aso = NULL;
 }
 
 static void mlx5e_ipsec_aso_copy(struct mlx5_wqe_aso_ctrl_seg *ctrl,
index ea58c691743302bfc0ccc4420f15ff4ff06e3cae..0c87ddb8a7a2188cef8a586bb5df04da5241f969 100644 (file)
@@ -2731,6 +2731,7 @@ void mlx5e_close_channels(struct mlx5e_channels *chs)
 {
        int i;
 
+       ASSERT_RTNL();
        if (chs->ptp) {
                mlx5e_ptp_close(chs->ptp);
                chs->ptp = NULL;
@@ -3012,17 +3013,29 @@ void mlx5e_activate_priv_channels(struct mlx5e_priv *priv)
        if (mlx5e_is_vport_rep(priv))
                mlx5e_rep_activate_channels(priv);
 
+       set_bit(MLX5E_STATE_CHANNELS_ACTIVE, &priv->state);
+
        mlx5e_wait_channels_min_rx_wqes(&priv->channels);
 
        if (priv->rx_res)
                mlx5e_rx_res_channels_activate(priv->rx_res, &priv->channels);
 }
 
+static void mlx5e_cancel_tx_timeout_work(struct mlx5e_priv *priv)
+{
+       WARN_ON_ONCE(test_bit(MLX5E_STATE_CHANNELS_ACTIVE, &priv->state));
+       if (current_work() != &priv->tx_timeout_work)
+               cancel_work_sync(&priv->tx_timeout_work);
+}
+
 void mlx5e_deactivate_priv_channels(struct mlx5e_priv *priv)
 {
        if (priv->rx_res)
                mlx5e_rx_res_channels_deactivate(priv->rx_res);
 
+       clear_bit(MLX5E_STATE_CHANNELS_ACTIVE, &priv->state);
+       mlx5e_cancel_tx_timeout_work(priv);
+
        if (mlx5e_is_vport_rep(priv))
                mlx5e_rep_deactivate_channels(priv);
 
@@ -4801,8 +4814,17 @@ static void mlx5e_tx_timeout_work(struct work_struct *work)
        struct net_device *netdev = priv->netdev;
        int i;
 
-       rtnl_lock();
-       mutex_lock(&priv->state_lock);
+       /* Take rtnl_lock to ensure no change in netdev->real_num_tx_queues
+        * through this flow. However, channel closing flows have to wait for
+        * this work to finish while holding rtnl lock too. So either get the
+        * lock or find that channels are being closed for other reason and
+        * this work is not relevant anymore.
+        */
+       while (!rtnl_trylock()) {
+               if (!test_bit(MLX5E_STATE_CHANNELS_ACTIVE, &priv->state))
+                       return;
+               msleep(20);
+       }
 
        if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
                goto unlock;
@@ -4821,7 +4843,6 @@ static void mlx5e_tx_timeout_work(struct work_struct *work)
        }
 
 unlock:
-       mutex_unlock(&priv->state_lock);
        rtnl_unlock();
 }
 
index 3ab682bbcf86780fa16daa27bc99baf9219bd88e..1bf7540a65ad95e61dbf9e918f475599500d1252 100644 (file)
@@ -1497,7 +1497,7 @@ mlx5e_vport_vf_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
 
        dl_port = mlx5_esw_offloads_devlink_port(dev->priv.eswitch,
                                                 rpriv->rep->vport);
-       if (dl_port) {
+       if (!IS_ERR(dl_port)) {
                SET_NETDEV_DEVLINK_PORT(netdev, dl_port);
                mlx5e_rep_vnic_reporter_create(priv, dl_port);
        }
index 7ca9e5b86778e3b0353530c4ce021a1fa8e5fd21..4809a66f3491a6234f17675b3e550bb45bf3afaf 100644 (file)
@@ -444,6 +444,9 @@ mlx5e_tc_add_flow_meter(struct mlx5e_priv *priv,
        struct mlx5e_flow_meter_handle *meter;
        enum mlx5e_post_meter_type type;
 
+       if (IS_ERR(post_act))
+               return PTR_ERR(post_act);
+
        meter = mlx5e_tc_meter_replace(priv->mdev, &attr->meter_attr.params);
        if (IS_ERR(meter)) {
                mlx5_core_err(priv->mdev, "Failed to get flow meter\n");
@@ -3738,6 +3741,20 @@ out_free:
        return err;
 }
 
+static int
+set_branch_dest_ft(struct mlx5e_priv *priv, struct mlx5_flow_attr *attr)
+{
+       struct mlx5e_post_act *post_act = get_post_action(priv);
+
+       if (IS_ERR(post_act))
+               return PTR_ERR(post_act);
+
+       attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
+       attr->dest_ft = mlx5e_tc_post_act_get_ft(post_act);
+
+       return 0;
+}
+
 static int
 alloc_branch_attr(struct mlx5e_tc_flow *flow,
                  struct mlx5e_tc_act_branch_ctrl *cond,
@@ -3761,8 +3778,8 @@ alloc_branch_attr(struct mlx5e_tc_flow *flow,
                break;
        case FLOW_ACTION_ACCEPT:
        case FLOW_ACTION_PIPE:
-               attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
-               attr->dest_ft = mlx5e_tc_post_act_get_ft(get_post_action(flow->priv));
+               if (set_branch_dest_ft(flow->priv, attr))
+                       goto out_err;
                break;
        case FLOW_ACTION_JUMP:
                if (*jump_count) {
@@ -3771,8 +3788,8 @@ alloc_branch_attr(struct mlx5e_tc_flow *flow,
                        goto out_err;
                }
                *jump_count = cond->extval;
-               attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
-               attr->dest_ft = mlx5e_tc_post_act_get_ft(get_post_action(flow->priv));
+               if (set_branch_dest_ft(flow->priv, attr))
+                       goto out_err;
                break;
        default:
                err = -EOPNOTSUPP;
index 095f31f380fa3aa8bc9c2a122ac2dc365dc5332d..190f10aba17028211fc6c34abaa7b35d44310ba2 100644 (file)
@@ -21,158 +21,6 @@ enum {
        MLX5_ESW_IPSEC_TX_ESP_FT_CNT_LEVEL,
 };
 
-static void esw_ipsec_rx_status_drop_destroy(struct mlx5e_ipsec *ipsec,
-                                            struct mlx5e_ipsec_rx *rx)
-{
-       mlx5_del_flow_rules(rx->status_drop.rule);
-       mlx5_destroy_flow_group(rx->status_drop.group);
-       mlx5_fc_destroy(ipsec->mdev, rx->status_drop_cnt);
-}
-
-static void esw_ipsec_rx_status_pass_destroy(struct mlx5e_ipsec *ipsec,
-                                            struct mlx5e_ipsec_rx *rx)
-{
-       mlx5_del_flow_rules(rx->status.rule);
-       mlx5_chains_put_table(esw_chains(ipsec->mdev->priv.eswitch), 0, 1, 0);
-}
-
-static int esw_ipsec_rx_status_drop_create(struct mlx5e_ipsec *ipsec,
-                                          struct mlx5e_ipsec_rx *rx)
-{
-       int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
-       struct mlx5_flow_table *ft = rx->ft.status;
-       struct mlx5_core_dev *mdev = ipsec->mdev;
-       struct mlx5_flow_destination dest = {};
-       struct mlx5_flow_act flow_act = {};
-       struct mlx5_flow_handle *rule;
-       struct mlx5_fc *flow_counter;
-       struct mlx5_flow_spec *spec;
-       struct mlx5_flow_group *g;
-       u32 *flow_group_in;
-       int err = 0;
-
-       flow_group_in = kvzalloc(inlen, GFP_KERNEL);
-       spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
-       if (!flow_group_in || !spec) {
-               err = -ENOMEM;
-               goto err_out;
-       }
-
-       MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, ft->max_fte - 1);
-       MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, ft->max_fte - 1);
-       g = mlx5_create_flow_group(ft, flow_group_in);
-       if (IS_ERR(g)) {
-               err = PTR_ERR(g);
-               mlx5_core_err(mdev,
-                             "Failed to add ipsec rx status drop flow group, err=%d\n", err);
-               goto err_out;
-       }
-
-       flow_counter = mlx5_fc_create(mdev, false);
-       if (IS_ERR(flow_counter)) {
-               err = PTR_ERR(flow_counter);
-               mlx5_core_err(mdev,
-                             "Failed to add ipsec rx status drop rule counter, err=%d\n", err);
-               goto err_cnt;
-       }
-
-       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT;
-       dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
-       dest.counter_id = mlx5_fc_id(flow_counter);
-       spec->flow_context.flow_source = MLX5_FLOW_CONTEXT_FLOW_SOURCE_UPLINK;
-       rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
-       if (IS_ERR(rule)) {
-               err = PTR_ERR(rule);
-               mlx5_core_err(mdev,
-                             "Failed to add ipsec rx status drop rule, err=%d\n", err);
-               goto err_rule;
-       }
-
-       rx->status_drop.group = g;
-       rx->status_drop.rule = rule;
-       rx->status_drop_cnt = flow_counter;
-
-       kvfree(flow_group_in);
-       kvfree(spec);
-       return 0;
-
-err_rule:
-       mlx5_fc_destroy(mdev, flow_counter);
-err_cnt:
-       mlx5_destroy_flow_group(g);
-err_out:
-       kvfree(flow_group_in);
-       kvfree(spec);
-       return err;
-}
-
-static int esw_ipsec_rx_status_pass_create(struct mlx5e_ipsec *ipsec,
-                                          struct mlx5e_ipsec_rx *rx,
-                                          struct mlx5_flow_destination *dest)
-{
-       struct mlx5_flow_act flow_act = {};
-       struct mlx5_flow_handle *rule;
-       struct mlx5_flow_spec *spec;
-       int err;
-
-       spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
-       if (!spec)
-               return -ENOMEM;
-
-       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
-                        misc_parameters_2.ipsec_syndrome);
-       MLX5_SET(fte_match_param, spec->match_value,
-                misc_parameters_2.ipsec_syndrome, 0);
-       spec->flow_context.flow_source = MLX5_FLOW_CONTEXT_FLOW_SOURCE_UPLINK;
-       spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
-       flow_act.flags = FLOW_ACT_NO_APPEND;
-       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
-                         MLX5_FLOW_CONTEXT_ACTION_COUNT;
-       rule = mlx5_add_flow_rules(rx->ft.status, spec, &flow_act, dest, 2);
-       if (IS_ERR(rule)) {
-               err = PTR_ERR(rule);
-               mlx5_core_warn(ipsec->mdev,
-                              "Failed to add ipsec rx status pass rule, err=%d\n", err);
-               goto err_rule;
-       }
-
-       rx->status.rule = rule;
-       kvfree(spec);
-       return 0;
-
-err_rule:
-       kvfree(spec);
-       return err;
-}
-
-void mlx5_esw_ipsec_rx_status_destroy(struct mlx5e_ipsec *ipsec,
-                                     struct mlx5e_ipsec_rx *rx)
-{
-       esw_ipsec_rx_status_pass_destroy(ipsec, rx);
-       esw_ipsec_rx_status_drop_destroy(ipsec, rx);
-}
-
-int mlx5_esw_ipsec_rx_status_create(struct mlx5e_ipsec *ipsec,
-                                   struct mlx5e_ipsec_rx *rx,
-                                   struct mlx5_flow_destination *dest)
-{
-       int err;
-
-       err = esw_ipsec_rx_status_drop_create(ipsec, rx);
-       if (err)
-               return err;
-
-       err = esw_ipsec_rx_status_pass_create(ipsec, rx, dest);
-       if (err)
-               goto err_pass_create;
-
-       return 0;
-
-err_pass_create:
-       esw_ipsec_rx_status_drop_destroy(ipsec, rx);
-       return err;
-}
-
 void mlx5_esw_ipsec_rx_create_attr_set(struct mlx5e_ipsec *ipsec,
                                       struct mlx5e_ipsec_rx_create_attr *attr)
 {
@@ -202,7 +50,7 @@ int mlx5_esw_ipsec_rx_setup_modify_header(struct mlx5e_ipsec_sa_entry *sa_entry,
        u32 mapped_id;
        int err;
 
-       err = xa_alloc_bh(&ipsec->rx_esw->ipsec_obj_id_map, &mapped_id,
+       err = xa_alloc_bh(&ipsec->ipsec_obj_id_map, &mapped_id,
                          xa_mk_value(sa_entry->ipsec_obj_id),
                          XA_LIMIT(1, ESW_IPSEC_RX_MAPPED_ID_MASK), 0);
        if (err)
@@ -233,7 +81,7 @@ int mlx5_esw_ipsec_rx_setup_modify_header(struct mlx5e_ipsec_sa_entry *sa_entry,
        return 0;
 
 err_header_alloc:
-       xa_erase_bh(&ipsec->rx_esw->ipsec_obj_id_map, mapped_id);
+       xa_erase_bh(&ipsec->ipsec_obj_id_map, mapped_id);
        return err;
 }
 
@@ -242,7 +90,7 @@ void mlx5_esw_ipsec_rx_id_mapping_remove(struct mlx5e_ipsec_sa_entry *sa_entry)
        struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
 
        if (sa_entry->rx_mapped_id)
-               xa_erase_bh(&ipsec->rx_esw->ipsec_obj_id_map,
+               xa_erase_bh(&ipsec->ipsec_obj_id_map,
                            sa_entry->rx_mapped_id);
 }
 
@@ -252,7 +100,7 @@ int mlx5_esw_ipsec_rx_ipsec_obj_id_search(struct mlx5e_priv *priv, u32 id,
        struct mlx5e_ipsec *ipsec = priv->ipsec;
        void *val;
 
-       val = xa_load(&ipsec->rx_esw->ipsec_obj_id_map, id);
+       val = xa_load(&ipsec->ipsec_obj_id_map, id);
        if (!val)
                return -ENOENT;
 
@@ -304,7 +152,7 @@ void mlx5_esw_ipsec_restore_dest_uplink(struct mlx5_core_dev *mdev)
 
        xa_for_each(&esw->offloads.vport_reps, i, rep) {
                rpriv = rep->rep_data[REP_ETH].priv;
-               if (!rpriv || !rpriv->netdev)
+               if (!rpriv || !rpriv->netdev || !atomic_read(&rpriv->tc_ht.nelems))
                        continue;
 
                rhashtable_walk_enter(&rpriv->tc_ht, &iter);
index 0c90f7a8b0d32c7e4268fc1becfee6ffb2229ea1..ac9c65b89166e6fda902d51310900a7c50894928 100644 (file)
@@ -8,11 +8,6 @@ struct mlx5e_ipsec;
 struct mlx5e_ipsec_sa_entry;
 
 #ifdef CONFIG_MLX5_ESWITCH
-void mlx5_esw_ipsec_rx_status_destroy(struct mlx5e_ipsec *ipsec,
-                                     struct mlx5e_ipsec_rx *rx);
-int mlx5_esw_ipsec_rx_status_create(struct mlx5e_ipsec *ipsec,
-                                   struct mlx5e_ipsec_rx *rx,
-                                   struct mlx5_flow_destination *dest);
 void mlx5_esw_ipsec_rx_create_attr_set(struct mlx5e_ipsec *ipsec,
                                       struct mlx5e_ipsec_rx_create_attr *attr);
 int mlx5_esw_ipsec_rx_status_pass_dest_get(struct mlx5e_ipsec *ipsec,
@@ -26,16 +21,6 @@ void mlx5_esw_ipsec_tx_create_attr_set(struct mlx5e_ipsec *ipsec,
                                       struct mlx5e_ipsec_tx_create_attr *attr);
 void mlx5_esw_ipsec_restore_dest_uplink(struct mlx5_core_dev *mdev);
 #else
-static inline void mlx5_esw_ipsec_rx_status_destroy(struct mlx5e_ipsec *ipsec,
-                                                   struct mlx5e_ipsec_rx *rx) {}
-
-static inline int mlx5_esw_ipsec_rx_status_create(struct mlx5e_ipsec *ipsec,
-                                                 struct mlx5e_ipsec_rx *rx,
-                                                 struct mlx5_flow_destination *dest)
-{
-       return  -EINVAL;
-}
-
 static inline void mlx5_esw_ipsec_rx_create_attr_set(struct mlx5e_ipsec *ipsec,
                                                     struct mlx5e_ipsec_rx_create_attr *attr) {}
 
index 8d0b915a31214ea83366bfdcbabcc8ec0c232eaf..3047d7015c5256726338904432ce56845c59c39c 100644 (file)
@@ -1463,7 +1463,7 @@ int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int num_vfs)
 {
        int err;
 
-       lockdep_assert_held(&esw->mode_lock);
+       devl_assert_locked(priv_to_devlink(esw->dev));
 
        if (!MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ft_support)) {
                esw_warn(esw->dev, "FDB is not supported, aborting ...\n");
@@ -1531,7 +1531,6 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs)
        if (toggle_lag)
                mlx5_lag_disable_change(esw->dev);
 
-       down_write(&esw->mode_lock);
        if (!mlx5_esw_is_fdb_created(esw)) {
                ret = mlx5_eswitch_enable_locked(esw, num_vfs);
        } else {
@@ -1554,8 +1553,6 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs)
                }
        }
 
-       up_write(&esw->mode_lock);
-
        if (toggle_lag)
                mlx5_lag_enable_change(esw->dev);
 
@@ -1569,12 +1566,11 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf)
                return;
 
        devl_assert_locked(priv_to_devlink(esw->dev));
-       down_write(&esw->mode_lock);
        /* If driver is unloaded, this function is called twice by remove_one()
         * and mlx5_unload(). Prevent the second call.
         */
        if (!esw->esw_funcs.num_vfs && !esw->esw_funcs.num_ec_vfs && !clear_vf)
-               goto unlock;
+               return;
 
        esw_info(esw->dev, "Unload vfs: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n",
                 esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS",
@@ -1603,9 +1599,6 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf)
                esw->esw_funcs.num_vfs = 0;
        else
                esw->esw_funcs.num_ec_vfs = 0;
-
-unlock:
-       up_write(&esw->mode_lock);
 }
 
 /* Free resources for corresponding eswitch mode. It is called by devlink
@@ -1647,10 +1640,8 @@ void mlx5_eswitch_disable(struct mlx5_eswitch *esw)
 
        devl_assert_locked(priv_to_devlink(esw->dev));
        mlx5_lag_disable_change(esw->dev);
-       down_write(&esw->mode_lock);
        mlx5_eswitch_disable_locked(esw);
        esw->mode = MLX5_ESWITCH_LEGACY;
-       up_write(&esw->mode_lock);
        mlx5_lag_enable_change(esw->dev);
 }
 
@@ -2254,8 +2245,13 @@ bool mlx5_esw_hold(struct mlx5_core_dev *mdev)
        if (!mlx5_esw_allowed(esw))
                return true;
 
-       if (down_read_trylock(&esw->mode_lock) != 0)
+       if (down_read_trylock(&esw->mode_lock) != 0) {
+               if (esw->eswitch_operation_in_progress) {
+                       up_read(&esw->mode_lock);
+                       return false;
+               }
                return true;
+       }
 
        return false;
 }
@@ -2312,7 +2308,8 @@ int mlx5_esw_try_lock(struct mlx5_eswitch *esw)
        if (down_write_trylock(&esw->mode_lock) == 0)
                return -EINVAL;
 
-       if (atomic64_read(&esw->user_count) > 0) {
+       if (esw->eswitch_operation_in_progress ||
+           atomic64_read(&esw->user_count) > 0) {
                up_write(&esw->mode_lock);
                return -EBUSY;
        }
@@ -2320,6 +2317,18 @@ int mlx5_esw_try_lock(struct mlx5_eswitch *esw)
        return esw->mode;
 }
 
+int mlx5_esw_lock(struct mlx5_eswitch *esw)
+{
+       down_write(&esw->mode_lock);
+
+       if (esw->eswitch_operation_in_progress) {
+               up_write(&esw->mode_lock);
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
 /**
  * mlx5_esw_unlock() - Release write lock on esw mode lock
  * @esw: eswitch device.
index 37ab66e7b403f1d86d3242e3fdabe7ce5bdcc49a..b674b57d05aad3ed340e8d19bc59ca569153395a 100644 (file)
@@ -383,6 +383,7 @@ struct mlx5_eswitch {
        struct xarray paired;
        struct mlx5_devcom_comp_dev *devcom;
        u16 enabled_ipsec_vf_count;
+       bool eswitch_operation_in_progress;
 };
 
 void esw_offloads_disable(struct mlx5_eswitch *esw);
@@ -827,6 +828,7 @@ void mlx5_esw_release(struct mlx5_core_dev *dev);
 void mlx5_esw_get(struct mlx5_core_dev *dev);
 void mlx5_esw_put(struct mlx5_core_dev *dev);
 int mlx5_esw_try_lock(struct mlx5_eswitch *esw);
+int mlx5_esw_lock(struct mlx5_eswitch *esw);
 void mlx5_esw_unlock(struct mlx5_eswitch *esw);
 
 void esw_vport_change_handle_locked(struct mlx5_vport *vport);
index 88236e75fd9013058dd855a77073ed21cb1e8afe..bb8bcb448ae903c6bdb66e67722075c8073773bb 100644 (file)
@@ -3653,14 +3653,18 @@ static int esw_inline_mode_to_devlink(u8 mlx5_mode, u8 *mode)
 
 static bool esw_offloads_devlink_ns_eq_netdev_ns(struct devlink *devlink)
 {
+       struct mlx5_core_dev *dev = devlink_priv(devlink);
        struct net *devl_net, *netdev_net;
-       struct mlx5_eswitch *esw;
-
-       esw = mlx5_devlink_eswitch_nocheck_get(devlink);
-       netdev_net = dev_net(esw->dev->mlx5e_res.uplink_netdev);
-       devl_net = devlink_net(devlink);
+       bool ret = false;
 
-       return net_eq(devl_net, netdev_net);
+       mutex_lock(&dev->mlx5e_res.uplink_netdev_lock);
+       if (dev->mlx5e_res.uplink_netdev) {
+               netdev_net = dev_net(dev->mlx5e_res.uplink_netdev);
+               devl_net = devlink_net(devlink);
+               ret = net_eq(devl_net, netdev_net);
+       }
+       mutex_unlock(&dev->mlx5e_res.uplink_netdev_lock);
+       return ret;
 }
 
 int mlx5_eswitch_block_mode(struct mlx5_core_dev *dev)
@@ -3733,13 +3737,16 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
                goto unlock;
        }
 
+       esw->eswitch_operation_in_progress = true;
+       up_write(&esw->mode_lock);
+
        mlx5_eswitch_disable_locked(esw);
        if (mode == DEVLINK_ESWITCH_MODE_SWITCHDEV) {
                if (mlx5_devlink_trap_get_num_active(esw->dev)) {
                        NL_SET_ERR_MSG_MOD(extack,
                                           "Can't change mode while devlink traps are active");
                        err = -EOPNOTSUPP;
-                       goto unlock;
+                       goto skip;
                }
                err = esw_offloads_start(esw, extack);
        } else if (mode == DEVLINK_ESWITCH_MODE_LEGACY) {
@@ -3749,6 +3756,9 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
                err = -EINVAL;
        }
 
+skip:
+       down_write(&esw->mode_lock);
+       esw->eswitch_operation_in_progress = false;
 unlock:
        mlx5_esw_unlock(esw);
 enable_lag:
@@ -3759,16 +3769,12 @@ enable_lag:
 int mlx5_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode)
 {
        struct mlx5_eswitch *esw;
-       int err;
 
        esw = mlx5_devlink_eswitch_get(devlink);
        if (IS_ERR(esw))
                return PTR_ERR(esw);
 
-       down_read(&esw->mode_lock);
-       err = esw_mode_to_devlink(esw->mode, mode);
-       up_read(&esw->mode_lock);
-       return err;
+       return esw_mode_to_devlink(esw->mode, mode);
 }
 
 static int mlx5_esw_vports_inline_set(struct mlx5_eswitch *esw, u8 mlx5_mode,
@@ -3862,11 +3868,15 @@ int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode,
        if (err)
                goto out;
 
+       esw->eswitch_operation_in_progress = true;
+       up_write(&esw->mode_lock);
+
        err = mlx5_esw_vports_inline_set(esw, mlx5_mode, extack);
-       if (err)
-               goto out;
+       if (!err)
+               esw->offloads.inline_mode = mlx5_mode;
 
-       esw->offloads.inline_mode = mlx5_mode;
+       down_write(&esw->mode_lock);
+       esw->eswitch_operation_in_progress = false;
        up_write(&esw->mode_lock);
        return 0;
 
@@ -3878,16 +3888,12 @@ out:
 int mlx5_devlink_eswitch_inline_mode_get(struct devlink *devlink, u8 *mode)
 {
        struct mlx5_eswitch *esw;
-       int err;
 
        esw = mlx5_devlink_eswitch_get(devlink);
        if (IS_ERR(esw))
                return PTR_ERR(esw);
 
-       down_read(&esw->mode_lock);
-       err = esw_inline_mode_to_devlink(esw->offloads.inline_mode, mode);
-       up_read(&esw->mode_lock);
-       return err;
+       return esw_inline_mode_to_devlink(esw->offloads.inline_mode, mode);
 }
 
 bool mlx5_eswitch_block_encap(struct mlx5_core_dev *dev)
@@ -3969,6 +3975,9 @@ int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink,
                goto unlock;
        }
 
+       esw->eswitch_operation_in_progress = true;
+       up_write(&esw->mode_lock);
+
        esw_destroy_offloads_fdb_tables(esw);
 
        esw->offloads.encap = encap;
@@ -3982,6 +3991,9 @@ int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink,
                (void)esw_create_offloads_fdb_tables(esw);
        }
 
+       down_write(&esw->mode_lock);
+       esw->eswitch_operation_in_progress = false;
+
 unlock:
        up_write(&esw->mode_lock);
        return err;
@@ -3996,9 +4008,7 @@ int mlx5_devlink_eswitch_encap_mode_get(struct devlink *devlink,
        if (IS_ERR(esw))
                return PTR_ERR(esw);
 
-       down_read(&esw->mode_lock);
        *encap = esw->offloads.encap;
-       up_read(&esw->mode_lock);
        return 0;
 }
 
index b568988e92e3e95985683f79b8c5fdf601d13d5a..c4e19d627da2148bd1fab3b6f388358320ecb9d0 100644 (file)
@@ -325,6 +325,29 @@ static void mlx5_fw_live_patch_event(struct work_struct *work)
                mlx5_core_err(dev, "Failed to reload FW tracer\n");
 }
 
+#if IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE)
+static int mlx5_check_hotplug_interrupt(struct mlx5_core_dev *dev)
+{
+       struct pci_dev *bridge = dev->pdev->bus->self;
+       u16 reg16;
+       int err;
+
+       if (!bridge)
+               return -EOPNOTSUPP;
+
+       err = pcie_capability_read_word(bridge, PCI_EXP_SLTCTL, &reg16);
+       if (err)
+               return err;
+
+       if ((reg16 & PCI_EXP_SLTCTL_HPIE) && (reg16 & PCI_EXP_SLTCTL_DLLSCE)) {
+               mlx5_core_warn(dev, "FW reset is not supported as HotPlug is enabled\n");
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+#endif
+
 static int mlx5_check_dev_ids(struct mlx5_core_dev *dev, u16 dev_id)
 {
        struct pci_bus *bridge_bus = dev->pdev->bus;
@@ -357,6 +380,12 @@ static bool mlx5_is_reset_now_capable(struct mlx5_core_dev *dev)
                return false;
        }
 
+#if IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE)
+       err = mlx5_check_hotplug_interrupt(dev);
+       if (err)
+               return false;
+#endif
+
        err = pci_read_config_word(dev->pdev, PCI_DEVICE_ID, &dev_id);
        if (err)
                return false;
index 65e20693c549e14753cbfb8509e1037723e6b7c1..33f4f58ee51c687d45a437b09275ead900336800 100644 (file)
@@ -933,6 +933,7 @@ static void qed_ilt_shadow_free(struct qed_hwfn *p_hwfn)
                p_dma->virt_addr = NULL;
        }
        kfree(p_mngr->ilt_shadow);
+       p_mngr->ilt_shadow = NULL;
 }
 
 static int qed_ilt_blk_alloc(struct qed_hwfn *p_hwfn,
index 6f2fa2a42770aa2743f12cae7bae30408f731088..1822f2ad8f0ddf788b5b5a52568a74e719c2eac8 100644 (file)
@@ -30,6 +30,8 @@
 
 #define QCASPI_MAX_REGS 0x20
 
+#define QCASPI_RX_MAX_FRAMES 4
+
 static const u16 qcaspi_spi_regs[] = {
        SPI_REG_BFR_SIZE,
        SPI_REG_WRBUF_SPC_AVA,
@@ -252,9 +254,9 @@ qcaspi_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring,
 {
        struct qcaspi *qca = netdev_priv(dev);
 
-       ring->rx_max_pending = 4;
+       ring->rx_max_pending = QCASPI_RX_MAX_FRAMES;
        ring->tx_max_pending = TX_RING_MAX_LEN;
-       ring->rx_pending = 4;
+       ring->rx_pending = QCASPI_RX_MAX_FRAMES;
        ring->tx_pending = qca->txr.count;
 }
 
@@ -263,22 +265,21 @@ qcaspi_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ring,
                     struct kernel_ethtool_ringparam *kernel_ring,
                     struct netlink_ext_ack *extack)
 {
-       const struct net_device_ops *ops = dev->netdev_ops;
        struct qcaspi *qca = netdev_priv(dev);
 
-       if ((ring->rx_pending) ||
+       if (ring->rx_pending != QCASPI_RX_MAX_FRAMES ||
            (ring->rx_mini_pending) ||
            (ring->rx_jumbo_pending))
                return -EINVAL;
 
-       if (netif_running(dev))
-               ops->ndo_stop(dev);
+       if (qca->spi_thread)
+               kthread_park(qca->spi_thread);
 
        qca->txr.count = max_t(u32, ring->tx_pending, TX_RING_MIN_LEN);
        qca->txr.count = min_t(u16, qca->txr.count, TX_RING_MAX_LEN);
 
-       if (netif_running(dev))
-               ops->ndo_open(dev);
+       if (qca->spi_thread)
+               kthread_unpark(qca->spi_thread);
 
        return 0;
 }
index bec723028e96c9c7f9ec686e497d2eea91a7d8c6..5f3c11fb3fa27905521157f8ee582edc39b943e4 100644 (file)
@@ -580,6 +580,18 @@ qcaspi_spi_thread(void *data)
        netdev_info(qca->net_dev, "SPI thread created\n");
        while (!kthread_should_stop()) {
                set_current_state(TASK_INTERRUPTIBLE);
+               if (kthread_should_park()) {
+                       netif_tx_disable(qca->net_dev);
+                       netif_carrier_off(qca->net_dev);
+                       qcaspi_flush_tx_ring(qca);
+                       kthread_parkme();
+                       if (qca->sync == QCASPI_SYNC_READY) {
+                               netif_carrier_on(qca->net_dev);
+                               netif_wake_queue(qca->net_dev);
+                       }
+                       continue;
+               }
+
                if ((qca->intr_req == qca->intr_svc) &&
                    !qca->txr.skb[qca->txr.head])
                        schedule();
@@ -608,11 +620,17 @@ qcaspi_spi_thread(void *data)
                        if (intr_cause & SPI_INT_CPU_ON) {
                                qcaspi_qca7k_sync(qca, QCASPI_EVENT_CPUON);
 
+                               /* Frame decoding in progress */
+                               if (qca->frm_handle.state != qca->frm_handle.init)
+                                       qca->net_dev->stats.rx_dropped++;
+
+                               qcafrm_fsm_init_spi(&qca->frm_handle);
+                               qca->stats.device_reset++;
+
                                /* not synced. */
                                if (qca->sync != QCASPI_SYNC_READY)
                                        continue;
 
-                               qca->stats.device_reset++;
                                netif_wake_queue(qca->net_dev);
                                netif_carrier_on(qca->net_dev);
                        }
index 2cd6fce5c9934c7a9fe2cc7b1396bd3b252d0a0d..9e40c28d453ab190d2c3150df27baa52d745a98d 100644 (file)
@@ -59,26 +59,19 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
                return -ENODEV;
        }
 
-       if (!of_device_is_compatible(np, "loongson, pci-gmac")) {
-               pr_info("dwmac_loongson_pci: Incompatible OF node\n");
-               return -ENODEV;
-       }
-
        plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
        if (!plat)
                return -ENOMEM;
 
+       plat->mdio_bus_data = devm_kzalloc(&pdev->dev,
+                                          sizeof(*plat->mdio_bus_data),
+                                          GFP_KERNEL);
+       if (!plat->mdio_bus_data)
+               return -ENOMEM;
+
        plat->mdio_node = of_get_child_by_name(np, "mdio");
        if (plat->mdio_node) {
                dev_info(&pdev->dev, "Found MDIO subnode\n");
-
-               plat->mdio_bus_data = devm_kzalloc(&pdev->dev,
-                                                  sizeof(*plat->mdio_bus_data),
-                                                  GFP_KERNEL);
-               if (!plat->mdio_bus_data) {
-                       ret = -ENOMEM;
-                       goto err_put_node;
-               }
                plat->mdio_bus_data->needs_reset = true;
        }
 
index d3bf42d0fceb69bd084b9d05db0f7dacdb8cff18..31631e3f89d0a499f04b26ed79b159e99cea4879 100644 (file)
@@ -34,6 +34,7 @@
 #define RGMII_CONFIG_LOOPBACK_EN               BIT(2)
 #define RGMII_CONFIG_PROG_SWAP                 BIT(1)
 #define RGMII_CONFIG_DDR_MODE                  BIT(0)
+#define RGMII_CONFIG_SGMII_CLK_DVDR            GENMASK(18, 10)
 
 /* SDCC_HC_REG_DLL_CONFIG fields */
 #define SDCC_DLL_CONFIG_DLL_RST                        BIT(30)
@@ -78,6 +79,8 @@
 #define ETHQOS_MAC_CTRL_SPEED_MODE             BIT(14)
 #define ETHQOS_MAC_CTRL_PORT_SEL               BIT(15)
 
+#define SGMII_10M_RX_CLK_DVDR                  0x31
+
 struct ethqos_emac_por {
        unsigned int offset;
        unsigned int value;
@@ -598,6 +601,9 @@ static int ethqos_configure_rgmii(struct qcom_ethqos *ethqos)
        return 0;
 }
 
+/* On interface toggle MAC registers gets reset.
+ * Configure MAC block for SGMII on ethernet phy link up
+ */
 static int ethqos_configure_sgmii(struct qcom_ethqos *ethqos)
 {
        int val;
@@ -617,6 +623,10 @@ static int ethqos_configure_sgmii(struct qcom_ethqos *ethqos)
        case SPEED_10:
                val |= ETHQOS_MAC_CTRL_PORT_SEL;
                val &= ~ETHQOS_MAC_CTRL_SPEED_MODE;
+               rgmii_updatel(ethqos, RGMII_CONFIG_SGMII_CLK_DVDR,
+                             FIELD_PREP(RGMII_CONFIG_SGMII_CLK_DVDR,
+                                        SGMII_10M_RX_CLK_DVDR),
+                             RGMII_IO_MACRO_CONFIG);
                break;
        }
 
index fa9e7e7040b9457c6f2786de5555554b36f12529..0542cfd1817e62a50adb9a739625ac9c04d40b33 100644 (file)
@@ -591,7 +591,11 @@ int stmmac_mdio_register(struct net_device *ndev)
        new_bus->parent = priv->device;
 
        err = of_mdiobus_register(new_bus, mdio_node);
-       if (err != 0) {
+       if (err == -ENODEV) {
+               err = 0;
+               dev_info(dev, "MDIO bus is disabled\n");
+               goto bus_register_fail;
+       } else if (err) {
                dev_err_probe(dev, err, "Cannot register the MDIO bus\n");
                goto bus_register_fail;
        }
index 508d9a392ab182c4809019e73fd2b658fd1d66de..f575f225d4178950abdc73584e6266c2421a92f6 100644 (file)
@@ -281,8 +281,10 @@ static int __team_options_register(struct team *team,
        return 0;
 
 inst_rollback:
-       for (i--; i >= 0; i--)
+       for (i--; i >= 0; i--) {
                __team_option_inst_del_option(team, dst_opts[i]);
+               list_del(&dst_opts[i]->list);
+       }
 
        i = option_count;
 alloc_rollback:
index 6902e97719d1366d754c20f3d28a0482db48500e..11c80555d97543990fdd17cf9326cf58826ab457 100644 (file)
@@ -968,9 +968,12 @@ static int qcom_pcie_post_init_2_7_0(struct qcom_pcie *pcie)
 
 static int qcom_pcie_enable_aspm(struct pci_dev *pdev, void *userdata)
 {
-       /* Downstream devices need to be in D0 state before enabling PCI PM substates */
+       /*
+        * Downstream devices need to be in D0 state before enabling PCI PM
+        * substates.
+        */
        pci_set_power_state(pdev, PCI_D0);
-       pci_enable_link_state(pdev, PCIE_LINK_STATE_ALL);
+       pci_enable_link_state_locked(pdev, PCIE_LINK_STATE_ALL);
 
        return 0;
 }
index d45e7b8dc530d6162730ee677371992c36881501..8b34ccff073a99ef5f5f574eec4467d986b6548d 100644 (file)
@@ -80,13 +80,49 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
                        DEV_LS7A_LPC, system_bus_quirk);
 
+/*
+ * Some Loongson PCIe ports have hardware limitations on their Maximum Read
+ * Request Size. They can't handle anything larger than this.  Sane
+ * firmware will set proper MRRS at boot, so we only need no_inc_mrrs for
+ * bridges. However, some MIPS Loongson firmware doesn't set MRRS properly,
+ * so we have to enforce maximum safe MRRS, which is 256 bytes.
+ */
+#ifdef CONFIG_MIPS
+static void loongson_set_min_mrrs_quirk(struct pci_dev *pdev)
+{
+       struct pci_bus *bus = pdev->bus;
+       struct pci_dev *bridge;
+       static const struct pci_device_id bridge_devids[] = {
+               { PCI_VDEVICE(LOONGSON, DEV_LS2K_PCIE_PORT0) },
+               { PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT0) },
+               { PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT1) },
+               { PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT2) },
+               { PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT3) },
+               { PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT4) },
+               { PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT5) },
+               { PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT6) },
+               { 0, },
+       };
+
+       /* look for the matching bridge */
+       while (!pci_is_root_bus(bus)) {
+               bridge = bus->self;
+               bus = bus->parent;
+
+               if (pci_match_id(bridge_devids, bridge)) {
+                       if (pcie_get_readrq(pdev) > 256) {
+                               pci_info(pdev, "limiting MRRS to 256\n");
+                               pcie_set_readrq(pdev, 256);
+                       }
+                       break;
+               }
+       }
+}
+DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, loongson_set_min_mrrs_quirk);
+#endif
+
 static void loongson_mrrs_quirk(struct pci_dev *pdev)
 {
-       /*
-        * Some Loongson PCIe ports have h/w limitations of maximum read
-        * request size. They can't handle anything larger than this. So
-        * force this limit on any devices attached under these ports.
-        */
        struct pci_host_bridge *bridge = pci_find_host_bridge(pdev->bus);
 
        bridge->no_inc_mrrs = 1;
index 94ba61fe1c44110b95c8b70543c0eda0ce553031..0452cbc362eef7b8707337a2d6efde15a01e9dcc 100644 (file)
@@ -751,7 +751,7 @@ static int vmd_pm_enable_quirk(struct pci_dev *pdev, void *userdata)
        if (!(features & VMD_FEAT_BIOS_PM_QUIRK))
                return 0;
 
-       pci_enable_link_state(pdev, PCIE_LINK_STATE_ALL);
+       pci_enable_link_state_locked(pdev, PCIE_LINK_STATE_ALL);
 
        pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_LTR);
        if (!pos)
index 601129772b2d5021afde6eeddc479506852f4902..5b1f271c6034be045aa446f7e5aacb2d6e3f2e2a 100644 (file)
@@ -512,15 +512,12 @@ static void enable_slot(struct acpiphp_slot *slot, bool bridge)
                                if (pass && dev->subordinate) {
                                        check_hotplug_bridge(slot, dev);
                                        pcibios_resource_survey_bus(dev->subordinate);
-                                       if (pci_is_root_bus(bus))
-                                               __pci_bus_size_bridges(dev->subordinate, &add_list);
+                                       __pci_bus_size_bridges(dev->subordinate,
+                                                              &add_list);
                                }
                        }
                }
-               if (pci_is_root_bus(bus))
-                       __pci_bus_assign_resources(bus, &add_list, NULL);
-               else
-                       pci_assign_unassigned_bridge_resources(bus->self);
+               __pci_bus_assign_resources(bus, &add_list, NULL);
        }
 
        acpiphp_sanitize_bus(bus);
index 50b04ae5c394e3691d3b100eeed3918cd7be9f4c..5dab531c8654d68eaaf1e0db404e543f0c64497e 100644 (file)
@@ -1041,7 +1041,7 @@ static struct pcie_link_state *pcie_aspm_get_link(struct pci_dev *pdev)
        return bridge->link_state;
 }
 
-static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
+static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool locked)
 {
        struct pcie_link_state *link = pcie_aspm_get_link(pdev);
 
@@ -1060,7 +1060,7 @@ static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
                return -EPERM;
        }
 
-       if (sem)
+       if (!locked)
                down_read(&pci_bus_sem);
        mutex_lock(&aspm_lock);
        if (state & PCIE_LINK_STATE_L0S)
@@ -1082,7 +1082,7 @@ static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
                link->clkpm_disable = 1;
        pcie_set_clkpm(link, policy_to_clkpm_state(link));
        mutex_unlock(&aspm_lock);
-       if (sem)
+       if (!locked)
                up_read(&pci_bus_sem);
 
        return 0;
@@ -1090,7 +1090,9 @@ static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
 
 int pci_disable_link_state_locked(struct pci_dev *pdev, int state)
 {
-       return __pci_disable_link_state(pdev, state, false);
+       lockdep_assert_held_read(&pci_bus_sem);
+
+       return __pci_disable_link_state(pdev, state, true);
 }
 EXPORT_SYMBOL(pci_disable_link_state_locked);
 
@@ -1105,21 +1107,11 @@ EXPORT_SYMBOL(pci_disable_link_state_locked);
  */
 int pci_disable_link_state(struct pci_dev *pdev, int state)
 {
-       return __pci_disable_link_state(pdev, state, true);
+       return __pci_disable_link_state(pdev, state, false);
 }
 EXPORT_SYMBOL(pci_disable_link_state);
 
-/**
- * pci_enable_link_state - Clear and set the default device link state so that
- * the link may be allowed to enter the specified states. Note that if the
- * BIOS didn't grant ASPM control to the OS, this does nothing because we can't
- * touch the LNKCTL register. Also note that this does not enable states
- * disabled by pci_disable_link_state(). Return 0 or a negative errno.
- *
- * @pdev: PCI device
- * @state: Mask of ASPM link states to enable
- */
-int pci_enable_link_state(struct pci_dev *pdev, int state)
+static int __pci_enable_link_state(struct pci_dev *pdev, int state, bool locked)
 {
        struct pcie_link_state *link = pcie_aspm_get_link(pdev);
 
@@ -1136,7 +1128,8 @@ int pci_enable_link_state(struct pci_dev *pdev, int state)
                return -EPERM;
        }
 
-       down_read(&pci_bus_sem);
+       if (!locked)
+               down_read(&pci_bus_sem);
        mutex_lock(&aspm_lock);
        link->aspm_default = 0;
        if (state & PCIE_LINK_STATE_L0S)
@@ -1157,12 +1150,48 @@ int pci_enable_link_state(struct pci_dev *pdev, int state)
        link->clkpm_default = (state & PCIE_LINK_STATE_CLKPM) ? 1 : 0;
        pcie_set_clkpm(link, policy_to_clkpm_state(link));
        mutex_unlock(&aspm_lock);
-       up_read(&pci_bus_sem);
+       if (!locked)
+               up_read(&pci_bus_sem);
 
        return 0;
 }
+
+/**
+ * pci_enable_link_state - Clear and set the default device link state so that
+ * the link may be allowed to enter the specified states. Note that if the
+ * BIOS didn't grant ASPM control to the OS, this does nothing because we can't
+ * touch the LNKCTL register. Also note that this does not enable states
+ * disabled by pci_disable_link_state(). Return 0 or a negative errno.
+ *
+ * @pdev: PCI device
+ * @state: Mask of ASPM link states to enable
+ */
+int pci_enable_link_state(struct pci_dev *pdev, int state)
+{
+       return __pci_enable_link_state(pdev, state, false);
+}
 EXPORT_SYMBOL(pci_enable_link_state);
 
+/**
+ * pci_enable_link_state_locked - Clear and set the default device link state
+ * so that the link may be allowed to enter the specified states. Note that if
+ * the BIOS didn't grant ASPM control to the OS, this does nothing because we
+ * can't touch the LNKCTL register. Also note that this does not enable states
+ * disabled by pci_disable_link_state(). Return 0 or a negative errno.
+ *
+ * @pdev: PCI device
+ * @state: Mask of ASPM link states to enable
+ *
+ * Context: Caller holds pci_bus_sem read lock.
+ */
+int pci_enable_link_state_locked(struct pci_dev *pdev, int state)
+{
+       lockdep_assert_held_read(&pci_bus_sem);
+
+       return __pci_enable_link_state(pdev, state, true);
+}
+EXPORT_SYMBOL(pci_enable_link_state_locked);
+
 static int pcie_aspm_set_policy(const char *val,
                                const struct kernel_param *kp)
 {
index 014010d035882375e9c0381ebce08a80af48ddd5..847b0dc41293d2fa47689bf634b34aef60f6b1ab 100644 (file)
@@ -1816,7 +1816,7 @@ static int arm_cmn_event_add(struct perf_event *event, int flags)
                        idx = 0;
                        while (cmn->dtc[j].counters[idx])
                                if (++idx == CMN_DT_NUM_COUNTERS)
-                                       goto free_dtms;
+                                       return -ENOSPC;
                }
                hw->dtc_idx[j] = idx;
        }
index f021ec5a70e5c31082dfd2ce965b474cd6cb5fcb..553725e1269c9d7ad88f89367dfa1cf367aaf1ce 100644 (file)
@@ -100,7 +100,7 @@ static void mtk_mipi_tx_pll_disable(struct clk_hw *hw)
 static long mtk_mipi_tx_pll_round_rate(struct clk_hw *hw, unsigned long rate,
                                       unsigned long *prate)
 {
-       return clamp_val(rate, 50000000, 1600000000);
+       return clamp_val(rate, 125000000, 1600000000);
 }
 
 static const struct clk_ops mtk_mipi_tx_pll_ops = {
index 0efe74ac9c6afc254dd48d9be37e3fc611d8e20f..637a5fbae6d9a9b2538147072cb159fc0a0960d9 100644 (file)
@@ -275,7 +275,7 @@ static int sp_usb_phy_probe(struct platform_device *pdev)
 
        phy = devm_phy_create(&pdev->dev, NULL, &sp_uphy_ops);
        if (IS_ERR(phy)) {
-               ret = -PTR_ERR(phy);
+               ret = PTR_ERR(phy);
                return ret;
        }
 
index 555b323f45da1ee6dc69ef606860786ac5cc16ae..bc847d3879f79c0684693a475a3c4664f2792794 100644 (file)
@@ -64,6 +64,7 @@ struct phy_gmii_sel_priv {
        u32 num_ports;
        u32 reg_offset;
        u32 qsgmii_main_ports;
+       bool no_offset;
 };
 
 static int phy_gmii_sel_mode(struct phy *phy, enum phy_mode mode, int submode)
@@ -402,7 +403,8 @@ static int phy_gmii_sel_init_ports(struct phy_gmii_sel_priv *priv)
                priv->num_ports = size / sizeof(u32);
                if (!priv->num_ports)
                        return -EINVAL;
-               priv->reg_offset = __be32_to_cpu(*offset);
+               if (!priv->no_offset)
+                       priv->reg_offset = __be32_to_cpu(*offset);
        }
 
        if_phys = devm_kcalloc(dev, priv->num_ports,
@@ -471,6 +473,7 @@ static int phy_gmii_sel_probe(struct platform_device *pdev)
                        dev_err(dev, "Failed to get syscon %d\n", ret);
                        return ret;
                }
+               priv->no_offset = true;
        }
 
        ret = phy_gmii_sel_init_ports(priv);
index 6fa1735ad7a49ad64ecc80033d2b1ec564b1114f..210b0a81b7ecbe3ec28499c3c8dbd52cbbf1c3fb 100644 (file)
@@ -73,10 +73,10 @@ struct intel_vbtn_priv {
        bool wakeup_mode;
 };
 
-static void detect_tablet_mode(struct platform_device *device)
+static void detect_tablet_mode(struct device *dev)
 {
-       struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev);
-       acpi_handle handle = ACPI_HANDLE(&device->dev);
+       struct intel_vbtn_priv *priv = dev_get_drvdata(dev);
+       acpi_handle handle = ACPI_HANDLE(dev);
        unsigned long long vgbs;
        acpi_status status;
        int m;
@@ -89,6 +89,8 @@ static void detect_tablet_mode(struct platform_device *device)
        input_report_switch(priv->switches_dev, SW_TABLET_MODE, m);
        m = (vgbs & VGBS_DOCK_MODE_FLAG) ? 1 : 0;
        input_report_switch(priv->switches_dev, SW_DOCK, m);
+
+       input_sync(priv->switches_dev);
 }
 
 /*
@@ -134,7 +136,7 @@ static int intel_vbtn_input_setup(struct platform_device *device)
        priv->switches_dev->id.bustype = BUS_HOST;
 
        if (priv->has_switches) {
-               detect_tablet_mode(device);
+               detect_tablet_mode(&device->dev);
 
                ret = input_register_device(priv->switches_dev);
                if (ret)
@@ -198,6 +200,9 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
        autorelease = val && (!ke_rel || ke_rel->type == KE_IGNORE);
 
        sparse_keymap_report_event(input_dev, event, val, autorelease);
+
+       /* Some devices need this to report further events */
+       acpi_evaluate_object(handle, "VBDL", NULL, NULL);
 }
 
 /*
@@ -352,7 +357,13 @@ static void intel_vbtn_pm_complete(struct device *dev)
 
 static int intel_vbtn_pm_resume(struct device *dev)
 {
+       struct intel_vbtn_priv *priv = dev_get_drvdata(dev);
+
        intel_vbtn_pm_complete(dev);
+
+       if (priv->has_switches)
+               detect_tablet_mode(dev);
+
        return 0;
 }
 
index 4dfdbfca684172cbd757f9e26829e16e56d58f6d..c66808601fdd0801ec01573a34f1f4ca544a658c 100644 (file)
@@ -590,6 +590,8 @@ static void ips_disable_gpu_turbo(struct ips_driver *ips)
  * @ips: IPS driver struct
  *
  * Check whether the MCP is over its thermal or power budget.
+ *
+ * Returns: %true if the temp or power has exceeded its maximum, else %false
  */
 static bool mcp_exceeded(struct ips_driver *ips)
 {
@@ -619,6 +621,8 @@ static bool mcp_exceeded(struct ips_driver *ips)
  * @cpu: CPU number to check
  *
  * Check a given CPU's average temp or power is over its limit.
+ *
+ * Returns: %true if the temp or power has exceeded its maximum, else %false
  */
 static bool cpu_exceeded(struct ips_driver *ips, int cpu)
 {
@@ -645,6 +649,8 @@ static bool cpu_exceeded(struct ips_driver *ips, int cpu)
  * @ips: IPS driver struct
  *
  * Check the MCH temp & power against their maximums.
+ *
+ * Returns: %true if the temp or power has exceeded its maximum, else %false
  */
 static bool mch_exceeded(struct ips_driver *ips)
 {
@@ -742,12 +748,13 @@ static void update_turbo_limits(struct ips_driver *ips)
  *   - down (at TDP limit)
  *     - adjust both CPU and GPU down if possible
  *
              cpu+ gpu+       cpu+gpu-        cpu-gpu+        cpu-gpu-
-cpu < gpu <    cpu+gpu+        cpu+            gpu+            nothing
-cpu < gpu >=   cpu+gpu-(mcp<)  cpu+gpu-(mcp<)  gpu-            gpu-
-cpu >= gpu <   cpu-gpu+(mcp<)  cpu-            cpu-gpu+(mcp<)  cpu-
-cpu >= gpu >=  cpu-gpu-        cpu-gpu-        cpu-gpu-        cpu-gpu-
*              |cpu+ gpu+      cpu+gpu-        cpu-gpu+        cpu-gpu-
+ * cpu < gpu <  |cpu+gpu+       cpu+            gpu+            nothing
+ * cpu < gpu >= |cpu+gpu-(mcp<) cpu+gpu-(mcp<)  gpu-            gpu-
+ * cpu >= gpu < |cpu-gpu+(mcp<) cpu-            cpu-gpu+(mcp<)  cpu-
+ * cpu >= gpu >=|cpu-gpu-       cpu-gpu-        cpu-gpu-        cpu-gpu-
  *
+ * Returns: %0
  */
 static int ips_adjust(void *data)
 {
@@ -935,11 +942,13 @@ static void monitor_timeout(struct timer_list *t)
  * @data: ips driver structure
  *
  * This is the main function for the IPS driver.  It monitors power and
- * tempurature in the MCP and adjusts CPU and GPU power clams accordingly.
+ * temperature in the MCP and adjusts CPU and GPU power clamps accordingly.
  *
- * We keep a 5s moving average of power consumption and tempurature.  Using
+ * We keep a 5s moving average of power consumption and temperature.  Using
  * that data, along with CPU vs GPU preference, we adjust the power clamps
  * up or down.
+ *
+ * Returns: %0 on success or -errno on error
  */
 static int ips_monitor(void *data)
 {
@@ -1146,6 +1155,8 @@ static void dump_thermal_info(struct ips_driver *ips)
  * Handle temperature limit trigger events, generally by lowering the clamps.
  * If we're at a critical limit, we clamp back to the lowest possible value
  * to prevent emergency shutdown.
+ *
+ * Returns: IRQ_NONE or IRQ_HANDLED
  */
 static irqreturn_t ips_irq_handler(int irq, void *arg)
 {
@@ -1293,9 +1304,12 @@ static void ips_debugfs_init(struct ips_driver *ips)
 
 /**
  * ips_detect_cpu - detect whether CPU supports IPS
+ * @ips: IPS driver struct
  *
  * Walk our list and see if we're on a supported CPU.  If we find one,
  * return the limits for it.
+ *
+ * Returns: the &ips_mcp_limits struct that matches the boot CPU or %NULL
  */
 static struct ips_mcp_limits *ips_detect_cpu(struct ips_driver *ips)
 {
@@ -1352,6 +1366,8 @@ static struct ips_mcp_limits *ips_detect_cpu(struct ips_driver *ips)
  * monitor and control graphics turbo mode.  If we can find them, we can
  * enable graphics turbo, otherwise we must disable it to avoid exceeding
  * thermal and power limits in the MCP.
+ *
+ * Returns: %true if the required symbols are found, else %false
  */
 static bool ips_get_i915_syms(struct ips_driver *ips)
 {
index d0b5fd4137bcdc76826832744cb0737a1cd6b672..3392ae99ac3f476343a479b62516f20133ddfbe3 100644 (file)
@@ -512,10 +512,10 @@ struct tpacpi_quirk {
  * Iterates over a quirks list until one is found that matches the
  * ThinkPad's vendor, BIOS and EC model.
  *
- * Returns 0 if nothing matches, otherwise returns the quirks field of
+ * Returns: %0 if nothing matches, otherwise returns the quirks field of
  * the matching &struct tpacpi_quirk entry.
  *
- * The match criteria is: vendor, ec and bios much match.
+ * The match criteria is: vendor, ec and bios must match.
  */
 static unsigned long __init tpacpi_check_quirks(
                        const struct tpacpi_quirk *qlist,
@@ -9303,7 +9303,7 @@ static struct tpacpi_battery_driver_data battery_info;
 
 /* ACPI helpers/functions/probes */
 
-/**
+/*
  * This evaluates a ACPI method call specific to the battery
  * ACPI extension. The specifics are that an error is marked
  * in the 32rd bit of the response, so we just check that here.
index 82672fcbc2aa27b7c6c252afcb73a0e46d33f57f..8280baa3254b0ba93cb8a80dc14f29fb0af3b375 100644 (file)
@@ -23,8 +23,9 @@
 static void intel_shim_vs_init(struct sdw_intel *sdw)
 {
        void __iomem *shim_vs = sdw->link_res->shim_vs;
-       u16 act = 0;
+       u16 act;
 
+       act = intel_readw(shim_vs, SDW_SHIM2_INTEL_VS_ACTMCTL);
        u16p_replace_bits(&act, 0x1, SDW_SHIM2_INTEL_VS_ACTMCTL_DOAIS);
        act |= SDW_SHIM2_INTEL_VS_ACTMCTL_DACTQE;
        act |=  SDW_SHIM2_INTEL_VS_ACTMCTL_DODS;
index 69719b335bcb1e4c9427d6c5331b5f5597e96725..f048b3d55b2edcb32269369aa7c2b5dda07414ea 100644 (file)
@@ -742,14 +742,15 @@ error_1:
  * sdw_ml_sync_bank_switch: Multilink register bank switch
  *
  * @bus: SDW bus instance
+ * @multi_link: whether this is a multi-link stream with hardware-based sync
  *
  * Caller function should free the buffers on error
  */
-static int sdw_ml_sync_bank_switch(struct sdw_bus *bus)
+static int sdw_ml_sync_bank_switch(struct sdw_bus *bus, bool multi_link)
 {
        unsigned long time_left;
 
-       if (!bus->multi_link)
+       if (!multi_link)
                return 0;
 
        /* Wait for completion of transfer */
@@ -847,7 +848,7 @@ static int do_bank_switch(struct sdw_stream_runtime *stream)
                        bus->bank_switch_timeout = DEFAULT_BANK_SWITCH_TIMEOUT;
 
                /* Check if bank switch was successful */
-               ret = sdw_ml_sync_bank_switch(bus);
+               ret = sdw_ml_sync_bank_switch(bus, multi_link);
                if (ret < 0) {
                        dev_err(bus->dev,
                                "multi link bank switch failed: %d\n", ret);
index ed1644e7683f47445b48d5c78a34b0db30b3dd6d..d642d06a453be75b40663ef2a1594dc696085e77 100644 (file)
@@ -424,7 +424,7 @@ error_kill_call:
        if (call->async) {
                if (cancel_work_sync(&call->async_work))
                        afs_put_call(call);
-               afs_put_call(call);
+               afs_set_call_complete(call, ret, 0);
        }
 
        ac->error = ret;
index 47e7770d05831757d45c4aee9331f52a10c06e76..79495cd7a7949916e53650b0af98388a930ec4cd 100644 (file)
@@ -9,6 +9,7 @@
 #include "debug.h"
 #include "errcode.h"
 #include "error.h"
+#include "journal.h"
 #include "trace.h"
 
 #include <linux/prefetch.h>
@@ -424,14 +425,11 @@ void bch2_fs_btree_cache_exit(struct bch_fs *c)
                BUG_ON(btree_node_read_in_flight(b) ||
                       btree_node_write_in_flight(b));
 
-               if (btree_node_dirty(b))
-                       bch2_btree_complete_write(c, b, btree_current_write(b));
-               clear_btree_node_dirty_acct(c, b);
-
                btree_node_data_free(c, b);
        }
 
-       BUG_ON(atomic_read(&c->btree_cache.dirty));
+       BUG_ON(!bch2_journal_error(&c->journal) &&
+              atomic_read(&c->btree_cache.dirty));
 
        list_splice(&bc->freed_pcpu, &bc->freed_nonpcpu);
 
index 57c20390e10e3fe05394415d8ccabb43201c871b..5a720f0cd5a653eb7053325de344192dc55fba3e 100644 (file)
@@ -1704,8 +1704,8 @@ int bch2_btree_root_read(struct bch_fs *c, enum btree_id id,
        return bch2_trans_run(c, __bch2_btree_root_read(trans, id, k, level));
 }
 
-void bch2_btree_complete_write(struct bch_fs *c, struct btree *b,
-                             struct btree_write *w)
+static void bch2_btree_complete_write(struct bch_fs *c, struct btree *b,
+                                     struct btree_write *w)
 {
        unsigned long old, new, v = READ_ONCE(b->will_make_reachable);
 
index 7e03dd76fb380498a42bcdef91857727403a4d8a..e0d7fa5b1dfb9ab292a010071da9ed0162d303c1 100644 (file)
@@ -134,9 +134,6 @@ void bch2_btree_node_read(struct bch_fs *, struct btree *, bool);
 int bch2_btree_root_read(struct bch_fs *, enum btree_id,
                         const struct bkey_i *, unsigned);
 
-void bch2_btree_complete_write(struct bch_fs *, struct btree *,
-                             struct btree_write *);
-
 bool bch2_btree_post_write_cleanup(struct bch_fs *, struct btree *);
 
 enum btree_write_flags {
index 37fbf22de8fcba305d717f41e4ae8a9461502d53..1b7a5668df7cc4694f73f7c287a1858f3b61074e 100644 (file)
@@ -992,8 +992,6 @@ void bch2_fs_btree_key_cache_exit(struct btree_key_cache *bc)
        list_for_each_entry_safe(ck, n, &items, list) {
                cond_resched();
 
-               bch2_journal_pin_drop(&c->journal, &ck->journal);
-
                list_del(&ck->list);
                kfree(ck->k);
                six_lock_exit(&ck->c.lock);
index 324767c0ddccd7457004a34e8ed6e49da8c54b85..25fdca00bf7bdeed69f9e114332746ccb1de0d23 100644 (file)
@@ -554,6 +554,19 @@ int __must_check bch2_trans_update_seq(struct btree_trans *trans, u64 seq,
                                                 BTREE_UPDATE_PREJOURNAL);
 }
 
+static noinline int bch2_btree_insert_clone_trans(struct btree_trans *trans,
+                                                 enum btree_id btree,
+                                                 struct bkey_i *k)
+{
+       struct bkey_i *n = bch2_trans_kmalloc(trans, bkey_bytes(&k->k));
+       int ret = PTR_ERR_OR_ZERO(n);
+       if (ret)
+               return ret;
+
+       bkey_copy(n, k);
+       return bch2_btree_insert_trans(trans, btree, n, 0);
+}
+
 int __must_check bch2_trans_update_buffered(struct btree_trans *trans,
                                            enum btree_id btree,
                                            struct bkey_i *k)
@@ -564,6 +577,9 @@ int __must_check bch2_trans_update_buffered(struct btree_trans *trans,
        EBUG_ON(trans->nr_wb_updates > trans->wb_updates_size);
        EBUG_ON(k->k.u64s > BTREE_WRITE_BUFERED_U64s_MAX);
 
+       if (unlikely(trans->journal_replay_not_finished))
+               return bch2_btree_insert_clone_trans(trans, btree, k);
+
        trans_for_each_wb_update(trans, i) {
                if (i->btree == btree && bpos_eq(i->k.k.p, k->k.p)) {
                        bkey_copy(&i->k, k);
index 6697417273aa14e7c5de09fbc1622c84eff24949..26be38ab6ecb8fffa179683fae7f2ec76895ec57 100644 (file)
@@ -1056,6 +1056,17 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path,
        flags &= ~BCH_WATERMARK_MASK;
        flags |= watermark;
 
+       if (!(flags & BTREE_INSERT_JOURNAL_RECLAIM) &&
+           watermark < c->journal.watermark) {
+               struct journal_res res = { 0 };
+
+               ret = drop_locks_do(trans,
+                       bch2_journal_res_get(&c->journal, &res, 1,
+                                            watermark|JOURNAL_RES_GET_CHECK));
+               if (ret)
+                       return ERR_PTR(ret);
+       }
+
        while (1) {
                nr_nodes[!!update_level] += 1 + split;
                update_level++;
index 71aa5e59787b8bc6dca216add572553363a44492..2418c528c5333b6e621df17e1579cd2205264e36 100644 (file)
@@ -471,7 +471,7 @@ int bch2_extent_drop_ptrs(struct btree_trans *trans,
         * we aren't using the extent overwrite path to delete, we're
         * just using the normal key deletion path:
         */
-       if (bkey_deleted(&n->k))
+       if (bkey_deleted(&n->k) && !(iter->flags & BTREE_ITER_IS_EXTENTS))
                n->k.size = 0;
 
        return bch2_trans_relock(trans) ?:
@@ -591,7 +591,7 @@ int bch2_data_update_init(struct btree_trans *trans,
                m->data_opts.rewrite_ptrs = 0;
                /* if iter == NULL, it's just a promote */
                if (iter)
-                       ret = bch2_extent_drop_ptrs(trans, iter, k, data_opts);
+                       ret = bch2_extent_drop_ptrs(trans, iter, k, m->data_opts);
                goto done;
        }
 
index 1a0f2d5715692baa2f26a088c61b55742e03fec3..2bfff0da7000b38dc18a20cb8a51290fa0696432 100644 (file)
@@ -485,20 +485,15 @@ retry:
        return ret;
 }
 
-int bch2_empty_dir_trans(struct btree_trans *trans, subvol_inum dir)
+int bch2_empty_dir_snapshot(struct btree_trans *trans, u64 dir, u32 snapshot)
 {
        struct btree_iter iter;
        struct bkey_s_c k;
-       u32 snapshot;
        int ret;
 
-       ret = bch2_subvolume_get_snapshot(trans, dir.subvol, &snapshot);
-       if (ret)
-               return ret;
-
        for_each_btree_key_upto_norestart(trans, iter, BTREE_ID_dirents,
-                          SPOS(dir.inum, 0, snapshot),
-                          POS(dir.inum, U64_MAX), 0, k, ret)
+                          SPOS(dir, 0, snapshot),
+                          POS(dir, U64_MAX), 0, k, ret)
                if (k.k->type == KEY_TYPE_dirent) {
                        ret = -ENOTEMPTY;
                        break;
@@ -508,6 +503,14 @@ int bch2_empty_dir_trans(struct btree_trans *trans, subvol_inum dir)
        return ret;
 }
 
+int bch2_empty_dir_trans(struct btree_trans *trans, subvol_inum dir)
+{
+       u32 snapshot;
+
+       return bch2_subvolume_get_snapshot(trans, dir.subvol, &snapshot) ?:
+               bch2_empty_dir_snapshot(trans, dir.inum, snapshot);
+}
+
 int bch2_readdir(struct bch_fs *c, subvol_inum inum, struct dir_context *ctx)
 {
        struct btree_trans *trans = bch2_trans_get(c);
index cd262bf4d9c5365747562f22536309dc5853d070..1e3431990abd3549efb0d9216679c1c5ec54489a 100644 (file)
@@ -64,6 +64,7 @@ u64 bch2_dirent_lookup(struct bch_fs *, subvol_inum,
                       const struct bch_hash_info *,
                       const struct qstr *, subvol_inum *);
 
+int bch2_empty_dir_snapshot(struct btree_trans *, u64, u32);
 int bch2_empty_dir_trans(struct btree_trans *, subvol_inum);
 int bch2_readdir(struct bch_fs *, subvol_inum, struct dir_context *);
 
index f6c92df552702a7455baa39532bf3c6231ae69b4..9d8afcb5979a12456c032a00faf5514962b9aa05 100644 (file)
@@ -1294,7 +1294,8 @@ unsigned bch2_bkey_ptrs_need_rebalance(struct bch_fs *c, struct bkey_s_c k,
                unsigned i = 0;
 
                bkey_for_each_ptr_decode(k.k, ptrs, p, entry) {
-                       if (p.crc.compression_type == BCH_COMPRESSION_TYPE_incompressible) {
+                       if (p.crc.compression_type == BCH_COMPRESSION_TYPE_incompressible ||
+                           p.ptr.unwritten) {
                                rewrite_ptrs = 0;
                                goto incompressible;
                        }
index 5a39bcb597a33d42826a16a98da394de3fe23660..a70b7a03057d7fdd9921a7e3e4fdddd742866508 100644 (file)
@@ -413,7 +413,7 @@ retry:
 
        if ((arg.flags & BCH_SUBVOL_SNAPSHOT_CREATE) &&
            !arg.src_ptr)
-               snapshot_src.subvol = to_bch_ei(dir)->ei_inode.bi_subvol;
+               snapshot_src.subvol = inode_inum(to_bch_ei(dir)).subvol;
 
        inode = __bch2_create(file_mnt_idmap(filp), to_bch_ei(dir),
                              dst_dentry, arg.mode|S_IFDIR,
index 4d51be813509891458735d494b44e36c043035c6..371565e02ff273cdded33d32ce3f913deccccad6 100644 (file)
@@ -1733,6 +1733,9 @@ static int bch2_unfreeze(struct super_block *sb)
        struct bch_fs *c = sb->s_fs_info;
        int ret;
 
+       if (test_bit(BCH_FS_EMERGENCY_RO, &c->flags))
+               return 0;
+
        down_write(&c->state_lock);
        ret = bch2_fs_read_write(c);
        up_write(&c->state_lock);
index c7849b0753e7a115d563aa4cfdf5bdf33b319ec0..9309cfeecd8d6194bc1819a259dac0882b5ea55e 100644 (file)
@@ -7,6 +7,7 @@
 #include "btree_update.h"
 #include "buckets.h"
 #include "compress.h"
+#include "dirent.h"
 #include "error.h"
 #include "extents.h"
 #include "extent_update.h"
@@ -1093,11 +1094,15 @@ static int may_delete_deleted_inode(struct btree_trans *trans,
        if (ret)
                goto out;
 
-       if (fsck_err_on(S_ISDIR(inode.bi_mode), c,
-                       deleted_inode_is_dir,
-                       "directory %llu:%u in deleted_inodes btree",
-                       pos.offset, pos.snapshot))
-               goto delete;
+       if (S_ISDIR(inode.bi_mode)) {
+               ret = bch2_empty_dir_snapshot(trans, pos.offset, pos.snapshot);
+               if (fsck_err_on(ret == -ENOTEMPTY, c, deleted_inode_is_dir,
+                               "non empty directory %llu:%u in deleted_inodes btree",
+                               pos.offset, pos.snapshot))
+                       goto delete;
+               if (ret)
+                       goto out;
+       }
 
        if (fsck_err_on(!(inode.bi_flags & BCH_INODE_unlinked), c,
                        deleted_inode_not_unlinked,
index 489b34046e7807744bdc7b8462910e5d9d4dc53a..8cf238be6213ece57815b6dce5e46a5c62c2853a 100644 (file)
@@ -249,7 +249,7 @@ static bool journal_entry_want_write(struct journal *j)
        return ret;
 }
 
-static bool journal_entry_close(struct journal *j)
+bool bch2_journal_entry_close(struct journal *j)
 {
        bool ret;
 
@@ -383,7 +383,7 @@ static bool journal_quiesced(struct journal *j)
        bool ret = atomic64_read(&j->seq) == j->seq_ondisk;
 
        if (!ret)
-               journal_entry_close(j);
+               bch2_journal_entry_close(j);
        return ret;
 }
 
@@ -436,7 +436,7 @@ retry:
 
        /*
         * Recheck after taking the lock, so we don't race with another thread
-        * that just did journal_entry_open() and call journal_entry_close()
+        * that just did journal_entry_open() and call bch2_journal_entry_close()
         * unnecessarily
         */
        if (journal_res_get_fast(j, res, flags)) {
@@ -1041,7 +1041,7 @@ void bch2_fs_journal_stop(struct journal *j)
        bch2_journal_reclaim_stop(j);
        bch2_journal_flush_all_pins(j);
 
-       wait_event(j->wait, journal_entry_close(j));
+       wait_event(j->wait, bch2_journal_entry_close(j));
 
        /*
         * Always write a new journal entry, to make sure the clock hands are up
index 4c513fca5ef2d1db0c1bc9673359235912505afc..2f768e11aec9a9aaed7e900a8d87f9fc0546373c 100644 (file)
@@ -266,6 +266,7 @@ static inline union journal_res_state journal_state_buf_put(struct journal *j, u
        return s;
 }
 
+bool bch2_journal_entry_close(struct journal *);
 void bch2_journal_buf_put_final(struct journal *, u64, bool);
 
 static inline void __bch2_journal_buf_put(struct journal *j, unsigned idx, u64 seq)
index 0f17fc5f8d6844f774d71f5a361b55e6acbb866f..5de1b68fb8afc80a61c06263cd8010b93e9efec5 100644 (file)
@@ -1599,6 +1599,7 @@ static CLOSURE_CALLBACK(journal_write_done)
        } while ((v = atomic64_cmpxchg(&j->reservations.counter,
                                       old.v, new.v)) != old.v);
 
+       bch2_journal_reclaim_fast(j);
        bch2_journal_space_available(j);
 
        closure_wake_up(&w->wait);
index e63c6eda86afeb9e9c0920554e9bef953b0a9a26..ec712104addb32c94a1baa350a4bb3a43304c8b2 100644 (file)
@@ -776,6 +776,9 @@ static int journal_flush_done(struct journal *j, u64 seq_to_flush,
                               (1U << JOURNAL_PIN_btree), 0, 0, 0))
                *did_work = true;
 
+       if (seq_to_flush > journal_cur_seq(j))
+               bch2_journal_entry_close(j);
+
        spin_lock(&j->lock);
        /*
         * If journal replay hasn't completed, the unreplayed journal entries
index 770ced1c62850d317eb991c8723401456735cc90..c7d9074c82d97bbd6d0b893c0e3059358b6014e5 100644 (file)
@@ -144,7 +144,7 @@ static int bch2_journal_replay(struct bch_fs *c)
        u64 start_seq   = c->journal_replay_seq_start;
        u64 end_seq     = c->journal_replay_seq_start;
        size_t i;
-       int ret;
+       int ret = 0;
 
        move_gap(keys->d, keys->nr, keys->size, keys->gap, keys->nr);
        keys->gap = keys->nr;
index 6e1bfe9feb59e4abe96e1dc74b30196fa5766f48..37d16e04e6715a56c8fdd328803fcb796c629a43 100644 (file)
@@ -121,6 +121,14 @@ int bch2_trans_mark_reflink_v(struct btree_trans *trans,
 {
        check_indirect_extent_deleting(new, &flags);
 
+       if (old.k->type == KEY_TYPE_reflink_v &&
+           new->k.type == KEY_TYPE_reflink_v &&
+           old.k->u64s == new->k.u64s &&
+           !memcmp(bkey_s_c_to_reflink_v(old).v->start,
+                   bkey_i_to_reflink_v(new)->v.start,
+                   bkey_val_bytes(&new->k) - 8))
+               return 0;
+
        return bch2_trans_mark_extent(trans, btree_id, level, old, new, flags);
 }
 
index ab743115f169e5fc1a7c665148d0c877800fefab..f3cb7115b530bb29dcd35453931a05753438f0fb 100644 (file)
@@ -276,8 +276,8 @@ static int bch2_compression_stats_to_text(struct printbuf *out, struct bch_fs *c
                if (!btree_type_has_ptrs(id))
                        continue;
 
-               for_each_btree_key(trans, iter, id, POS_MIN,
-                                  BTREE_ITER_ALL_SNAPSHOTS, k, ret) {
+               ret = for_each_btree_key2(trans, iter, id, POS_MIN,
+                                         BTREE_ITER_ALL_SNAPSHOTS, k, ({
                        struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
                        const union bch_extent_entry *entry;
                        struct extent_ptr_decoded p;
@@ -309,8 +309,8 @@ static int bch2_compression_stats_to_text(struct printbuf *out, struct bch_fs *c
                                nr_uncompressed_extents++;
                        else if (compressed)
                                nr_compressed_extents++;
-               }
-               bch2_trans_iter_exit(trans, &iter);
+                       0;
+               }));
        }
 
        bch2_trans_put(trans);
index 51453d4928fa400dcf0d08c2e01bb1080b59cb88..2833e8ef4c098f680a4883d41a1e925dc477bc2f 100644 (file)
@@ -199,7 +199,7 @@ void btrfs_free_reserved_data_space(struct btrfs_inode *inode,
        start = round_down(start, fs_info->sectorsize);
 
        btrfs_free_reserved_data_space_noquota(fs_info, len);
-       btrfs_qgroup_free_data(inode, reserved, start, len);
+       btrfs_qgroup_free_data(inode, reserved, start, len, NULL);
 }
 
 /*
index bbcc3df776461f5b6952422c246e65bbcbc1ccc6..62cb97f7c94fa26e0969707f595e07ffa9bb3937 100644 (file)
@@ -4799,6 +4799,32 @@ void btrfs_cleanup_dirty_bgs(struct btrfs_transaction *cur_trans,
        }
 }
 
+static void btrfs_free_all_qgroup_pertrans(struct btrfs_fs_info *fs_info)
+{
+       struct btrfs_root *gang[8];
+       int i;
+       int ret;
+
+       spin_lock(&fs_info->fs_roots_radix_lock);
+       while (1) {
+               ret = radix_tree_gang_lookup_tag(&fs_info->fs_roots_radix,
+                                                (void **)gang, 0,
+                                                ARRAY_SIZE(gang),
+                                                BTRFS_ROOT_TRANS_TAG);
+               if (ret == 0)
+                       break;
+               for (i = 0; i < ret; i++) {
+                       struct btrfs_root *root = gang[i];
+
+                       btrfs_qgroup_free_meta_all_pertrans(root);
+                       radix_tree_tag_clear(&fs_info->fs_roots_radix,
+                                       (unsigned long)root->root_key.objectid,
+                                       BTRFS_ROOT_TRANS_TAG);
+               }
+       }
+       spin_unlock(&fs_info->fs_roots_radix_lock);
+}
+
 void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans,
                                   struct btrfs_fs_info *fs_info)
 {
@@ -4827,6 +4853,8 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans,
                                     EXTENT_DIRTY);
        btrfs_destroy_pinned_extent(fs_info, &cur_trans->pinned_extents);
 
+       btrfs_free_all_qgroup_pertrans(fs_info);
+
        cur_trans->state =TRANS_STATE_COMPLETED;
        wake_up(&cur_trans->commit_wait);
 }
index 0455935ff558804b3e47291821a566e348d8a6d4..01423670bc8a2b5aba840a98687d6cec84a166b9 100644 (file)
@@ -1547,6 +1547,23 @@ out:
        return ret;
 }
 
+static void free_head_ref_squota_rsv(struct btrfs_fs_info *fs_info,
+                                    struct btrfs_delayed_ref_head *href)
+{
+       u64 root = href->owning_root;
+
+       /*
+        * Don't check must_insert_reserved, as this is called from contexts
+        * where it has already been unset.
+        */
+       if (btrfs_qgroup_mode(fs_info) != BTRFS_QGROUP_MODE_SIMPLE ||
+           !href->is_data || !is_fstree(root))
+               return;
+
+       btrfs_qgroup_free_refroot(fs_info, root, href->reserved_bytes,
+                                 BTRFS_QGROUP_RSV_DATA);
+}
+
 static int run_delayed_data_ref(struct btrfs_trans_handle *trans,
                                struct btrfs_delayed_ref_head *href,
                                struct btrfs_delayed_ref_node *node,
@@ -1569,7 +1586,6 @@ static int run_delayed_data_ref(struct btrfs_trans_handle *trans,
                struct btrfs_squota_delta delta = {
                        .root = href->owning_root,
                        .num_bytes = node->num_bytes,
-                       .rsv_bytes = href->reserved_bytes,
                        .is_data = true,
                        .is_inc = true,
                        .generation = trans->transid,
@@ -1586,11 +1602,9 @@ static int run_delayed_data_ref(struct btrfs_trans_handle *trans,
                                                 flags, ref->objectid,
                                                 ref->offset, &key,
                                                 node->ref_mod, href->owning_root);
+               free_head_ref_squota_rsv(trans->fs_info, href);
                if (!ret)
                        ret = btrfs_record_squota_delta(trans->fs_info, &delta);
-               else
-                       btrfs_qgroup_free_refroot(trans->fs_info, delta.root,
-                                                 delta.rsv_bytes, BTRFS_QGROUP_RSV_DATA);
        } else if (node->action == BTRFS_ADD_DELAYED_REF) {
                ret = __btrfs_inc_extent_ref(trans, node, parent, ref->root,
                                             ref->objectid, ref->offset,
@@ -1742,7 +1756,6 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans,
                struct btrfs_squota_delta delta = {
                        .root = href->owning_root,
                        .num_bytes = fs_info->nodesize,
-                       .rsv_bytes = 0,
                        .is_data = false,
                        .is_inc = true,
                        .generation = trans->transid,
@@ -1774,8 +1787,10 @@ static int run_one_delayed_ref(struct btrfs_trans_handle *trans,
        int ret = 0;
 
        if (TRANS_ABORTED(trans)) {
-               if (insert_reserved)
+               if (insert_reserved) {
                        btrfs_pin_extent(trans, node->bytenr, node->num_bytes, 1);
+                       free_head_ref_squota_rsv(trans->fs_info, href);
+               }
                return 0;
        }
 
@@ -1871,6 +1886,8 @@ u64 btrfs_cleanup_ref_head_accounting(struct btrfs_fs_info *fs_info,
                                  struct btrfs_delayed_ref_root *delayed_refs,
                                  struct btrfs_delayed_ref_head *head)
 {
+       u64 ret = 0;
+
        /*
         * We had csum deletions accounted for in our delayed refs rsv, we need
         * to drop the csum leaves for this update from our delayed_refs_rsv.
@@ -1885,14 +1902,13 @@ u64 btrfs_cleanup_ref_head_accounting(struct btrfs_fs_info *fs_info,
 
                btrfs_delayed_refs_rsv_release(fs_info, 0, nr_csums);
 
-               return btrfs_calc_delayed_ref_csum_bytes(fs_info, nr_csums);
+               ret = btrfs_calc_delayed_ref_csum_bytes(fs_info, nr_csums);
        }
-       if (btrfs_qgroup_mode(fs_info) == BTRFS_QGROUP_MODE_SIMPLE &&
-           head->must_insert_reserved && head->is_data)
-               btrfs_qgroup_free_refroot(fs_info, head->owning_root,
-                                         head->reserved_bytes, BTRFS_QGROUP_RSV_DATA);
+       /* must_insert_reserved can be set only if we didn't run the head ref. */
+       if (head->must_insert_reserved)
+               free_head_ref_squota_rsv(fs_info, head);
 
-       return 0;
+       return ret;
 }
 
 static int cleanup_ref_head(struct btrfs_trans_handle *trans,
@@ -2033,6 +2049,12 @@ static int btrfs_run_delayed_refs_for_head(struct btrfs_trans_handle *trans,
                 * spin lock.
                 */
                must_insert_reserved = locked_ref->must_insert_reserved;
+               /*
+                * Unsetting this on the head ref relinquishes ownership of
+                * the rsv_bytes, so it is critical that every possible code
+                * path from here forward frees all reserves including qgroup
+                * reserve.
+                */
                locked_ref->must_insert_reserved = false;
 
                extent_op = locked_ref->extent_op;
@@ -3292,7 +3314,6 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
                struct btrfs_squota_delta delta = {
                        .root = delayed_ref_root,
                        .num_bytes = num_bytes,
-                       .rsv_bytes = 0,
                        .is_data = is_data,
                        .is_inc = false,
                        .generation = btrfs_extent_generation(leaf, ei),
@@ -4937,7 +4958,6 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans,
                .root = root_objectid,
                .num_bytes = ins->offset,
                .generation = trans->transid,
-               .rsv_bytes = 0,
                .is_data = true,
                .is_inc = true,
        };
index e6230a6ffa9859fd26046b12e9cc295e5cf78d35..8f724c54fc8e9c8a38f720df77526f7b722b6f44 100644 (file)
@@ -2302,7 +2302,8 @@ static int try_release_extent_state(struct extent_io_tree *tree,
                ret = 0;
        } else {
                u32 clear_bits = ~(EXTENT_LOCKED | EXTENT_NODATASUM |
-                                  EXTENT_DELALLOC_NEW | EXTENT_CTLBITS);
+                                  EXTENT_DELALLOC_NEW | EXTENT_CTLBITS |
+                                  EXTENT_QGROUP_RESERVED);
 
                /*
                 * At this point we can safely clear everything except the
index f47731c45bb50497c6a3e5059eed67526bf95be2..32611a4edd6b2388af70203ab33ec41f2f7f60c3 100644 (file)
@@ -3192,7 +3192,7 @@ static long btrfs_fallocate(struct file *file, int mode,
                        qgroup_reserved -= range->len;
                } else if (qgroup_reserved > 0) {
                        btrfs_qgroup_free_data(BTRFS_I(inode), data_reserved,
-                                              range->start, range->len);
+                                              range->start, range->len, NULL);
                        qgroup_reserved -= range->len;
                }
                list_del(&range->list);
index 9f5a9894f88f49156e9ddb7c4baac8ef1be252df..fb3c3f43c3fa401da09ad815ae815e47e92087e3 100644 (file)
@@ -688,7 +688,7 @@ out:
         * And at reserve time, it's always aligned to page size, so
         * just free one page here.
         */
-       btrfs_qgroup_free_data(inode, NULL, 0, PAGE_SIZE);
+       btrfs_qgroup_free_data(inode, NULL, 0, PAGE_SIZE, NULL);
        btrfs_free_path(path);
        btrfs_end_transaction(trans);
        return ret;
@@ -5132,7 +5132,7 @@ static void evict_inode_truncate_pages(struct inode *inode)
                 */
                if (state_flags & EXTENT_DELALLOC)
                        btrfs_qgroup_free_data(BTRFS_I(inode), NULL, start,
-                                              end - start + 1);
+                                              end - start + 1, NULL);
 
                clear_extent_bit(io_tree, start, end,
                                 EXTENT_CLEAR_ALL_BITS | EXTENT_DO_ACCOUNTING,
@@ -8059,7 +8059,7 @@ next:
                 *    reserved data space.
                 *    Since the IO will never happen for this page.
                 */
-               btrfs_qgroup_free_data(inode, NULL, cur, range_end + 1 - cur);
+               btrfs_qgroup_free_data(inode, NULL, cur, range_end + 1 - cur, NULL);
                if (!inode_evicting) {
                        clear_extent_bit(tree, cur, range_end, EXTENT_LOCKED |
                                 EXTENT_DELALLOC | EXTENT_UPTODATE |
@@ -9491,7 +9491,7 @@ static struct btrfs_trans_handle *insert_prealloc_file_extent(
        struct btrfs_path *path;
        u64 start = ins->objectid;
        u64 len = ins->offset;
-       int qgroup_released;
+       u64 qgroup_released = 0;
        int ret;
 
        memset(&stack_fi, 0, sizeof(stack_fi));
@@ -9504,9 +9504,9 @@ static struct btrfs_trans_handle *insert_prealloc_file_extent(
        btrfs_set_stack_file_extent_compression(&stack_fi, BTRFS_COMPRESS_NONE);
        /* Encryption and other encoding is reserved and all 0 */
 
-       qgroup_released = btrfs_qgroup_release_data(inode, file_offset, len);
-       if (qgroup_released < 0)
-               return ERR_PTR(qgroup_released);
+       ret = btrfs_qgroup_release_data(inode, file_offset, len, &qgroup_released);
+       if (ret < 0)
+               return ERR_PTR(ret);
 
        if (trans) {
                ret = insert_reserved_file_extent(trans, inode,
@@ -10401,7 +10401,7 @@ out_delalloc_release:
        btrfs_delalloc_release_metadata(inode, disk_num_bytes, ret < 0);
 out_qgroup_free_data:
        if (ret < 0)
-               btrfs_qgroup_free_data(inode, data_reserved, start, num_bytes);
+               btrfs_qgroup_free_data(inode, data_reserved, start, num_bytes, NULL);
 out_free_data_space:
        /*
         * If btrfs_reserve_extent() succeeded, then we already decremented
index 4e50b62db2a8feba629ee2ceb2040e28b4c2485b..a1743904202b78a7c341aabf2c6af3756d15b2aa 100644 (file)
@@ -1290,6 +1290,15 @@ static noinline int __btrfs_ioctl_snap_create(struct file *file,
                         * are limited to own subvolumes only
                         */
                        ret = -EPERM;
+               } else if (btrfs_ino(BTRFS_I(src_inode)) != BTRFS_FIRST_FREE_OBJECTID) {
+                       /*
+                        * Snapshots must be made with the src_inode referring
+                        * to the subvolume inode, otherwise the permission
+                        * checking above is useless because we may have
+                        * permission on a lower directory but not the subvol
+                        * itself.
+                        */
+                       ret = -EINVAL;
                } else {
                        ret = btrfs_mksnapshot(&file->f_path, idmap,
                                               name, namelen,
index 574e8a55e24a2b08e6b3a411330a284854f3e5ab..a82e1417c4d278ffccb8939d2f56e79caa14f179 100644 (file)
@@ -152,11 +152,12 @@ static struct btrfs_ordered_extent *alloc_ordered_extent(
 {
        struct btrfs_ordered_extent *entry;
        int ret;
+       u64 qgroup_rsv = 0;
 
        if (flags &
            ((1 << BTRFS_ORDERED_NOCOW) | (1 << BTRFS_ORDERED_PREALLOC))) {
                /* For nocow write, we can release the qgroup rsv right now */
-               ret = btrfs_qgroup_free_data(inode, NULL, file_offset, num_bytes);
+               ret = btrfs_qgroup_free_data(inode, NULL, file_offset, num_bytes, &qgroup_rsv);
                if (ret < 0)
                        return ERR_PTR(ret);
        } else {
@@ -164,7 +165,7 @@ static struct btrfs_ordered_extent *alloc_ordered_extent(
                 * The ordered extent has reserved qgroup space, release now
                 * and pass the reserved number for qgroup_record to free.
                 */
-               ret = btrfs_qgroup_release_data(inode, file_offset, num_bytes);
+               ret = btrfs_qgroup_release_data(inode, file_offset, num_bytes, &qgroup_rsv);
                if (ret < 0)
                        return ERR_PTR(ret);
        }
@@ -182,7 +183,7 @@ static struct btrfs_ordered_extent *alloc_ordered_extent(
        entry->inode = igrab(&inode->vfs_inode);
        entry->compress_type = compress_type;
        entry->truncated_len = (u64)-1;
-       entry->qgroup_rsv = ret;
+       entry->qgroup_rsv = qgroup_rsv;
        entry->flags = flags;
        refcount_set(&entry->refs, 1);
        init_waitqueue_head(&entry->wait);
@@ -599,7 +600,9 @@ void btrfs_remove_ordered_extent(struct btrfs_inode *btrfs_inode,
                        release = entry->disk_num_bytes;
                else
                        release = entry->num_bytes;
-               btrfs_delalloc_release_metadata(btrfs_inode, release, false);
+               btrfs_delalloc_release_metadata(btrfs_inode, release,
+                                               test_bit(BTRFS_ORDERED_IOERR,
+                                                        &entry->flags));
        }
 
        percpu_counter_add_batch(&fs_info->ordered_bytes, -entry->num_bytes,
index ce446d9d7f23da3f44cb9c7100c8e0d7b3866684..e46774e8f49fd6609afa61914adb82dd53dac83d 100644 (file)
@@ -4057,13 +4057,14 @@ int btrfs_qgroup_reserve_data(struct btrfs_inode *inode,
 
 /* Free ranges specified by @reserved, normally in error path */
 static int qgroup_free_reserved_data(struct btrfs_inode *inode,
-                       struct extent_changeset *reserved, u64 start, u64 len)
+                                    struct extent_changeset *reserved,
+                                    u64 start, u64 len, u64 *freed_ret)
 {
        struct btrfs_root *root = inode->root;
        struct ulist_node *unode;
        struct ulist_iterator uiter;
        struct extent_changeset changeset;
-       int freed = 0;
+       u64 freed = 0;
        int ret;
 
        extent_changeset_init(&changeset);
@@ -4104,7 +4105,9 @@ static int qgroup_free_reserved_data(struct btrfs_inode *inode,
        }
        btrfs_qgroup_free_refroot(root->fs_info, root->root_key.objectid, freed,
                                  BTRFS_QGROUP_RSV_DATA);
-       ret = freed;
+       if (freed_ret)
+               *freed_ret = freed;
+       ret = 0;
 out:
        extent_changeset_release(&changeset);
        return ret;
@@ -4112,7 +4115,7 @@ out:
 
 static int __btrfs_qgroup_release_data(struct btrfs_inode *inode,
                        struct extent_changeset *reserved, u64 start, u64 len,
-                       int free)
+                       u64 *released, int free)
 {
        struct extent_changeset changeset;
        int trace_op = QGROUP_RELEASE;
@@ -4128,7 +4131,7 @@ static int __btrfs_qgroup_release_data(struct btrfs_inode *inode,
        /* In release case, we shouldn't have @reserved */
        WARN_ON(!free && reserved);
        if (free && reserved)
-               return qgroup_free_reserved_data(inode, reserved, start, len);
+               return qgroup_free_reserved_data(inode, reserved, start, len, released);
        extent_changeset_init(&changeset);
        ret = clear_record_extent_bits(&inode->io_tree, start, start + len -1,
                                       EXTENT_QGROUP_RESERVED, &changeset);
@@ -4143,7 +4146,8 @@ static int __btrfs_qgroup_release_data(struct btrfs_inode *inode,
                btrfs_qgroup_free_refroot(inode->root->fs_info,
                                inode->root->root_key.objectid,
                                changeset.bytes_changed, BTRFS_QGROUP_RSV_DATA);
-       ret = changeset.bytes_changed;
+       if (released)
+               *released = changeset.bytes_changed;
 out:
        extent_changeset_release(&changeset);
        return ret;
@@ -4162,9 +4166,10 @@ out:
  * NOTE: This function may sleep for memory allocation.
  */
 int btrfs_qgroup_free_data(struct btrfs_inode *inode,
-                       struct extent_changeset *reserved, u64 start, u64 len)
+                          struct extent_changeset *reserved,
+                          u64 start, u64 len, u64 *freed)
 {
-       return __btrfs_qgroup_release_data(inode, reserved, start, len, 1);
+       return __btrfs_qgroup_release_data(inode, reserved, start, len, freed, 1);
 }
 
 /*
@@ -4182,9 +4187,9 @@ int btrfs_qgroup_free_data(struct btrfs_inode *inode,
  *
  * NOTE: This function may sleep for memory allocation.
  */
-int btrfs_qgroup_release_data(struct btrfs_inode *inode, u64 start, u64 len)
+int btrfs_qgroup_release_data(struct btrfs_inode *inode, u64 start, u64 len, u64 *released)
 {
-       return __btrfs_qgroup_release_data(inode, NULL, start, len, 0);
+       return __btrfs_qgroup_release_data(inode, NULL, start, len, released, 0);
 }
 
 static void add_root_meta_rsv(struct btrfs_root *root, int num_bytes,
@@ -4332,8 +4337,9 @@ static void qgroup_convert_meta(struct btrfs_fs_info *fs_info, u64 ref_root,
 
                qgroup_rsv_release(fs_info, qgroup, num_bytes,
                                BTRFS_QGROUP_RSV_META_PREALLOC);
-               qgroup_rsv_add(fs_info, qgroup, num_bytes,
-                               BTRFS_QGROUP_RSV_META_PERTRANS);
+               if (!sb_rdonly(fs_info->sb))
+                       qgroup_rsv_add(fs_info, qgroup, num_bytes,
+                                      BTRFS_QGROUP_RSV_META_PERTRANS);
 
                list_for_each_entry(glist, &qgroup->groups, next_group)
                        qgroup_iterator_add(&qgroup_list, glist->group);
@@ -4655,6 +4661,17 @@ void btrfs_qgroup_destroy_extent_records(struct btrfs_transaction *trans)
        *root = RB_ROOT;
 }
 
+void btrfs_free_squota_rsv(struct btrfs_fs_info *fs_info, u64 root, u64 rsv_bytes)
+{
+       if (btrfs_qgroup_mode(fs_info) != BTRFS_QGROUP_MODE_SIMPLE)
+               return;
+
+       if (!is_fstree(root))
+               return;
+
+       btrfs_qgroup_free_refroot(fs_info, root, rsv_bytes, BTRFS_QGROUP_RSV_DATA);
+}
+
 int btrfs_record_squota_delta(struct btrfs_fs_info *fs_info,
                              struct btrfs_squota_delta *delta)
 {
@@ -4699,8 +4716,5 @@ int btrfs_record_squota_delta(struct btrfs_fs_info *fs_info,
 
 out:
        spin_unlock(&fs_info->qgroup_lock);
-       if (!ret && delta->rsv_bytes)
-               btrfs_qgroup_free_refroot(fs_info, root, delta->rsv_bytes,
-                                         BTRFS_QGROUP_RSV_DATA);
        return ret;
 }
index 855a4f97876185099db6a188d70c75ace327071f..be18c862e64ede62e6db26877b7ca69fa3c3ad8a 100644 (file)
@@ -274,8 +274,6 @@ struct btrfs_squota_delta {
        u64 root;
        /* The number of bytes in the extent being counted. */
        u64 num_bytes;
-       /* The number of bytes reserved for this extent. */
-       u64 rsv_bytes;
        /* The generation the extent was created in. */
        u64 generation;
        /* Whether we are using or freeing the extent. */
@@ -358,10 +356,10 @@ int btrfs_verify_qgroup_counts(struct btrfs_fs_info *fs_info, u64 qgroupid,
 /* New io_tree based accurate qgroup reserve API */
 int btrfs_qgroup_reserve_data(struct btrfs_inode *inode,
                        struct extent_changeset **reserved, u64 start, u64 len);
-int btrfs_qgroup_release_data(struct btrfs_inode *inode, u64 start, u64 len);
+int btrfs_qgroup_release_data(struct btrfs_inode *inode, u64 start, u64 len, u64 *released);
 int btrfs_qgroup_free_data(struct btrfs_inode *inode,
                           struct extent_changeset *reserved, u64 start,
-                          u64 len);
+                          u64 len, u64 *freed);
 int btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes,
                              enum btrfs_qgroup_rsv_type type, bool enforce);
 int __btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes,
@@ -422,6 +420,7 @@ int btrfs_qgroup_trace_subtree_after_cow(struct btrfs_trans_handle *trans,
                struct btrfs_root *root, struct extent_buffer *eb);
 void btrfs_qgroup_destroy_extent_records(struct btrfs_transaction *trans);
 bool btrfs_check_quota_leak(struct btrfs_fs_info *fs_info);
+void btrfs_free_squota_rsv(struct btrfs_fs_info *fs_info, u64 root, u64 rsv_bytes);
 int btrfs_record_squota_delta(struct btrfs_fs_info *fs_info,
                              struct btrfs_squota_delta *delta);
 
index bfc0eb5e3b7c22f90ec83b4c5b53abd2fda5cd04..5b3333ceef04818dbf98270da4bb84c99e5c70f8 100644 (file)
@@ -37,8 +37,6 @@
 
 static struct kmem_cache *btrfs_trans_handle_cachep;
 
-#define BTRFS_ROOT_TRANS_TAG 0
-
 /*
  * Transaction states and transitions
  *
index 18c4f6e83b78839d3a2f65306eef097f0f28a944..2bf8bbdfd0b38b1b1caf3cf1cf0b6738d28f231f 100644 (file)
@@ -12,6 +12,9 @@
 #include "ctree.h"
 #include "misc.h"
 
+/* Radix-tree tag for roots that are part of the trasaction. */
+#define BTRFS_ROOT_TRANS_TAG                   0
+
 enum btrfs_trans_state {
        TRANS_STATE_RUNNING,
        TRANS_STATE_COMMIT_PREP,
index 0166bb9ca160bdb5196aa9731b2c2daebd3c7116..6aa15dafc67786559d3b68ebfefd8f90e119b3fc 100644 (file)
@@ -349,9 +349,10 @@ static void ext4_inode_extension_cleanup(struct inode *inode, ssize_t count)
                return;
        }
        /*
-        * If i_disksize got extended due to writeback of delalloc blocks while
-        * the DIO was running we could fail to cleanup the orphan list in
-        * ext4_handle_inode_extension(). Do it now.
+        * If i_disksize got extended either due to writeback of delalloc
+        * blocks or extending truncate while the DIO was running we could fail
+        * to cleanup the orphan list in ext4_handle_inode_extension(). Do it
+        * now.
         */
        if (!list_empty(&EXT4_I(inode)->i_orphan) && inode->i_nlink) {
                handle_t *handle = ext4_journal_start(inode, EXT4_HT_INODE, 2);
@@ -386,10 +387,11 @@ static int ext4_dio_write_end_io(struct kiocb *iocb, ssize_t size,
         * blocks. But the code in ext4_iomap_alloc() is careful to use
         * zeroed/unwritten extents if this is possible; thus we won't leave
         * uninitialized blocks in a file even if we didn't succeed in writing
-        * as much as we intended.
+        * as much as we intended. Also we can race with truncate or write
+        * expanding the file so we have to be a bit careful here.
         */
-       WARN_ON_ONCE(i_size_read(inode) < READ_ONCE(EXT4_I(inode)->i_disksize));
-       if (pos + size <= READ_ONCE(EXT4_I(inode)->i_disksize))
+       if (pos + size <= READ_ONCE(EXT4_I(inode)->i_disksize) &&
+           pos + size <= i_size_read(inode))
                return size;
        return ext4_handle_inode_extension(inode, pos, size);
 }
index 454d5612641ee3c32e71114e4d6148c52b484459..d72b5e3c92ec4088b878246f431059906d8cf931 100644 (file)
@@ -4478,6 +4478,10 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
        start = max(start, rounddown(ac->ac_o_ex.fe_logical,
                        (ext4_lblk_t)EXT4_BLOCKS_PER_GROUP(ac->ac_sb)));
 
+       /* avoid unnecessary preallocation that may trigger assertions */
+       if (start + size > EXT_MAX_BLOCKS)
+               size = EXT_MAX_BLOCKS - start;
+
        /* don't cover already allocated blocks in selected range */
        if (ar->pleft && start <= ar->lleft) {
                size -= ar->lleft + 1 - start;
index 23904a6a9a96f74a45eb8c2f9bf72d795e05ac60..12ef91d170bb3091ac35a33d2b9dc38330b00948 100644 (file)
@@ -1222,6 +1222,7 @@ void fuse_dax_conn_free(struct fuse_conn *fc)
        if (fc->dax) {
                fuse_free_dax_mem_ranges(&fc->dax->free_ranges);
                kfree(fc->dax);
+               fc->dax = NULL;
        }
 }
 
index 1cdb6327511ef843db8936302fe7f141c4016186..a660f1f21540abbb3dd60e876ca81a587af3336e 100644 (file)
@@ -1448,7 +1448,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter,
        if (!ia)
                return -ENOMEM;
 
-       if (fopen_direct_io && fc->direct_io_relax) {
+       if (fopen_direct_io && fc->direct_io_allow_mmap) {
                res = filemap_write_and_wait_range(mapping, pos, pos + count - 1);
                if (res) {
                        fuse_io_free(ia);
@@ -1574,6 +1574,7 @@ static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from)
        ssize_t res;
        bool exclusive_lock =
                !(ff->open_flags & FOPEN_PARALLEL_DIRECT_WRITES) ||
+               get_fuse_conn(inode)->direct_io_allow_mmap ||
                iocb->ki_flags & IOCB_APPEND ||
                fuse_direct_write_extending_i_size(iocb, from);
 
@@ -1581,6 +1582,7 @@ static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from)
         * Take exclusive lock if
         * - Parallel direct writes are disabled - a user space decision
         * - Parallel direct writes are enabled and i_size is being extended.
+        * - Shared mmap on direct_io file is supported (FUSE_DIRECT_IO_ALLOW_MMAP).
         *   This might not be needed at all, but needs further investigation.
         */
        if (exclusive_lock)
@@ -2466,9 +2468,9 @@ static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
 
        if (ff->open_flags & FOPEN_DIRECT_IO) {
                /* Can't provide the coherency needed for MAP_SHARED
-                * if FUSE_DIRECT_IO_RELAX isn't set.
+                * if FUSE_DIRECT_IO_ALLOW_MMAP isn't set.
                 */
-               if ((vma->vm_flags & VM_MAYSHARE) && !fc->direct_io_relax)
+               if ((vma->vm_flags & VM_MAYSHARE) && !fc->direct_io_allow_mmap)
                        return -ENODEV;
 
                invalidate_inode_pages2(file->f_mapping);
index 6e6e721f421b9da154ff504cfe8fbcff0602bb0d..1df83eebda92771d20a42ea2aaefa118effcbc77 100644 (file)
@@ -63,6 +63,19 @@ struct fuse_forget_link {
        struct fuse_forget_link *next;
 };
 
+/* Submount lookup tracking */
+struct fuse_submount_lookup {
+       /** Refcount */
+       refcount_t count;
+
+       /** Unique ID, which identifies the inode between userspace
+        * and kernel */
+       u64 nodeid;
+
+       /** The request used for sending the FORGET message */
+       struct fuse_forget_link *forget;
+};
+
 /** FUSE inode */
 struct fuse_inode {
        /** Inode data */
@@ -158,6 +171,8 @@ struct fuse_inode {
         */
        struct fuse_inode_dax *dax;
 #endif
+       /** Submount specific lookup tracking */
+       struct fuse_submount_lookup *submount_lookup;
 };
 
 /** FUSE inode state bits */
@@ -797,8 +812,8 @@ struct fuse_conn {
        /* Is tmpfile not implemented by fs? */
        unsigned int no_tmpfile:1;
 
-       /* relax restrictions in FOPEN_DIRECT_IO mode */
-       unsigned int direct_io_relax:1;
+       /* Relax restrictions to allow shared mmap in FOPEN_DIRECT_IO mode */
+       unsigned int direct_io_allow_mmap:1;
 
        /* Is statx not implemented by fs? */
        unsigned int no_statx:1;
index 74d4f09d5827e8af92aef881eb8060fa69e4afca..2a6d44f91729bbd7e3bf1c955a952ecdd695bd0f 100644 (file)
@@ -68,6 +68,24 @@ struct fuse_forget_link *fuse_alloc_forget(void)
        return kzalloc(sizeof(struct fuse_forget_link), GFP_KERNEL_ACCOUNT);
 }
 
+static struct fuse_submount_lookup *fuse_alloc_submount_lookup(void)
+{
+       struct fuse_submount_lookup *sl;
+
+       sl = kzalloc(sizeof(struct fuse_submount_lookup), GFP_KERNEL_ACCOUNT);
+       if (!sl)
+               return NULL;
+       sl->forget = fuse_alloc_forget();
+       if (!sl->forget)
+               goto out_free;
+
+       return sl;
+
+out_free:
+       kfree(sl);
+       return NULL;
+}
+
 static struct inode *fuse_alloc_inode(struct super_block *sb)
 {
        struct fuse_inode *fi;
@@ -83,6 +101,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb)
        fi->attr_version = 0;
        fi->orig_ino = 0;
        fi->state = 0;
+       fi->submount_lookup = NULL;
        mutex_init(&fi->mutex);
        spin_lock_init(&fi->lock);
        fi->forget = fuse_alloc_forget();
@@ -113,6 +132,17 @@ static void fuse_free_inode(struct inode *inode)
        kmem_cache_free(fuse_inode_cachep, fi);
 }
 
+static void fuse_cleanup_submount_lookup(struct fuse_conn *fc,
+                                        struct fuse_submount_lookup *sl)
+{
+       if (!refcount_dec_and_test(&sl->count))
+               return;
+
+       fuse_queue_forget(fc, sl->forget, sl->nodeid, 1);
+       sl->forget = NULL;
+       kfree(sl);
+}
+
 static void fuse_evict_inode(struct inode *inode)
 {
        struct fuse_inode *fi = get_fuse_inode(inode);
@@ -132,6 +162,11 @@ static void fuse_evict_inode(struct inode *inode)
                                          fi->nlookup);
                        fi->forget = NULL;
                }
+
+               if (fi->submount_lookup) {
+                       fuse_cleanup_submount_lookup(fc, fi->submount_lookup);
+                       fi->submount_lookup = NULL;
+               }
        }
        if (S_ISREG(inode->i_mode) && !fuse_is_bad(inode)) {
                WARN_ON(!list_empty(&fi->write_files));
@@ -330,6 +365,13 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
                fuse_dax_dontcache(inode, attr->flags);
 }
 
+static void fuse_init_submount_lookup(struct fuse_submount_lookup *sl,
+                                     u64 nodeid)
+{
+       sl->nodeid = nodeid;
+       refcount_set(&sl->count, 1);
+}
+
 static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr,
                            struct fuse_conn *fc)
 {
@@ -392,12 +434,22 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
         */
        if (fc->auto_submounts && (attr->flags & FUSE_ATTR_SUBMOUNT) &&
            S_ISDIR(attr->mode)) {
+               struct fuse_inode *fi;
+
                inode = new_inode(sb);
                if (!inode)
                        return NULL;
 
                fuse_init_inode(inode, attr, fc);
-               get_fuse_inode(inode)->nodeid = nodeid;
+               fi = get_fuse_inode(inode);
+               fi->nodeid = nodeid;
+               fi->submount_lookup = fuse_alloc_submount_lookup();
+               if (!fi->submount_lookup) {
+                       iput(inode);
+                       return NULL;
+               }
+               /* Sets nlookup = 1 on fi->submount_lookup->nlookup */
+               fuse_init_submount_lookup(fi->submount_lookup, nodeid);
                inode->i_flags |= S_AUTOMOUNT;
                goto done;
        }
@@ -420,11 +472,11 @@ retry:
                iput(inode);
                goto retry;
        }
-done:
        fi = get_fuse_inode(inode);
        spin_lock(&fi->lock);
        fi->nlookup++;
        spin_unlock(&fi->lock);
+done:
        fuse_change_attributes(inode, attr, NULL, attr_valid, attr_version);
 
        return inode;
@@ -1230,8 +1282,8 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args,
                                fc->init_security = 1;
                        if (flags & FUSE_CREATE_SUPP_GROUP)
                                fc->create_supp_group = 1;
-                       if (flags & FUSE_DIRECT_IO_RELAX)
-                               fc->direct_io_relax = 1;
+                       if (flags & FUSE_DIRECT_IO_ALLOW_MMAP)
+                               fc->direct_io_allow_mmap = 1;
                } else {
                        ra_pages = fc->max_read / PAGE_SIZE;
                        fc->no_lock = 1;
@@ -1278,7 +1330,7 @@ void fuse_send_init(struct fuse_mount *fm)
                FUSE_NO_OPENDIR_SUPPORT | FUSE_EXPLICIT_INVAL_DATA |
                FUSE_HANDLE_KILLPRIV_V2 | FUSE_SETXATTR_EXT | FUSE_INIT_EXT |
                FUSE_SECURITY_CTX | FUSE_CREATE_SUPP_GROUP |
-               FUSE_HAS_EXPIRE_ONLY | FUSE_DIRECT_IO_RELAX;
+               FUSE_HAS_EXPIRE_ONLY | FUSE_DIRECT_IO_ALLOW_MMAP;
 #ifdef CONFIG_FUSE_DAX
        if (fm->fc->dax)
                flags |= FUSE_MAP_ALIGNMENT;
@@ -1465,6 +1517,8 @@ static int fuse_fill_super_submount(struct super_block *sb,
        struct super_block *parent_sb = parent_fi->inode.i_sb;
        struct fuse_attr root_attr;
        struct inode *root;
+       struct fuse_submount_lookup *sl;
+       struct fuse_inode *fi;
 
        fuse_sb_defaults(sb);
        fm->sb = sb;
@@ -1487,12 +1541,27 @@ static int fuse_fill_super_submount(struct super_block *sb,
         * its nlookup should not be incremented.  fuse_iget() does
         * that, though, so undo it here.
         */
-       get_fuse_inode(root)->nlookup--;
+       fi = get_fuse_inode(root);
+       fi->nlookup--;
+
        sb->s_d_op = &fuse_dentry_operations;
        sb->s_root = d_make_root(root);
        if (!sb->s_root)
                return -ENOMEM;
 
+       /*
+        * Grab the parent's submount_lookup pointer and take a
+        * reference on the shared nlookup from the parent.  This is to
+        * prevent the last forget for this nodeid from getting
+        * triggered until all users have finished with it.
+        */
+       sl = parent_fi->submount_lookup;
+       WARN_ON(!sl);
+       if (sl) {
+               refcount_inc(&sl->count);
+               fi->submount_lookup = sl;
+       }
+
        return 0;
 }
 
index 8d6f934c3d9543d3c87a77f5ec3566df7a2b2a37..5e122586e06ed0f9b9a36ebfe089ca7b3a75aee8 100644 (file)
@@ -119,7 +119,7 @@ static int journal_submit_commit_record(journal_t *journal,
        struct commit_header *tmp;
        struct buffer_head *bh;
        struct timespec64 now;
-       blk_opf_t write_flags = REQ_OP_WRITE | REQ_SYNC;
+       blk_opf_t write_flags = REQ_OP_WRITE | JBD2_JOURNAL_REQ_FLAGS;
 
        *cbh = NULL;
 
@@ -270,6 +270,7 @@ static int journal_finish_inode_data_buffers(journal_t *journal,
                        if (!ret)
                                ret = err;
                }
+               cond_resched();
                spin_lock(&journal->j_list_lock);
                jinode->i_flags &= ~JI_COMMIT_RUNNING;
                smp_mb();
@@ -395,8 +396,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
                 */
                jbd2_journal_update_sb_log_tail(journal,
                                                journal->j_tail_sequence,
-                                               journal->j_tail,
-                                               REQ_SYNC);
+                                               journal->j_tail, 0);
                mutex_unlock(&journal->j_checkpoint_mutex);
        } else {
                jbd2_debug(3, "superblock not updated\n");
@@ -715,6 +715,7 @@ start_journal_io:
 
                        for (i = 0; i < bufs; i++) {
                                struct buffer_head *bh = wbuf[i];
+
                                /*
                                 * Compute checksum.
                                 */
@@ -727,7 +728,8 @@ start_journal_io:
                                clear_buffer_dirty(bh);
                                set_buffer_uptodate(bh);
                                bh->b_end_io = journal_end_buffer_io_sync;
-                               submit_bh(REQ_OP_WRITE | REQ_SYNC, bh);
+                               submit_bh(REQ_OP_WRITE | JBD2_JOURNAL_REQ_FLAGS,
+                                         bh);
                        }
                        cond_resched();
 
index ed53188472f9aa9949d1c3c6338cba01f725b79a..206cb53ef2b06813a7344da309e0d811dd3e808c 100644 (file)
@@ -1100,8 +1100,7 @@ int __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block)
         * space and if we lose sb update during power failure we'd replay
         * old transaction with possibly newly overwritten data.
         */
-       ret = jbd2_journal_update_sb_log_tail(journal, tid, block,
-                                             REQ_SYNC | REQ_FUA);
+       ret = jbd2_journal_update_sb_log_tail(journal, tid, block, REQ_FUA);
        if (ret)
                goto out;
 
@@ -1775,8 +1774,7 @@ static int journal_reset(journal_t *journal)
                 */
                jbd2_journal_update_sb_log_tail(journal,
                                                journal->j_tail_sequence,
-                                               journal->j_tail,
-                                               REQ_SYNC | REQ_FUA);
+                                               journal->j_tail, REQ_FUA);
                mutex_unlock(&journal->j_checkpoint_mutex);
        }
        return jbd2_journal_start_thread(journal);
@@ -1798,9 +1796,16 @@ static int jbd2_write_superblock(journal_t *journal, blk_opf_t write_flags)
                return -EIO;
        }
 
-       trace_jbd2_write_superblock(journal, write_flags);
+       /*
+        * Always set high priority flags to exempt from block layer's
+        * QOS policies, e.g. writeback throttle.
+        */
+       write_flags |= JBD2_JOURNAL_REQ_FLAGS;
        if (!(journal->j_flags & JBD2_BARRIER))
                write_flags &= ~(REQ_FUA | REQ_PREFLUSH);
+
+       trace_jbd2_write_superblock(journal, write_flags);
+
        if (buffer_write_io_error(bh)) {
                /*
                 * Oh, dear.  A previous attempt to write the journal
@@ -2050,7 +2055,7 @@ void jbd2_journal_update_sb_errno(journal_t *journal)
        jbd2_debug(1, "JBD2: updating superblock error (errno %d)\n", errcode);
        sb->s_errno    = cpu_to_be32(errcode);
 
-       jbd2_write_superblock(journal, REQ_SYNC | REQ_FUA);
+       jbd2_write_superblock(journal, REQ_FUA);
 }
 EXPORT_SYMBOL(jbd2_journal_update_sb_errno);
 
@@ -2171,8 +2176,7 @@ int jbd2_journal_destroy(journal_t *journal)
                                ++journal->j_transaction_sequence;
                        write_unlock(&journal->j_state_lock);
 
-                       jbd2_mark_journal_empty(journal,
-                                       REQ_SYNC | REQ_PREFLUSH | REQ_FUA);
+                       jbd2_mark_journal_empty(journal, REQ_PREFLUSH | REQ_FUA);
                        mutex_unlock(&journal->j_checkpoint_mutex);
                } else
                        err = -EIO;
@@ -2473,7 +2477,7 @@ int jbd2_journal_flush(journal_t *journal, unsigned int flags)
         * the magic code for a fully-recovered superblock.  Any future
         * commits of data to the journal will restore the current
         * s_start value. */
-       jbd2_mark_journal_empty(journal, REQ_SYNC | REQ_FUA);
+       jbd2_mark_journal_empty(journal, REQ_FUA);
 
        if (flags)
                err = __jbd2_journal_erase(journal, flags);
@@ -2519,7 +2523,7 @@ int jbd2_journal_wipe(journal_t *journal, int write)
        if (write) {
                /* Lock to make assertions happy... */
                mutex_lock_io(&journal->j_checkpoint_mutex);
-               jbd2_mark_journal_empty(journal, REQ_SYNC | REQ_FUA);
+               jbd2_mark_journal_empty(journal, REQ_FUA);
                mutex_unlock(&journal->j_checkpoint_mutex);
        }
 
index fdf2aad7347090b7ceecd97a5a9eb3dfdfc1093a..e6beaaf4f1700b0ac78d05128dc23fd74c902dcb 100644 (file)
@@ -26,8 +26,6 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
        int i;
        int flags = nfsexp_flags(rqstp, exp);
 
-       validate_process_creds();
-
        /* discard any old override before preparing the new set */
        revert_creds(get_cred(current_real_cred()));
        new = prepare_creds();
@@ -81,10 +79,8 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
        else
                new->cap_effective = cap_raise_nfsd_set(new->cap_effective,
                                                        new->cap_permitted);
-       validate_process_creds();
        put_cred(override_creds(new));
        put_cred(new);
-       validate_process_creds();
        return 0;
 
 oom:
index fe61d9bbcc1faa2d704f9ec926812a022d78381d..5014ab87d313f6797af445967a05288ac6e0750c 100644 (file)
@@ -955,7 +955,6 @@ nfsd(void *vrqstp)
                rqstp->rq_server->sv_maxconn = nn->max_connections;
 
                svc_recv(rqstp);
-               validate_process_creds();
        }
 
        atomic_dec(&nfsdstats.th_cnt);
index fbbea7498f02b4845c2302f84f91c5b0f555b5a6..e01e4e2acbd9a26cf8c6617ce29e1aba7968bceb 100644 (file)
@@ -901,7 +901,6 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
        int host_err;
        bool retried = false;
 
-       validate_process_creds();
        /*
         * If we get here, then the client has already done an "open",
         * and (hopefully) checked permission - so allow OWNER_OVERRIDE
@@ -926,7 +925,6 @@ retry:
                }
                err = nfserrno(host_err);
        }
-       validate_process_creds();
        return err;
 }
 
@@ -943,12 +941,7 @@ int
 nfsd_open_verified(struct svc_rqst *rqstp, struct svc_fh *fhp, int may_flags,
                   struct file **filp)
 {
-       int err;
-
-       validate_process_creds();
-       err = __nfsd_open(rqstp, fhp, S_IFREG, may_flags, filp);
-       validate_process_creds();
-       return err;
+       return __nfsd_open(rqstp, fhp, S_IFREG, may_flags, filp);
 }
 
 /*
index 02dc608d40d81f90c9427695763c85d0fd111e93..3494a9cd8046c42a0f9b681c87285e922a8afa40 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -1088,8 +1088,6 @@ struct file *dentry_open(const struct path *path, int flags,
        int error;
        struct file *f;
 
-       validate_creds(cred);
-
        /* We must always pass in a valid mount pointer. */
        BUG_ON(!path->mnt);
 
@@ -1128,7 +1126,6 @@ struct file *dentry_create(const struct path *path, int flags, umode_t mode,
        struct file *f;
        int error;
 
-       validate_creds(cred);
        f = alloc_empty_file(flags, cred);
        if (IS_ERR(f))
                return f;
index 59f6b8e32cc97acda64aa7b95c45544a1e52ee0a..d64a306a414be0580e910842b19f150bf43863a9 100644 (file)
@@ -291,16 +291,23 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
        oparms.fid->mid = le64_to_cpu(o_rsp->hdr.MessageId);
 #endif /* CIFS_DEBUG2 */
 
-       rc = -EINVAL;
+
        if (o_rsp->OplockLevel != SMB2_OPLOCK_LEVEL_LEASE) {
+               spin_unlock(&cfids->cfid_list_lock);
+               rc = -EINVAL;
+               goto oshr_free;
+       }
+
+       rc = smb2_parse_contexts(server, rsp_iov,
+                                &oparms.fid->epoch,
+                                oparms.fid->lease_key,
+                                &oplock, NULL, NULL);
+       if (rc) {
                spin_unlock(&cfids->cfid_list_lock);
                goto oshr_free;
        }
 
-       smb2_parse_contexts(server, o_rsp,
-                           &oparms.fid->epoch,
-                           oparms.fid->lease_key, &oplock,
-                           NULL, NULL);
+       rc = -EINVAL;
        if (!(oplock & SMB2_LEASE_READ_CACHING_HE)) {
                spin_unlock(&cfids->cfid_list_lock);
                goto oshr_free;
index 32dfa0f7a78c30013f9d5ead8c5f684b295183ec..e20b4354e703b8e9662808bf19441fe91a7f682b 100644 (file)
@@ -313,6 +313,9 @@ static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = {
 char *
 smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *shdr)
 {
+       const int max_off = 4096;
+       const int max_len = 128 * 1024;
+
        *off = 0;
        *len = 0;
 
@@ -384,29 +387,20 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *shdr)
         * Invalid length or offset probably means data area is invalid, but
         * we have little choice but to ignore the data area in this case.
         */
-       if (*off > 4096) {
-               cifs_dbg(VFS, "offset %d too large, data area ignored\n", *off);
-               *len = 0;
-               *off = 0;
-       } else if (*off < 0) {
-               cifs_dbg(VFS, "negative offset %d to data invalid ignore data area\n",
-                        *off);
+       if (unlikely(*off < 0 || *off > max_off ||
+                    *len < 0 || *len > max_len)) {
+               cifs_dbg(VFS, "%s: invalid data area (off=%d len=%d)\n",
+                        __func__, *off, *len);
                *off = 0;
                *len = 0;
-       } else if (*len < 0) {
-               cifs_dbg(VFS, "negative data length %d invalid, data area ignored\n",
-                        *len);
-               *len = 0;
-       } else if (*len > 128 * 1024) {
-               cifs_dbg(VFS, "data area larger than 128K: %d\n", *len);
+       } else if (*off == 0) {
                *len = 0;
        }
 
        /* return pointer to beginning of data area, ie offset from SMB start */
-       if ((*off != 0) && (*len != 0))
+       if (*off > 0 && *len > 0)
                return (char *)shdr + *off;
-       else
-               return NULL;
+       return NULL;
 }
 
 /*
index fcfb6566b899fb6c4b394cca215419396dcb293b..8f6f0a38b88684aa0287a9df8fe776b1760984ea 100644 (file)
@@ -3003,7 +3003,7 @@ static int smb2_query_reparse_point(const unsigned int xid,
        struct kvec *rsp_iov;
        struct smb2_ioctl_rsp *ioctl_rsp;
        struct reparse_data_buffer *reparse_buf;
-       u32 plen;
+       u32 off, count, len;
 
        cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
 
@@ -3084,16 +3084,22 @@ static int smb2_query_reparse_point(const unsigned int xid,
         */
        if (rc == 0) {
                /* See MS-FSCC 2.3.23 */
+               off = le32_to_cpu(ioctl_rsp->OutputOffset);
+               count = le32_to_cpu(ioctl_rsp->OutputCount);
+               if (check_add_overflow(off, count, &len) ||
+                   len > rsp_iov[1].iov_len) {
+                       cifs_tcon_dbg(VFS, "%s: invalid ioctl: off=%d count=%d\n",
+                                     __func__, off, count);
+                       rc = -EIO;
+                       goto query_rp_exit;
+               }
 
-               reparse_buf = (struct reparse_data_buffer *)
-                       ((char *)ioctl_rsp +
-                        le32_to_cpu(ioctl_rsp->OutputOffset));
-               plen = le32_to_cpu(ioctl_rsp->OutputCount);
-
-               if (plen + le32_to_cpu(ioctl_rsp->OutputOffset) >
-                   rsp_iov[1].iov_len) {
-                       cifs_tcon_dbg(FYI, "srv returned invalid ioctl len: %d\n",
-                                plen);
+               reparse_buf = (void *)((u8 *)ioctl_rsp + off);
+               len = sizeof(*reparse_buf);
+               if (count < len ||
+                   count < le16_to_cpu(reparse_buf->ReparseDataLength) + len) {
+                       cifs_tcon_dbg(VFS, "%s: invalid ioctl: off=%d count=%d\n",
+                                     __func__, off, count);
                        rc = -EIO;
                        goto query_rp_exit;
                }
@@ -4943,6 +4949,7 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
        struct smb2_hdr *shdr;
        unsigned int pdu_length = server->pdu_size;
        unsigned int buf_size;
+       unsigned int next_cmd;
        struct mid_q_entry *mid_entry;
        int next_is_large;
        char *next_buffer = NULL;
@@ -4971,14 +4978,15 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
        next_is_large = server->large_buf;
 one_more:
        shdr = (struct smb2_hdr *)buf;
-       if (shdr->NextCommand) {
+       next_cmd = le32_to_cpu(shdr->NextCommand);
+       if (next_cmd) {
+               if (WARN_ON_ONCE(next_cmd > pdu_length))
+                       return -1;
                if (next_is_large)
                        next_buffer = (char *)cifs_buf_get();
                else
                        next_buffer = (char *)cifs_small_buf_get();
-               memcpy(next_buffer,
-                      buf + le32_to_cpu(shdr->NextCommand),
-                      pdu_length - le32_to_cpu(shdr->NextCommand));
+               memcpy(next_buffer, buf + next_cmd, pdu_length - next_cmd);
        }
 
        mid_entry = smb2_find_mid(server, buf);
@@ -5002,8 +5010,8 @@ one_more:
        else
                ret = cifs_handle_standard(server, mid_entry);
 
-       if (ret == 0 && shdr->NextCommand) {
-               pdu_length -= le32_to_cpu(shdr->NextCommand);
+       if (ret == 0 && next_cmd) {
+               pdu_length -= next_cmd;
                server->large_buf = next_is_large;
                if (next_is_large)
                        server->bigbuf = buf = next_buffer;
index 20634fc6d4f09eced1aa6ad08741432f147fc87d..c571760ad39a100bd90fada8a0ad8905c6235e2b 100644 (file)
@@ -2236,17 +2236,18 @@ parse_posix_ctxt(struct create_context *cc, struct smb2_file_all_info *info,
                 posix->nlink, posix->mode, posix->reparse_tag);
 }
 
-void
-smb2_parse_contexts(struct TCP_Server_Info *server,
-                   struct smb2_create_rsp *rsp,
-                   unsigned int *epoch, char *lease_key, __u8 *oplock,
-                   struct smb2_file_all_info *buf,
-                   struct create_posix_rsp *posix)
+int smb2_parse_contexts(struct TCP_Server_Info *server,
+                       struct kvec *rsp_iov,
+                       unsigned int *epoch,
+                       char *lease_key, __u8 *oplock,
+                       struct smb2_file_all_info *buf,
+                       struct create_posix_rsp *posix)
 {
-       char *data_offset;
+       struct smb2_create_rsp *rsp = rsp_iov->iov_base;
        struct create_context *cc;
-       unsigned int next;
-       unsigned int remaining;
+       size_t rem, off, len;
+       size_t doff, dlen;
+       size_t noff, nlen;
        char *name;
        static const char smb3_create_tag_posix[] = {
                0x93, 0xAD, 0x25, 0x50, 0x9C,
@@ -2255,45 +2256,63 @@ smb2_parse_contexts(struct TCP_Server_Info *server,
        };
 
        *oplock = 0;
-       data_offset = (char *)rsp + le32_to_cpu(rsp->CreateContextsOffset);
-       remaining = le32_to_cpu(rsp->CreateContextsLength);
-       cc = (struct create_context *)data_offset;
+
+       off = le32_to_cpu(rsp->CreateContextsOffset);
+       rem = le32_to_cpu(rsp->CreateContextsLength);
+       if (check_add_overflow(off, rem, &len) || len > rsp_iov->iov_len)
+               return -EINVAL;
+       cc = (struct create_context *)((u8 *)rsp + off);
 
        /* Initialize inode number to 0 in case no valid data in qfid context */
        if (buf)
                buf->IndexNumber = 0;
 
-       while (remaining >= sizeof(struct create_context)) {
-               name = le16_to_cpu(cc->NameOffset) + (char *)cc;
-               if (le16_to_cpu(cc->NameLength) == 4 &&
-                   strncmp(name, SMB2_CREATE_REQUEST_LEASE, 4) == 0)
-                       *oplock = server->ops->parse_lease_buf(cc, epoch,
-                                                          lease_key);
-               else if (buf && (le16_to_cpu(cc->NameLength) == 4) &&
-                   strncmp(name, SMB2_CREATE_QUERY_ON_DISK_ID, 4) == 0)
-                       parse_query_id_ctxt(cc, buf);
-               else if ((le16_to_cpu(cc->NameLength) == 16)) {
-                       if (posix &&
-                           memcmp(name, smb3_create_tag_posix, 16) == 0)
+       while (rem >= sizeof(*cc)) {
+               doff = le16_to_cpu(cc->DataOffset);
+               dlen = le32_to_cpu(cc->DataLength);
+               if (check_add_overflow(doff, dlen, &len) || len > rem)
+                       return -EINVAL;
+
+               noff = le16_to_cpu(cc->NameOffset);
+               nlen = le16_to_cpu(cc->NameLength);
+               if (noff + nlen >= doff)
+                       return -EINVAL;
+
+               name = (char *)cc + noff;
+               switch (nlen) {
+               case 4:
+                       if (!strncmp(name, SMB2_CREATE_REQUEST_LEASE, 4)) {
+                               *oplock = server->ops->parse_lease_buf(cc, epoch,
+                                                                      lease_key);
+                       } else if (buf &&
+                                  !strncmp(name, SMB2_CREATE_QUERY_ON_DISK_ID, 4)) {
+                               parse_query_id_ctxt(cc, buf);
+                       }
+                       break;
+               case 16:
+                       if (posix && !memcmp(name, smb3_create_tag_posix, 16))
                                parse_posix_ctxt(cc, buf, posix);
+                       break;
+               default:
+                       cifs_dbg(FYI, "%s: unhandled context (nlen=%zu dlen=%zu)\n",
+                                __func__, nlen, dlen);
+                       if (IS_ENABLED(CONFIG_CIFS_DEBUG2))
+                               cifs_dump_mem("context data: ", cc, dlen);
+                       break;
                }
-               /* else {
-                       cifs_dbg(FYI, "Context not matched with len %d\n",
-                               le16_to_cpu(cc->NameLength));
-                       cifs_dump_mem("Cctxt name: ", name, 4);
-               } */
-
-               next = le32_to_cpu(cc->Next);
-               if (!next)
+
+               off = le32_to_cpu(cc->Next);
+               if (!off)
                        break;
-               remaining -= next;
-               cc = (struct create_context *)((char *)cc + next);
+               if (check_sub_overflow(rem, off, &rem))
+                       return -EINVAL;
+               cc = (struct create_context *)((u8 *)cc + off);
        }
 
        if (rsp->OplockLevel != SMB2_OPLOCK_LEVEL_LEASE)
                *oplock = rsp->OplockLevel;
 
-       return;
+       return 0;
 }
 
 static int
@@ -3124,8 +3143,8 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
        }
 
 
-       smb2_parse_contexts(server, rsp, &oparms->fid->epoch,
-                           oparms->fid->lease_key, oplock, buf, posix);
+       rc = smb2_parse_contexts(server, &rsp_iov, &oparms->fid->epoch,
+                                oparms->fid->lease_key, oplock, buf, posix);
 creat_exit:
        SMB2_open_free(&rqst);
        free_rsp_buf(resp_buftype, rsp);
index 46eff9ec302aadc5c1eccdc2e13168607f5304c1..0e371f7e2854b924053cbec235ef3b94f9244551 100644 (file)
@@ -251,11 +251,13 @@ extern int smb3_validate_negotiate(const unsigned int, struct cifs_tcon *);
 
 extern enum securityEnum smb2_select_sectype(struct TCP_Server_Info *,
                                        enum securityEnum);
-extern void smb2_parse_contexts(struct TCP_Server_Info *server,
-                               struct smb2_create_rsp *rsp,
-                               unsigned int *epoch, char *lease_key,
-                               __u8 *oplock, struct smb2_file_all_info *buf,
-                               struct create_posix_rsp *posix);
+int smb2_parse_contexts(struct TCP_Server_Info *server,
+                       struct kvec *rsp_iov,
+                       unsigned int *epoch,
+                       char *lease_key, __u8 *oplock,
+                       struct smb2_file_all_info *buf,
+                       struct create_posix_rsp *posix);
+
 extern int smb3_encryption_required(const struct cifs_tcon *tcon);
 extern int smb2_validate_iov(unsigned int offset, unsigned int buffer_length,
                             struct kvec *iov, unsigned int min_buf_size);
index 9fbaaa387dcc50c05d22cc55c680ca4105c152cd..57f2343164a34d81ad9816c0dec7c8994b66beb0 100644 (file)
@@ -1145,7 +1145,7 @@ struct smb2_server_client_notification {
 #define SMB2_CREATE_SD_BUFFER                  "SecD" /* security descriptor */
 #define SMB2_CREATE_DURABLE_HANDLE_REQUEST     "DHnQ"
 #define SMB2_CREATE_DURABLE_HANDLE_RECONNECT   "DHnC"
-#define SMB2_CREATE_ALLOCATION_SIZE            "AISi"
+#define SMB2_CREATE_ALLOCATION_SIZE            "AlSi"
 #define SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST "MxAc"
 #define SMB2_CREATE_TIMEWARP_REQUEST           "TWrp"
 #define SMB2_CREATE_QUERY_ON_DISK_ID           "QFid"
@@ -1253,6 +1253,7 @@ struct create_mxac_rsp {
 #define SMB2_LEASE_WRITE_CACHING_LE            cpu_to_le32(0x04)
 
 #define SMB2_LEASE_FLAG_BREAK_IN_PROGRESS_LE   cpu_to_le32(0x02)
+#define SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE        cpu_to_le32(0x04)
 
 #define SMB2_LEASE_KEY_SIZE                    16
 
index 50c68beb71d6c49855b3f3dc8b8b2789e25e90c5..562b180459a1a82d9137c96a2832b85485561c7a 100644 (file)
@@ -102,9 +102,10 @@ static int alloc_lease(struct oplock_info *opinfo, struct lease_ctx_info *lctx)
        lease->new_state = 0;
        lease->flags = lctx->flags;
        lease->duration = lctx->duration;
+       lease->is_dir = lctx->is_dir;
        memcpy(lease->parent_lease_key, lctx->parent_lease_key, SMB2_LEASE_KEY_SIZE);
        lease->version = lctx->version;
-       lease->epoch = 0;
+       lease->epoch = le16_to_cpu(lctx->epoch);
        INIT_LIST_HEAD(&opinfo->lease_entry);
        opinfo->o_lease = lease;
 
@@ -395,8 +396,8 @@ void close_id_del_oplock(struct ksmbd_file *fp)
 {
        struct oplock_info *opinfo;
 
-       if (S_ISDIR(file_inode(fp->filp)->i_mode))
-               return;
+       if (fp->reserve_lease_break)
+               smb_lazy_parent_lease_break_close(fp);
 
        opinfo = opinfo_get(fp);
        if (!opinfo)
@@ -543,12 +544,13 @@ static struct oplock_info *same_client_has_lease(struct ksmbd_inode *ci,
                        /* upgrading lease */
                        if ((atomic_read(&ci->op_count) +
                             atomic_read(&ci->sop_count)) == 1) {
-                               if (lease->state ==
-                                   (lctx->req_state & lease->state)) {
+                               if (lease->state != SMB2_LEASE_NONE_LE &&
+                                   lease->state == (lctx->req_state & lease->state)) {
                                        lease->state |= lctx->req_state;
                                        if (lctx->req_state &
                                                SMB2_LEASE_WRITE_CACHING_LE)
                                                lease_read_to_write(opinfo);
+
                                }
                        } else if ((atomic_read(&ci->op_count) +
                                    atomic_read(&ci->sop_count)) > 1) {
@@ -900,7 +902,8 @@ static int oplock_break(struct oplock_info *brk_opinfo, int req_op_level)
                                        lease->new_state =
                                                SMB2_LEASE_READ_CACHING_LE;
                        } else {
-                               if (lease->state & SMB2_LEASE_HANDLE_CACHING_LE)
+                               if (lease->state & SMB2_LEASE_HANDLE_CACHING_LE &&
+                                               !lease->is_dir)
                                        lease->new_state =
                                                SMB2_LEASE_READ_CACHING_LE;
                                else
@@ -1032,6 +1035,7 @@ static void copy_lease(struct oplock_info *op1, struct oplock_info *op2)
               SMB2_LEASE_KEY_SIZE);
        lease2->duration = lease1->duration;
        lease2->flags = lease1->flags;
+       lease2->epoch = lease1->epoch++;
 }
 
 static int add_lease_global_list(struct oplock_info *opinfo)
@@ -1081,6 +1085,89 @@ static void set_oplock_level(struct oplock_info *opinfo, int level,
        }
 }
 
+void smb_send_parent_lease_break_noti(struct ksmbd_file *fp,
+                                     struct lease_ctx_info *lctx)
+{
+       struct oplock_info *opinfo;
+       struct ksmbd_inode *p_ci = NULL;
+
+       if (lctx->version != 2)
+               return;
+
+       p_ci = ksmbd_inode_lookup_lock(fp->filp->f_path.dentry->d_parent);
+       if (!p_ci)
+               return;
+
+       read_lock(&p_ci->m_lock);
+       list_for_each_entry(opinfo, &p_ci->m_op_list, op_entry) {
+               if (!opinfo->is_lease)
+                       continue;
+
+               if (opinfo->o_lease->state != SMB2_OPLOCK_LEVEL_NONE &&
+                   (!(lctx->flags & SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE) ||
+                    !compare_guid_key(opinfo, fp->conn->ClientGUID,
+                                     lctx->parent_lease_key))) {
+                       if (!atomic_inc_not_zero(&opinfo->refcount))
+                               continue;
+
+                       atomic_inc(&opinfo->conn->r_count);
+                       if (ksmbd_conn_releasing(opinfo->conn)) {
+                               atomic_dec(&opinfo->conn->r_count);
+                               continue;
+                       }
+
+                       read_unlock(&p_ci->m_lock);
+                       oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE);
+                       opinfo_conn_put(opinfo);
+                       read_lock(&p_ci->m_lock);
+               }
+       }
+       read_unlock(&p_ci->m_lock);
+
+       ksmbd_inode_put(p_ci);
+}
+
+void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp)
+{
+       struct oplock_info *opinfo;
+       struct ksmbd_inode *p_ci = NULL;
+
+       rcu_read_lock();
+       opinfo = rcu_dereference(fp->f_opinfo);
+       rcu_read_unlock();
+
+       if (!opinfo->is_lease || opinfo->o_lease->version != 2)
+               return;
+
+       p_ci = ksmbd_inode_lookup_lock(fp->filp->f_path.dentry->d_parent);
+       if (!p_ci)
+               return;
+
+       read_lock(&p_ci->m_lock);
+       list_for_each_entry(opinfo, &p_ci->m_op_list, op_entry) {
+               if (!opinfo->is_lease)
+                       continue;
+
+               if (opinfo->o_lease->state != SMB2_OPLOCK_LEVEL_NONE) {
+                       if (!atomic_inc_not_zero(&opinfo->refcount))
+                               continue;
+
+                       atomic_inc(&opinfo->conn->r_count);
+                       if (ksmbd_conn_releasing(opinfo->conn)) {
+                               atomic_dec(&opinfo->conn->r_count);
+                               continue;
+                       }
+                       read_unlock(&p_ci->m_lock);
+                       oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE);
+                       opinfo_conn_put(opinfo);
+                       read_lock(&p_ci->m_lock);
+               }
+       }
+       read_unlock(&p_ci->m_lock);
+
+       ksmbd_inode_put(p_ci);
+}
+
 /**
  * smb_grant_oplock() - handle oplock/lease request on file open
  * @work:              smb work
@@ -1104,10 +1191,6 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
        bool prev_op_has_lease;
        __le32 prev_op_state = 0;
 
-       /* not support directory lease */
-       if (S_ISDIR(file_inode(fp->filp)->i_mode))
-               return 0;
-
        opinfo = alloc_opinfo(work, pid, tid);
        if (!opinfo)
                return -ENOMEM;
@@ -1364,6 +1447,7 @@ void create_lease_buf(u8 *rbuf, struct lease *lease)
                memcpy(buf->lcontext.LeaseKey, lease->lease_key,
                       SMB2_LEASE_KEY_SIZE);
                buf->lcontext.LeaseFlags = lease->flags;
+               buf->lcontext.Epoch = cpu_to_le16(++lease->epoch);
                buf->lcontext.LeaseState = lease->state;
                memcpy(buf->lcontext.ParentLeaseKey, lease->parent_lease_key,
                       SMB2_LEASE_KEY_SIZE);
@@ -1400,10 +1484,11 @@ void create_lease_buf(u8 *rbuf, struct lease *lease)
 /**
  * parse_lease_state() - parse lease context containted in file open request
  * @open_req:  buffer containing smb2 file open(create) request
+ * @is_dir:    whether leasing file is directory
  *
  * Return:  oplock state, -ENOENT if create lease context not found
  */
-struct lease_ctx_info *parse_lease_state(void *open_req)
+struct lease_ctx_info *parse_lease_state(void *open_req, bool is_dir)
 {
        struct create_context *cc;
        struct smb2_create_req *req = (struct smb2_create_req *)open_req;
@@ -1421,8 +1506,14 @@ struct lease_ctx_info *parse_lease_state(void *open_req)
                struct create_lease_v2 *lc = (struct create_lease_v2 *)cc;
 
                memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
-               lreq->req_state = lc->lcontext.LeaseState;
+               if (is_dir) {
+                       lreq->req_state = lc->lcontext.LeaseState &
+                               ~SMB2_LEASE_WRITE_CACHING_LE;
+                       lreq->is_dir = true;
+               } else
+                       lreq->req_state = lc->lcontext.LeaseState;
                lreq->flags = lc->lcontext.LeaseFlags;
+               lreq->epoch = lc->lcontext.Epoch;
                lreq->duration = lc->lcontext.LeaseDuration;
                memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey,
                                SMB2_LEASE_KEY_SIZE);
index 4b0fe6da76940f54a915cb4bd20d3ce67539bd3e..5b93ea9196c013d0b757add55db43c143cd9706b 100644 (file)
@@ -34,7 +34,9 @@ struct lease_ctx_info {
        __le32                  flags;
        __le64                  duration;
        __u8                    parent_lease_key[SMB2_LEASE_KEY_SIZE];
+       __le16                  epoch;
        int                     version;
+       bool                    is_dir;
 };
 
 struct lease_table {
@@ -53,6 +55,7 @@ struct lease {
        __u8                    parent_lease_key[SMB2_LEASE_KEY_SIZE];
        int                     version;
        unsigned short          epoch;
+       bool                    is_dir;
        struct lease_table      *l_lb;
 };
 
@@ -108,7 +111,7 @@ void opinfo_put(struct oplock_info *opinfo);
 
 /* Lease related functions */
 void create_lease_buf(u8 *rbuf, struct lease *lease);
-struct lease_ctx_info *parse_lease_state(void *open_req);
+struct lease_ctx_info *parse_lease_state(void *open_req, bool is_dir);
 __u8 smb2_map_lease_to_oplock(__le32 lease_state);
 int lease_read_to_write(struct oplock_info *opinfo);
 
@@ -124,4 +127,7 @@ struct oplock_info *lookup_lease_in_table(struct ksmbd_conn *conn,
 int find_same_lease_key(struct ksmbd_session *sess, struct ksmbd_inode *ci,
                        struct lease_ctx_info *lctx);
 void destroy_lease_table(struct ksmbd_conn *conn);
+void smb_send_parent_lease_break_noti(struct ksmbd_file *fp,
+                                     struct lease_ctx_info *lctx);
+void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp);
 #endif /* __KSMBD_OPLOCK_H */
index aed7704a0672864609f6a9ab313efeca0cba9be0..27a9dce3e03abe4673ac7241aa828943d22754d8 100644 (file)
@@ -221,7 +221,8 @@ void init_smb3_0_server(struct ksmbd_conn *conn)
        conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE;
 
        if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
-               conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
+               conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING |
+                       SMB2_GLOBAL_CAP_DIRECTORY_LEASING;
 
        if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION &&
            conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION)
@@ -245,7 +246,8 @@ void init_smb3_02_server(struct ksmbd_conn *conn)
        conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE;
 
        if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
-               conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
+               conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING |
+                       SMB2_GLOBAL_CAP_DIRECTORY_LEASING;
 
        if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION ||
            (!(server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION_OFF) &&
@@ -270,7 +272,8 @@ int init_smb3_11_server(struct ksmbd_conn *conn)
        conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE;
 
        if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
-               conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
+               conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING |
+                       SMB2_GLOBAL_CAP_DIRECTORY_LEASING;
 
        if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION ||
            (!(server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION_OFF) &&
index d369b98a6e10373bbc331beba1daa4414db619a9..652ab429bf2e9cd945a772c6cddac46012fadf00 100644 (file)
@@ -2516,7 +2516,7 @@ static void smb2_new_xattrs(struct ksmbd_tree_connect *tcon, const struct path *
        da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME |
                XATTR_DOSINFO_ITIME;
 
-       rc = ksmbd_vfs_set_dos_attrib_xattr(mnt_idmap(path->mnt), path, &da, false);
+       rc = ksmbd_vfs_set_dos_attrib_xattr(mnt_idmap(path->mnt), path, &da, true);
        if (rc)
                ksmbd_debug(SMB, "failed to store file attribute into xattr\n");
 }
@@ -2732,10 +2732,6 @@ int smb2_open(struct ksmbd_work *work)
                }
        }
 
-       req_op_level = req->RequestedOplockLevel;
-       if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE)
-               lc = parse_lease_state(req);
-
        if (le32_to_cpu(req->ImpersonationLevel) > le32_to_cpu(IL_DELEGATE)) {
                pr_err("Invalid impersonationlevel : 0x%x\n",
                       le32_to_cpu(req->ImpersonationLevel));
@@ -3189,23 +3185,6 @@ int smb2_open(struct ksmbd_work *work)
                goto err_out;
        }
 
-       rc = ksmbd_vfs_getattr(&path, &stat);
-       if (rc)
-               goto err_out;
-
-       if (stat.result_mask & STATX_BTIME)
-               fp->create_time = ksmbd_UnixTimeToNT(stat.btime);
-       else
-               fp->create_time = ksmbd_UnixTimeToNT(stat.ctime);
-       if (req->FileAttributes || fp->f_ci->m_fattr == 0)
-               fp->f_ci->m_fattr =
-                       cpu_to_le32(smb2_get_dos_mode(&stat, le32_to_cpu(req->FileAttributes)));
-
-       if (!created)
-               smb2_update_xattrs(tcon, &path, fp);
-       else
-               smb2_new_xattrs(tcon, &path, fp);
-
        if (file_present || created)
                ksmbd_vfs_kern_path_unlock(&parent_path, &path);
 
@@ -3215,6 +3194,10 @@ int smb2_open(struct ksmbd_work *work)
                need_truncate = 1;
        }
 
+       req_op_level = req->RequestedOplockLevel;
+       if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE)
+               lc = parse_lease_state(req, S_ISDIR(file_inode(filp)->i_mode));
+
        share_ret = ksmbd_smb_check_shared_mode(fp->filp, fp);
        if (!test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_OPLOCKS) ||
            (req_op_level == SMB2_OPLOCK_LEVEL_LEASE &&
@@ -3225,6 +3208,13 @@ int smb2_open(struct ksmbd_work *work)
                }
        } else {
                if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE) {
+                       /*
+                        * Compare parent lease using parent key. If there is no
+                        * a lease that has same parent key, Send lease break
+                        * notification.
+                        */
+                       smb_send_parent_lease_break_noti(fp, lc);
+
                        req_op_level = smb2_map_lease_to_oplock(lc->req_state);
                        ksmbd_debug(SMB,
                                    "lease req for(%s) req oplock state 0x%x, lease state 0x%x\n",
@@ -3295,6 +3285,23 @@ int smb2_open(struct ksmbd_work *work)
                }
        }
 
+       rc = ksmbd_vfs_getattr(&path, &stat);
+       if (rc)
+               goto err_out1;
+
+       if (stat.result_mask & STATX_BTIME)
+               fp->create_time = ksmbd_UnixTimeToNT(stat.btime);
+       else
+               fp->create_time = ksmbd_UnixTimeToNT(stat.ctime);
+       if (req->FileAttributes || fp->f_ci->m_fattr == 0)
+               fp->f_ci->m_fattr =
+                       cpu_to_le32(smb2_get_dos_mode(&stat, le32_to_cpu(req->FileAttributes)));
+
+       if (!created)
+               smb2_update_xattrs(tcon, &path, fp);
+       else
+               smb2_new_xattrs(tcon, &path, fp);
+
        memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE);
 
        rsp->StructureSize = cpu_to_le16(89);
@@ -7080,6 +7087,7 @@ skip:
                                                      smb2_remove_blocked_lock,
                                                      argv);
                                if (rc) {
+                                       kfree(argv);
                                        err = -ENOMEM;
                                        goto out;
                                }
@@ -8211,6 +8219,11 @@ static void smb21_lease_break_ack(struct ksmbd_work *work)
                            le32_to_cpu(req->LeaseState));
        }
 
+       if (ret < 0) {
+               rsp->hdr.Status = err;
+               goto err_out;
+       }
+
        lease_state = lease->state;
        opinfo->op_state = OPLOCK_STATE_NONE;
        wake_up_interruptible_all(&opinfo->oplock_q);
@@ -8218,11 +8231,6 @@ static void smb21_lease_break_ack(struct ksmbd_work *work)
        wake_up_interruptible_all(&opinfo->oplock_brk);
        opinfo_put(opinfo);
 
-       if (ret < 0) {
-               rsp->hdr.Status = err;
-               goto err_out;
-       }
-
        rsp->StructureSize = cpu_to_le16(36);
        rsp->Reserved = 0;
        rsp->Flags = 0;
index 9091dcd7a3102c82a24d04948847ed5edbb67d45..4277750a6da1b16e6e6f19d29f157f31124cff3b 100644 (file)
@@ -517,6 +517,9 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp,
                }
        }
 
+       /* Reserve lease break for parent dir at closing time */
+       fp->reserve_lease_break = true;
+
        /* Do we need to break any of a levelII oplock? */
        smb_break_all_levII_oplock(work, fp, 1);
 
index ddf233994ddbbf37c1657b925961a7f8be94f4f0..4e82ff627d1224d7972534a1233b0f952e94f9e4 100644 (file)
@@ -87,6 +87,17 @@ static struct ksmbd_inode *ksmbd_inode_lookup(struct ksmbd_file *fp)
        return __ksmbd_inode_lookup(fp->filp->f_path.dentry);
 }
 
+struct ksmbd_inode *ksmbd_inode_lookup_lock(struct dentry *d)
+{
+       struct ksmbd_inode *ci;
+
+       read_lock(&inode_hash_lock);
+       ci = __ksmbd_inode_lookup(d);
+       read_unlock(&inode_hash_lock);
+
+       return ci;
+}
+
 int ksmbd_query_inode_status(struct dentry *dentry)
 {
        struct ksmbd_inode *ci;
@@ -199,7 +210,7 @@ static void ksmbd_inode_free(struct ksmbd_inode *ci)
        kfree(ci);
 }
 
-static void ksmbd_inode_put(struct ksmbd_inode *ci)
+void ksmbd_inode_put(struct ksmbd_inode *ci)
 {
        if (atomic_dec_and_test(&ci->m_count))
                ksmbd_inode_free(ci);
index 8325cf4527c464c7db83b772e145f01849814faf..a528f0cc775ae0b6c60e05dfef3c2484fa92af3c 100644 (file)
@@ -105,6 +105,7 @@ struct ksmbd_file {
        struct ksmbd_readdir_data       readdir_data;
        int                             dot_dotdot[2];
        unsigned int                    f_state;
+       bool                            reserve_lease_break;
 };
 
 static inline void set_ctx_actor(struct dir_context *ctx,
@@ -138,6 +139,8 @@ struct ksmbd_file *ksmbd_lookup_foreign_fd(struct ksmbd_work *work, u64 id);
 struct ksmbd_file *ksmbd_lookup_fd_slow(struct ksmbd_work *work, u64 id,
                                        u64 pid);
 void ksmbd_fd_put(struct ksmbd_work *work, struct ksmbd_file *fp);
+struct ksmbd_inode *ksmbd_inode_lookup_lock(struct dentry *d);
+void ksmbd_inode_put(struct ksmbd_inode *ci);
 struct ksmbd_file *ksmbd_lookup_durable_fd(unsigned long long id);
 struct ksmbd_file *ksmbd_lookup_fd_cguid(char *cguid);
 struct ksmbd_file *ksmbd_lookup_fd_inode(struct dentry *dentry);
index 0b90869fd805cd62ab6db7cf924ee0cad8c86eaf..43e237864a422b6df5e85a0119008b4c154566bf 100644 (file)
@@ -546,6 +546,8 @@ static struct dentry *eventfs_root_lookup(struct inode *dir,
                if (strcmp(ei_child->name, name) != 0)
                        continue;
                ret = simple_lookup(dir, dentry, flags);
+               if (IS_ERR(ret))
+                       goto out;
                create_dir_dentry(ei, ei_child, ei_dentry, true);
                created = true;
                break;
@@ -568,6 +570,8 @@ static struct dentry *eventfs_root_lookup(struct inode *dir,
                        if (r <= 0)
                                continue;
                        ret = simple_lookup(dir, dentry, flags);
+                       if (IS_ERR(ret))
+                               goto out;
                        create_file_dentry(ei, i, ei_dentry, name, mode, cdata,
                                           fops, true);
                        break;
index 13ba34e6d64ff30f51de4367f3aa08f12796786e..2acf191eb89ede0a7df7d667e948f74228cc2ac6 100644 (file)
@@ -245,7 +245,7 @@ struct folio *ufs_get_locked_folio(struct address_space *mapping,
 {
        struct inode *inode = mapping->host;
        struct folio *folio = filemap_lock_folio(mapping, index);
-       if (!folio) {
+       if (IS_ERR(folio)) {
                folio = read_mapping_folio(mapping, index, NULL);
 
                if (IS_ERR(folio)) {
index af8d353a4b86af3d4e571301238a4e6aa20b78f9..2976f534a7a32f050410125df97e9880cc429296 100644 (file)
@@ -109,14 +109,7 @@ static inline int groups_search(const struct group_info *group_info, kgid_t grp)
  * same context as task->real_cred.
  */
 struct cred {
-       atomic_t        usage;
-#ifdef CONFIG_DEBUG_CREDENTIALS
-       atomic_t        subscribers;    /* number of processes subscribed */
-       void            *put_addr;
-       unsigned        magic;
-#define CRED_MAGIC     0x43736564
-#define CRED_MAGIC_DEAD        0x44656144
-#endif
+       atomic_long_t   usage;
        kuid_t          uid;            /* real UID of the task */
        kgid_t          gid;            /* real GID of the task */
        kuid_t          suid;           /* saved UID of the task */
@@ -172,46 +165,6 @@ extern int cred_fscmp(const struct cred *, const struct cred *);
 extern void __init cred_init(void);
 extern int set_cred_ucounts(struct cred *);
 
-/*
- * check for validity of credentials
- */
-#ifdef CONFIG_DEBUG_CREDENTIALS
-extern void __noreturn __invalid_creds(const struct cred *, const char *, unsigned);
-extern void __validate_process_creds(struct task_struct *,
-                                    const char *, unsigned);
-
-extern bool creds_are_invalid(const struct cred *cred);
-
-static inline void __validate_creds(const struct cred *cred,
-                                   const char *file, unsigned line)
-{
-       if (unlikely(creds_are_invalid(cred)))
-               __invalid_creds(cred, file, line);
-}
-
-#define validate_creds(cred)                           \
-do {                                                   \
-       __validate_creds((cred), __FILE__, __LINE__);   \
-} while(0)
-
-#define validate_process_creds()                               \
-do {                                                           \
-       __validate_process_creds(current, __FILE__, __LINE__);  \
-} while(0)
-
-extern void validate_creds_for_do_exit(struct task_struct *);
-#else
-static inline void validate_creds(const struct cred *cred)
-{
-}
-static inline void validate_creds_for_do_exit(struct task_struct *tsk)
-{
-}
-static inline void validate_process_creds(void)
-{
-}
-#endif
-
 static inline bool cap_ambient_invariant_ok(const struct cred *cred)
 {
        return cap_issubset(cred->cap_ambient,
@@ -229,7 +182,7 @@ static inline bool cap_ambient_invariant_ok(const struct cred *cred)
  */
 static inline struct cred *get_new_cred_many(struct cred *cred, int nr)
 {
-       atomic_add(nr, &cred->usage);
+       atomic_long_add(nr, &cred->usage);
        return cred;
 }
 
@@ -264,7 +217,6 @@ static inline const struct cred *get_cred_many(const struct cred *cred, int nr)
        struct cred *nonconst_cred = (struct cred *) cred;
        if (!cred)
                return cred;
-       validate_creds(cred);
        nonconst_cred->non_rcu = 0;
        return get_new_cred_many(nonconst_cred, nr);
 }
@@ -288,9 +240,8 @@ static inline const struct cred *get_cred_rcu(const struct cred *cred)
        struct cred *nonconst_cred = (struct cred *) cred;
        if (!cred)
                return NULL;
-       if (!atomic_inc_not_zero(&nonconst_cred->usage))
+       if (!atomic_long_inc_not_zero(&nonconst_cred->usage))
                return NULL;
-       validate_creds(cred);
        nonconst_cred->non_rcu = 0;
        return cred;
 }
@@ -312,8 +263,7 @@ static inline void put_cred_many(const struct cred *_cred, int nr)
        struct cred *cred = (struct cred *) _cred;
 
        if (cred) {
-               validate_creds(cred);
-               if (atomic_sub_and_test(nr, &cred->usage))
+               if (atomic_long_sub_and_test(nr, &cred->usage))
                        __put_cred(cred);
        }
 }
index ab2f17d9926b599c2457f6e3dc834d12b6d8e7dc..e00ddf1ed39c05c945c0f31703d52f77881d615d 100644 (file)
@@ -559,6 +559,8 @@ struct damon_ctx {
         * update
         */
        unsigned long next_ops_update_sis;
+       /* for waiting until the execution of the kdamond_fn is started */
+       struct completion kdamond_started;
 
 /* public: */
        struct task_struct *kdamond;
index 805bb635cdf55805171c20f66312663a6d84fe8e..239a4f68801bb59812c33b80d88958065bf124a3 100644 (file)
@@ -434,6 +434,7 @@ enum {
        /* keep async read/write and isreg together and in order */
        REQ_F_SUPPORT_NOWAIT_BIT,
        REQ_F_ISREG_BIT,
+       REQ_F_POLL_NO_LAZY_BIT,
 
        /* not a real bit, just to check we're not overflowing the space */
        __REQ_F_LAST_BIT,
@@ -501,6 +502,8 @@ enum {
        REQ_F_CLEAR_POLLIN      = BIT(REQ_F_CLEAR_POLLIN_BIT),
        /* hashed into ->cancel_hash_locked, protected by ->uring_lock */
        REQ_F_HASH_LOCKED       = BIT(REQ_F_HASH_LOCKED_BIT),
+       /* don't use lazy poll wake for this request */
+       REQ_F_POLL_NO_LAZY      = BIT(REQ_F_POLL_NO_LAZY_BIT),
 };
 
 typedef void (*io_req_tw_func_t)(struct io_kiocb *req, struct io_tw_state *ts);
index 6dcbb4eb80fb2085c578ef4c8fd40bfeba9d6db3..beb30719ee161bad0e01db32edfd14e610a6634c 100644 (file)
@@ -1374,6 +1374,9 @@ JBD2_FEATURE_INCOMPAT_FUNCS(csum2,                CSUM_V2)
 JBD2_FEATURE_INCOMPAT_FUNCS(csum3,             CSUM_V3)
 JBD2_FEATURE_INCOMPAT_FUNCS(fast_commit,       FAST_COMMIT)
 
+/* Journal high priority write IO operation flags */
+#define JBD2_JOURNAL_REQ_FLAGS         (REQ_META | REQ_SYNC | REQ_IDLE)
+
 /*
  * Journal flag definitions
  */
index 6f3631425f386dad40e847aa592a31e12d1b5e9f..3f7b664d625b94e35539d1184bd2b5fcf109c4b1 100644 (file)
@@ -621,7 +621,7 @@ struct mlx5_ifc_fte_match_set_misc_bits {
 
        u8         reserved_at_140[0x8];
        u8         bth_dst_qp[0x18];
-       u8         reserved_at_160[0x20];
+       u8         inner_esp_spi[0x20];
        u8         outer_esp_spi[0x20];
        u8         reserved_at_1a0[0x60];
 };
@@ -12001,6 +12001,13 @@ enum {
        MLX5_IPSEC_ASO_INC_SN            = 0x2,
 };
 
+enum {
+       MLX5_IPSEC_ASO_REPLAY_WIN_32BIT  = 0x0,
+       MLX5_IPSEC_ASO_REPLAY_WIN_64BIT  = 0x1,
+       MLX5_IPSEC_ASO_REPLAY_WIN_128BIT = 0x2,
+       MLX5_IPSEC_ASO_REPLAY_WIN_256BIT = 0x3,
+};
+
 struct mlx5_ifc_ipsec_aso_bits {
        u8         valid[0x1];
        u8         reserved_at_201[0x1];
index 418d26608ece70d12a5608dff42f0f4d04af5aea..da5219b48d52294a4442a27ea1f1a80b41e3e555 100644 (file)
@@ -886,8 +886,8 @@ static inline bool vma_is_anonymous(struct vm_area_struct *vma)
  */
 static inline bool vma_is_initial_heap(const struct vm_area_struct *vma)
 {
-       return vma->vm_start <= vma->vm_mm->brk &&
-               vma->vm_end >= vma->vm_mm->start_brk;
+       return vma->vm_start < vma->vm_mm->brk &&
+               vma->vm_end > vma->vm_mm->start_brk;
 }
 
 /*
@@ -901,8 +901,8 @@ static inline bool vma_is_initial_stack(const struct vm_area_struct *vma)
         * its "stack".  It's not even well-defined for programs written
         * languages like Go.
         */
-       return vma->vm_start <= vma->vm_mm->start_stack &&
-              vma->vm_end >= vma->vm_mm->start_stack;
+       return vma->vm_start <= vma->vm_mm->start_stack &&
+               vma->vm_end >= vma->vm_mm->start_stack;
 }
 
 static inline bool vma_is_temporary_stack(struct vm_area_struct *vma)
index 9ae7def16cb2a9dd14f653eb78eefd753ce5c0c0..f4fe593c1400e662add6d60baa0cd794e78a172b 100644 (file)
@@ -232,22 +232,27 @@ static inline bool lru_gen_add_folio(struct lruvec *lruvec, struct folio *folio,
        if (folio_test_unevictable(folio) || !lrugen->enabled)
                return false;
        /*
-        * There are three common cases for this page:
-        * 1. If it's hot, e.g., freshly faulted in or previously hot and
-        *    migrated, add it to the youngest generation.
-        * 2. If it's cold but can't be evicted immediately, i.e., an anon page
-        *    not in swapcache or a dirty page pending writeback, add it to the
-        *    second oldest generation.
-        * 3. Everything else (clean, cold) is added to the oldest generation.
+        * There are four common cases for this page:
+        * 1. If it's hot, i.e., freshly faulted in, add it to the youngest
+        *    generation, and it's protected over the rest below.
+        * 2. If it can't be evicted immediately, i.e., a dirty page pending
+        *    writeback, add it to the second youngest generation.
+        * 3. If it should be evicted first, e.g., cold and clean from
+        *    folio_rotate_reclaimable(), add it to the oldest generation.
+        * 4. Everything else falls between 2 & 3 above and is added to the
+        *    second oldest generation if it's considered inactive, or the
+        *    oldest generation otherwise. See lru_gen_is_active().
         */
        if (folio_test_active(folio))
                seq = lrugen->max_seq;
        else if ((type == LRU_GEN_ANON && !folio_test_swapcache(folio)) ||
                 (folio_test_reclaim(folio) &&
                  (folio_test_dirty(folio) || folio_test_writeback(folio))))
-               seq = lrugen->min_seq[type] + 1;
-       else
+               seq = lrugen->max_seq - 1;
+       else if (reclaiming || lrugen->min_seq[type] + MIN_NR_GENS >= lrugen->max_seq)
                seq = lrugen->min_seq[type];
+       else
+               seq = lrugen->min_seq[type] + 1;
 
        gen = lru_gen_from_seq(seq);
        flags = (gen + 1UL) << LRU_GEN_PGOFF;
index 3c25226beeed4731616f640a4b9d9d5ae05f0054..9db36e1977125b91de428c32eeec1d842d80a695 100644 (file)
@@ -505,33 +505,37 @@ void lru_gen_look_around(struct page_vma_mapped_walk *pvmw);
  * the old generation, is incremented when all its bins become empty.
  *
  * There are four operations:
- * 1. MEMCG_LRU_HEAD, which moves an memcg to the head of a random bin in its
+ * 1. MEMCG_LRU_HEAD, which moves a memcg to the head of a random bin in its
  *    current generation (old or young) and updates its "seg" to "head";
- * 2. MEMCG_LRU_TAIL, which moves an memcg to the tail of a random bin in its
+ * 2. MEMCG_LRU_TAIL, which moves a memcg to the tail of a random bin in its
  *    current generation (old or young) and updates its "seg" to "tail";
- * 3. MEMCG_LRU_OLD, which moves an memcg to the head of a random bin in the old
+ * 3. MEMCG_LRU_OLD, which moves a memcg to the head of a random bin in the old
  *    generation, updates its "gen" to "old" and resets its "seg" to "default";
- * 4. MEMCG_LRU_YOUNG, which moves an memcg to the tail of a random bin in the
+ * 4. MEMCG_LRU_YOUNG, which moves a memcg to the tail of a random bin in the
  *    young generation, updates its "gen" to "young" and resets its "seg" to
  *    "default".
  *
  * The events that trigger the above operations are:
  * 1. Exceeding the soft limit, which triggers MEMCG_LRU_HEAD;
- * 2. The first attempt to reclaim an memcg below low, which triggers
+ * 2. The first attempt to reclaim a memcg below low, which triggers
  *    MEMCG_LRU_TAIL;
- * 3. The first attempt to reclaim an memcg below reclaimable size threshold,
- *    which triggers MEMCG_LRU_TAIL;
- * 4. The second attempt to reclaim an memcg below reclaimable size threshold,
- *    which triggers MEMCG_LRU_YOUNG;
- * 5. Attempting to reclaim an memcg below min, which triggers MEMCG_LRU_YOUNG;
+ * 3. The first attempt to reclaim a memcg offlined or below reclaimable size
+ *    threshold, which triggers MEMCG_LRU_TAIL;
+ * 4. The second attempt to reclaim a memcg offlined or below reclaimable size
+ *    threshold, which triggers MEMCG_LRU_YOUNG;
+ * 5. Attempting to reclaim a memcg below min, which triggers MEMCG_LRU_YOUNG;
  * 6. Finishing the aging on the eviction path, which triggers MEMCG_LRU_YOUNG;
- * 7. Offlining an memcg, which triggers MEMCG_LRU_OLD.
+ * 7. Offlining a memcg, which triggers MEMCG_LRU_OLD.
  *
- * Note that memcg LRU only applies to global reclaim, and the round-robin
- * incrementing of their max_seq counters ensures the eventual fairness to all
- * eligible memcgs. For memcg reclaim, it still relies on mem_cgroup_iter().
+ * Notes:
+ * 1. Memcg LRU only applies to global reclaim, and the round-robin incrementing
+ *    of their max_seq counters ensures the eventual fairness to all eligible
+ *    memcgs. For memcg reclaim, it still relies on mem_cgroup_iter().
+ * 2. There are only two valid generations: old (seq) and young (seq+1).
+ *    MEMCG_NR_GENS is set to three so that when reading the generation counter
+ *    locklessly, a stale value (seq-1) does not wraparound to young.
  */
-#define MEMCG_NR_GENS  2
+#define MEMCG_NR_GENS  3
 #define MEMCG_NR_BINS  8
 
 struct lru_gen_memcg {
index 60ca768bc8679f4ff135f2d0364e46b5e7ab4fb9..dea043bc1e383acc4c18e83d506d1ffe5c489448 100644 (file)
@@ -1829,6 +1829,7 @@ extern bool pcie_ports_native;
 int pci_disable_link_state(struct pci_dev *pdev, int state);
 int pci_disable_link_state_locked(struct pci_dev *pdev, int state);
 int pci_enable_link_state(struct pci_dev *pdev, int state);
+int pci_enable_link_state_locked(struct pci_dev *pdev, int state);
 void pcie_no_aspm(void);
 bool pcie_aspm_support_enabled(void);
 bool pcie_aspm_enabled(struct pci_dev *pdev);
@@ -1839,6 +1840,8 @@ static inline int pci_disable_link_state_locked(struct pci_dev *pdev, int state)
 { return 0; }
 static inline int pci_enable_link_state(struct pci_dev *pdev, int state)
 { return 0; }
+static inline int pci_enable_link_state_locked(struct pci_dev *pdev, int state)
+{ return 0; }
 static inline void pcie_no_aspm(void) { }
 static inline bool pcie_aspm_support_enabled(void) { return false; }
 static inline bool pcie_aspm_enabled(struct pci_dev *pdev) { return false; }
index 82da55101b5a30b2a5512d964429d2c5f73d03fd..61ebe723ee4d5078afdeec1ec70d392d0ef54ec4 100644 (file)
@@ -31,17 +31,22 @@ struct prefix_info {
        __u8                    length;
        __u8                    prefix_len;
 
+       union __packed {
+               __u8            flags;
+               struct __packed {
 #if defined(__BIG_ENDIAN_BITFIELD)
-       __u8                    onlink : 1,
+                       __u8    onlink : 1,
                                autoconf : 1,
                                reserved : 6;
 #elif defined(__LITTLE_ENDIAN_BITFIELD)
-       __u8                    reserved : 6,
+                       __u8    reserved : 6,
                                autoconf : 1,
                                onlink : 1;
 #else
 #error "Please fix <asm/byteorder.h>"
 #endif
+               };
+       };
        __be32                  valid;
        __be32                  prefered;
        __be32                  reserved2;
@@ -49,6 +54,9 @@ struct prefix_info {
        struct in6_addr         prefix;
 };
 
+/* rfc4861 4.6.2: IPv6 PIO is 32 bytes in size */
+static_assert(sizeof(struct prefix_info) == 32);
+
 #include <linux/ipv6.h>
 #include <linux/netdevice.h>
 #include <net/if_inet6.h>
index 3e454c4d7ba623d6abcfcfb396c0f4390de84c5a..f07642264c1eb622e57b9ce0715e296360a4db6e 100644 (file)
 #define IF_RS_SENT     0x10
 #define IF_READY       0x80000000
 
-/* prefix flags */
-#define IF_PREFIX_ONLINK       0x01
-#define IF_PREFIX_AUTOCONF     0x02
-
 enum {
        INET6_IFADDR_STATE_PREDAD,
        INET6_IFADDR_STATE_DAD,
index fe1507c1db828b14e6d684f1f1bca514dbb4103d..692d5955911c7dbf967110be2dd98e62c75f20af 100644 (file)
@@ -62,6 +62,8 @@ struct nf_flowtable_type {
                                                  enum flow_offload_tuple_dir dir,
                                                  struct nf_flow_rule *flow_rule);
        void                            (*free)(struct nf_flowtable *ft);
+       void                            (*get)(struct nf_flowtable *ft);
+       void                            (*put)(struct nf_flowtable *ft);
        nf_hookfn                       *hook;
        struct module                   *owner;
 };
@@ -240,6 +242,11 @@ nf_flow_table_offload_add_cb(struct nf_flowtable *flow_table,
        }
 
        list_add_tail(&block_cb->list, &block->cb_list);
+       up_write(&flow_table->flow_block_lock);
+
+       if (flow_table->type->get)
+               flow_table->type->get(flow_table);
+       return 0;
 
 unlock:
        up_write(&flow_table->flow_block_lock);
@@ -262,6 +269,9 @@ nf_flow_table_offload_del_cb(struct nf_flowtable *flow_table,
                WARN_ON(true);
        }
        up_write(&flow_table->flow_block_lock);
+
+       if (flow_table->type->put)
+               flow_table->type->put(flow_table);
 }
 
 void flow_offload_route_init(struct flow_offload *flow,
index db92a7202b342b3a1df3f7583c86b79f3ad4e3df..e7418d15fe3906507827025545dcd5348202ff30 100644 (file)
  *  - add FUSE_HAS_EXPIRE_ONLY
  *
  *  7.39
- *  - add FUSE_DIRECT_IO_RELAX
+ *  - add FUSE_DIRECT_IO_ALLOW_MMAP
  *  - add FUSE_STATX and related structures
  */
 
@@ -409,8 +409,7 @@ struct fuse_file_lock {
  * FUSE_CREATE_SUPP_GROUP: add supplementary group info to create, mkdir,
  *                     symlink and mknod (single group that matches parent)
  * FUSE_HAS_EXPIRE_ONLY: kernel supports expiry-only entry invalidation
- * FUSE_DIRECT_IO_RELAX: relax restrictions in FOPEN_DIRECT_IO mode, for now
- *                       allow shared mmap
+ * FUSE_DIRECT_IO_ALLOW_MMAP: allow shared mmap in FOPEN_DIRECT_IO mode.
  */
 #define FUSE_ASYNC_READ                (1 << 0)
 #define FUSE_POSIX_LOCKS       (1 << 1)
@@ -449,7 +448,10 @@ struct fuse_file_lock {
 #define FUSE_HAS_INODE_DAX     (1ULL << 33)
 #define FUSE_CREATE_SUPP_GROUP (1ULL << 34)
 #define FUSE_HAS_EXPIRE_ONLY   (1ULL << 35)
-#define FUSE_DIRECT_IO_RELAX   (1ULL << 36)
+#define FUSE_DIRECT_IO_ALLOW_MMAP (1ULL << 36)
+
+/* Obsolete alias for FUSE_DIRECT_IO_ALLOW_MMAP */
+#define FUSE_DIRECT_IO_RELAX   FUSE_DIRECT_IO_ALLOW_MMAP
 
 /**
  * CUSE INIT request/reply flags
index d38d05edb4fa26c92f46b48bc89d0aa280c568ab..d59b74a99d4e4b444dcb2f86dc9d3594d838e1cf 100644 (file)
@@ -366,11 +366,16 @@ void io_poll_task_func(struct io_kiocb *req, struct io_tw_state *ts)
 
 static void __io_poll_execute(struct io_kiocb *req, int mask)
 {
+       unsigned flags = 0;
+
        io_req_set_res(req, mask, 0);
        req->io_task_work.func = io_poll_task_func;
 
        trace_io_uring_task_add(req, mask);
-       __io_req_task_work_add(req, IOU_F_TWQ_LAZY_WAKE);
+
+       if (!(req->flags & REQ_F_POLL_NO_LAZY))
+               flags = IOU_F_TWQ_LAZY_WAKE;
+       __io_req_task_work_add(req, flags);
 }
 
 static inline void io_poll_execute(struct io_kiocb *req, int res)
@@ -526,10 +531,19 @@ static void __io_queue_proc(struct io_poll *poll, struct io_poll_table *pt,
        poll->head = head;
        poll->wait.private = (void *) wqe_private;
 
-       if (poll->events & EPOLLEXCLUSIVE)
+       if (poll->events & EPOLLEXCLUSIVE) {
+               /*
+                * Exclusive waits may only wake a limited amount of entries
+                * rather than all of them, this may interfere with lazy
+                * wake if someone does wait(events > 1). Ensure we don't do
+                * lazy wake for those, as we need to process each one as they
+                * come in.
+                */
+               req->flags |= REQ_F_POLL_NO_LAZY;
                add_wait_queue_exclusive(head, &poll->wait);
-       else
+       } else {
                add_wait_queue(head, &poll->wait);
+       }
 }
 
 static void io_poll_queue_proc(struct file *file, struct wait_queue_head *head,
index acbc2924ecd211e07c2aec13a96106f0fed63b02..7d3ef62e620a58068a77e0ada254fc7e3e47990d 100644 (file)
@@ -7,7 +7,7 @@
 #include <linux/nospec.h>
 
 #include <uapi/linux/io_uring.h>
-#include <uapi/asm-generic/ioctls.h>
+#include <asm/ioctls.h>
 
 #include "io_uring.h"
 #include "rsrc.h"
index 1cc3b1c595d7f9d4c0530335b7a677a0fcc70c29..2fd510256604e986e88295a8eb5b17f0d2a10073 100644 (file)
@@ -94,7 +94,6 @@ config KEXEC_JUMP
 config CRASH_DUMP
        bool "kernel crash dumps"
        depends on ARCH_SUPPORTS_CRASH_DUMP
-       depends on ARCH_SUPPORTS_KEXEC
        select CRASH_CORE
        select KEXEC_CORE
        help
index efe87d501c8c3c002cbdd6124fc0e3026ad82bd7..d4313b53837e3de5bb42b553152b086b5d0657ef 100644 (file)
@@ -199,7 +199,7 @@ static __initdata char *suffix_tbl[] = {
  * It returns 0 on success and -EINVAL on failure.
  */
 static int __init parse_crashkernel_suffix(char *cmdline,
-                                          unsigned long long   *crash_size,
+                                          unsigned long long *crash_size,
                                           const char *suffix)
 {
        char *cur = cmdline;
@@ -268,9 +268,9 @@ static int __init __parse_crashkernel(char *cmdline,
                             unsigned long long *crash_base,
                             const char *suffix)
 {
-       char    *first_colon, *first_space;
-       char    *ck_cmdline;
-       char    *name = "crashkernel=";
+       char *first_colon, *first_space;
+       char *ck_cmdline;
+       char *name = "crashkernel=";
 
        BUG_ON(!crash_size || !crash_base);
        *crash_size = 0;
@@ -440,7 +440,7 @@ retry:
                return;
        }
 
-       if ((crash_base > CRASH_ADDR_LOW_MAX) &&
+       if ((crash_base >= CRASH_ADDR_LOW_MAX) &&
             crash_low_size && reserve_crashkernel_low(crash_low_size)) {
                memblock_phys_free(crash_base, crash_size);
                return;
index 3c714cb31660d970cb7d19cd25b48161cf50a6df..c033a201c808e59763f36338854b04123e6a5ab9 100644 (file)
@@ -43,10 +43,6 @@ static struct group_info init_groups = { .usage = REFCOUNT_INIT(2) };
  */
 struct cred init_cred = {
        .usage                  = ATOMIC_INIT(4),
-#ifdef CONFIG_DEBUG_CREDENTIALS
-       .subscribers            = ATOMIC_INIT(2),
-       .magic                  = CRED_MAGIC,
-#endif
        .uid                    = GLOBAL_ROOT_UID,
        .gid                    = GLOBAL_ROOT_GID,
        .suid                   = GLOBAL_ROOT_UID,
@@ -66,31 +62,6 @@ struct cred init_cred = {
        .ucounts                = &init_ucounts,
 };
 
-static inline void set_cred_subscribers(struct cred *cred, int n)
-{
-#ifdef CONFIG_DEBUG_CREDENTIALS
-       atomic_set(&cred->subscribers, n);
-#endif
-}
-
-static inline int read_cred_subscribers(const struct cred *cred)
-{
-#ifdef CONFIG_DEBUG_CREDENTIALS
-       return atomic_read(&cred->subscribers);
-#else
-       return 0;
-#endif
-}
-
-static inline void alter_cred_subscribers(const struct cred *_cred, int n)
-{
-#ifdef CONFIG_DEBUG_CREDENTIALS
-       struct cred *cred = (struct cred *) _cred;
-
-       atomic_add(n, &cred->subscribers);
-#endif
-}
-
 /*
  * The RCU callback to actually dispose of a set of credentials
  */
@@ -100,20 +71,9 @@ static void put_cred_rcu(struct rcu_head *rcu)
 
        kdebug("put_cred_rcu(%p)", cred);
 
-#ifdef CONFIG_DEBUG_CREDENTIALS
-       if (cred->magic != CRED_MAGIC_DEAD ||
-           atomic_read(&cred->usage) != 0 ||
-           read_cred_subscribers(cred) != 0)
-               panic("CRED: put_cred_rcu() sees %p with"
-                     " mag %x, put %p, usage %d, subscr %d\n",
-                     cred, cred->magic, cred->put_addr,
-                     atomic_read(&cred->usage),
-                     read_cred_subscribers(cred));
-#else
-       if (atomic_read(&cred->usage) != 0)
-               panic("CRED: put_cred_rcu() sees %p with usage %d\n",
-                     cred, atomic_read(&cred->usage));
-#endif
+       if (atomic_long_read(&cred->usage) != 0)
+               panic("CRED: put_cred_rcu() sees %p with usage %ld\n",
+                     cred, atomic_long_read(&cred->usage));
 
        security_cred_free(cred);
        key_put(cred->session_keyring);
@@ -137,16 +97,10 @@ static void put_cred_rcu(struct rcu_head *rcu)
  */
 void __put_cred(struct cred *cred)
 {
-       kdebug("__put_cred(%p{%d,%d})", cred,
-              atomic_read(&cred->usage),
-              read_cred_subscribers(cred));
-
-       BUG_ON(atomic_read(&cred->usage) != 0);
-#ifdef CONFIG_DEBUG_CREDENTIALS
-       BUG_ON(read_cred_subscribers(cred) != 0);
-       cred->magic = CRED_MAGIC_DEAD;
-       cred->put_addr = __builtin_return_address(0);
-#endif
+       kdebug("__put_cred(%p{%ld})", cred,
+              atomic_long_read(&cred->usage));
+
+       BUG_ON(atomic_long_read(&cred->usage) != 0);
        BUG_ON(cred == current->cred);
        BUG_ON(cred == current->real_cred);
 
@@ -164,9 +118,8 @@ void exit_creds(struct task_struct *tsk)
 {
        struct cred *real_cred, *cred;
 
-       kdebug("exit_creds(%u,%p,%p,{%d,%d})", tsk->pid, tsk->real_cred, tsk->cred,
-              atomic_read(&tsk->cred->usage),
-              read_cred_subscribers(tsk->cred));
+       kdebug("exit_creds(%u,%p,%p,{%ld})", tsk->pid, tsk->real_cred, tsk->cred,
+              atomic_long_read(&tsk->cred->usage));
 
        real_cred = (struct cred *) tsk->real_cred;
        tsk->real_cred = NULL;
@@ -174,15 +127,10 @@ void exit_creds(struct task_struct *tsk)
        cred = (struct cred *) tsk->cred;
        tsk->cred = NULL;
 
-       validate_creds(cred);
        if (real_cred == cred) {
-               alter_cred_subscribers(cred, -2);
                put_cred_many(cred, 2);
        } else {
-               validate_creds(real_cred);
-               alter_cred_subscribers(real_cred, -1);
                put_cred(real_cred);
-               alter_cred_subscribers(cred, -1);
                put_cred(cred);
        }
 
@@ -230,10 +178,7 @@ struct cred *cred_alloc_blank(void)
        if (!new)
                return NULL;
 
-       atomic_set(&new->usage, 1);
-#ifdef CONFIG_DEBUG_CREDENTIALS
-       new->magic = CRED_MAGIC;
-#endif
+       atomic_long_set(&new->usage, 1);
        if (security_cred_alloc_blank(new, GFP_KERNEL_ACCOUNT) < 0)
                goto error;
 
@@ -264,8 +209,6 @@ struct cred *prepare_creds(void)
        const struct cred *old;
        struct cred *new;
 
-       validate_process_creds();
-
        new = kmem_cache_alloc(cred_jar, GFP_KERNEL);
        if (!new)
                return NULL;
@@ -276,8 +219,7 @@ struct cred *prepare_creds(void)
        memcpy(new, old, sizeof(struct cred));
 
        new->non_rcu = 0;
-       atomic_set(&new->usage, 1);
-       set_cred_subscribers(new, 0);
+       atomic_long_set(&new->usage, 1);
        get_group_info(new->group_info);
        get_uid(new->user);
        get_user_ns(new->user_ns);
@@ -300,7 +242,6 @@ struct cred *prepare_creds(void)
        if (security_prepare_creds(new, old, GFP_KERNEL_ACCOUNT) < 0)
                goto error;
 
-       validate_creds(new);
        return new;
 
 error:
@@ -362,10 +303,8 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags)
                clone_flags & CLONE_THREAD
            ) {
                p->real_cred = get_cred_many(p->cred, 2);
-               alter_cred_subscribers(p->cred, 2);
-               kdebug("share_creds(%p{%d,%d})",
-                      p->cred, atomic_read(&p->cred->usage),
-                      read_cred_subscribers(p->cred));
+               kdebug("share_creds(%p{%ld})",
+                      p->cred, atomic_long_read(&p->cred->usage));
                inc_rlimit_ucounts(task_ucounts(p), UCOUNT_RLIMIT_NPROC, 1);
                return 0;
        }
@@ -404,8 +343,6 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags)
 
        p->cred = p->real_cred = get_cred(new);
        inc_rlimit_ucounts(task_ucounts(p), UCOUNT_RLIMIT_NPROC, 1);
-       alter_cred_subscribers(new, 2);
-       validate_creds(new);
        return 0;
 
 error_put:
@@ -457,17 +394,11 @@ int commit_creds(struct cred *new)
        struct task_struct *task = current;
        const struct cred *old = task->real_cred;
 
-       kdebug("commit_creds(%p{%d,%d})", new,
-              atomic_read(&new->usage),
-              read_cred_subscribers(new));
+       kdebug("commit_creds(%p{%ld})", new,
+              atomic_long_read(&new->usage));
 
        BUG_ON(task->cred != old);
-#ifdef CONFIG_DEBUG_CREDENTIALS
-       BUG_ON(read_cred_subscribers(old) < 2);
-       validate_creds(old);
-       validate_creds(new);
-#endif
-       BUG_ON(atomic_read(&new->usage) < 1);
+       BUG_ON(atomic_long_read(&new->usage) < 1);
 
        get_cred(new); /* we will require a ref for the subj creds too */
 
@@ -502,14 +433,12 @@ int commit_creds(struct cred *new)
         * RLIMIT_NPROC limits on user->processes have already been checked
         * in set_user().
         */
-       alter_cred_subscribers(new, 2);
        if (new->user != old->user || new->user_ns != old->user_ns)
                inc_rlimit_ucounts(new->ucounts, UCOUNT_RLIMIT_NPROC, 1);
        rcu_assign_pointer(task->real_cred, new);
        rcu_assign_pointer(task->cred, new);
        if (new->user != old->user || new->user_ns != old->user_ns)
                dec_rlimit_ucounts(old->ucounts, UCOUNT_RLIMIT_NPROC, 1);
-       alter_cred_subscribers(old, -2);
 
        /* send notifications */
        if (!uid_eq(new->uid,   old->uid)  ||
@@ -539,14 +468,10 @@ EXPORT_SYMBOL(commit_creds);
  */
 void abort_creds(struct cred *new)
 {
-       kdebug("abort_creds(%p{%d,%d})", new,
-              atomic_read(&new->usage),
-              read_cred_subscribers(new));
+       kdebug("abort_creds(%p{%ld})", new,
+              atomic_long_read(&new->usage));
 
-#ifdef CONFIG_DEBUG_CREDENTIALS
-       BUG_ON(read_cred_subscribers(new) != 0);
-#endif
-       BUG_ON(atomic_read(&new->usage) < 1);
+       BUG_ON(atomic_long_read(&new->usage) < 1);
        put_cred(new);
 }
 EXPORT_SYMBOL(abort_creds);
@@ -562,12 +487,8 @@ const struct cred *override_creds(const struct cred *new)
 {
        const struct cred *old = current->cred;
 
-       kdebug("override_creds(%p{%d,%d})", new,
-              atomic_read(&new->usage),
-              read_cred_subscribers(new));
-
-       validate_creds(old);
-       validate_creds(new);
+       kdebug("override_creds(%p{%ld})", new,
+              atomic_long_read(&new->usage));
 
        /*
         * NOTE! This uses 'get_new_cred()' rather than 'get_cred()'.
@@ -576,18 +497,12 @@ const struct cred *override_creds(const struct cred *new)
         * we are only installing the cred into the thread-synchronous
         * '->cred' pointer, not the '->real_cred' pointer that is
         * visible to other threads under RCU.
-        *
-        * Also note that we did validate_creds() manually, not depending
-        * on the validation in 'get_cred()'.
         */
        get_new_cred((struct cred *)new);
-       alter_cred_subscribers(new, 1);
        rcu_assign_pointer(current->cred, new);
-       alter_cred_subscribers(old, -1);
 
-       kdebug("override_creds() = %p{%d,%d}", old,
-              atomic_read(&old->usage),
-              read_cred_subscribers(old));
+       kdebug("override_creds() = %p{%ld}", old,
+              atomic_long_read(&old->usage));
        return old;
 }
 EXPORT_SYMBOL(override_creds);
@@ -603,15 +518,10 @@ void revert_creds(const struct cred *old)
 {
        const struct cred *override = current->cred;
 
-       kdebug("revert_creds(%p{%d,%d})", old,
-              atomic_read(&old->usage),
-              read_cred_subscribers(old));
+       kdebug("revert_creds(%p{%ld})", old,
+              atomic_long_read(&old->usage));
 
-       validate_creds(old);
-       validate_creds(override);
-       alter_cred_subscribers(old, 1);
        rcu_assign_pointer(current->cred, old);
-       alter_cred_subscribers(override, -1);
        put_cred(override);
 }
 EXPORT_SYMBOL(revert_creds);
@@ -731,12 +641,10 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
        kdebug("prepare_kernel_cred() alloc %p", new);
 
        old = get_task_cred(daemon);
-       validate_creds(old);
 
        *new = *old;
        new->non_rcu = 0;
-       atomic_set(&new->usage, 1);
-       set_cred_subscribers(new, 0);
+       atomic_long_set(&new->usage, 1);
        get_uid(new->user);
        get_user_ns(new->user_ns);
        get_group_info(new->group_info);
@@ -760,7 +668,6 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
                goto error;
 
        put_cred(old);
-       validate_creds(new);
        return new;
 
 error:
@@ -825,109 +732,3 @@ int set_create_files_as(struct cred *new, struct inode *inode)
        return security_kernel_create_files_as(new, inode);
 }
 EXPORT_SYMBOL(set_create_files_as);
-
-#ifdef CONFIG_DEBUG_CREDENTIALS
-
-bool creds_are_invalid(const struct cred *cred)
-{
-       if (cred->magic != CRED_MAGIC)
-               return true;
-       return false;
-}
-EXPORT_SYMBOL(creds_are_invalid);
-
-/*
- * dump invalid credentials
- */
-static void dump_invalid_creds(const struct cred *cred, const char *label,
-                              const struct task_struct *tsk)
-{
-       pr_err("%s credentials: %p %s%s%s\n",
-              label, cred,
-              cred == &init_cred ? "[init]" : "",
-              cred == tsk->real_cred ? "[real]" : "",
-              cred == tsk->cred ? "[eff]" : "");
-       pr_err("->magic=%x, put_addr=%p\n",
-              cred->magic, cred->put_addr);
-       pr_err("->usage=%d, subscr=%d\n",
-              atomic_read(&cred->usage),
-              read_cred_subscribers(cred));
-       pr_err("->*uid = { %d,%d,%d,%d }\n",
-               from_kuid_munged(&init_user_ns, cred->uid),
-               from_kuid_munged(&init_user_ns, cred->euid),
-               from_kuid_munged(&init_user_ns, cred->suid),
-               from_kuid_munged(&init_user_ns, cred->fsuid));
-       pr_err("->*gid = { %d,%d,%d,%d }\n",
-               from_kgid_munged(&init_user_ns, cred->gid),
-               from_kgid_munged(&init_user_ns, cred->egid),
-               from_kgid_munged(&init_user_ns, cred->sgid),
-               from_kgid_munged(&init_user_ns, cred->fsgid));
-#ifdef CONFIG_SECURITY
-       pr_err("->security is %p\n", cred->security);
-       if ((unsigned long) cred->security >= PAGE_SIZE &&
-           (((unsigned long) cred->security & 0xffffff00) !=
-            (POISON_FREE << 24 | POISON_FREE << 16 | POISON_FREE << 8)))
-               pr_err("->security {%x, %x}\n",
-                      ((u32*)cred->security)[0],
-                      ((u32*)cred->security)[1]);
-#endif
-}
-
-/*
- * report use of invalid credentials
- */
-void __noreturn __invalid_creds(const struct cred *cred, const char *file, unsigned line)
-{
-       pr_err("Invalid credentials\n");
-       pr_err("At %s:%u\n", file, line);
-       dump_invalid_creds(cred, "Specified", current);
-       BUG();
-}
-EXPORT_SYMBOL(__invalid_creds);
-
-/*
- * check the credentials on a process
- */
-void __validate_process_creds(struct task_struct *tsk,
-                             const char *file, unsigned line)
-{
-       if (tsk->cred == tsk->real_cred) {
-               if (unlikely(read_cred_subscribers(tsk->cred) < 2 ||
-                            creds_are_invalid(tsk->cred)))
-                       goto invalid_creds;
-       } else {
-               if (unlikely(read_cred_subscribers(tsk->real_cred) < 1 ||
-                            read_cred_subscribers(tsk->cred) < 1 ||
-                            creds_are_invalid(tsk->real_cred) ||
-                            creds_are_invalid(tsk->cred)))
-                       goto invalid_creds;
-       }
-       return;
-
-invalid_creds:
-       pr_err("Invalid process credentials\n");
-       pr_err("At %s:%u\n", file, line);
-
-       dump_invalid_creds(tsk->real_cred, "Real", tsk);
-       if (tsk->cred != tsk->real_cred)
-               dump_invalid_creds(tsk->cred, "Effective", tsk);
-       else
-               pr_err("Effective creds == Real creds\n");
-       BUG();
-}
-EXPORT_SYMBOL(__validate_process_creds);
-
-/*
- * check creds for do_exit()
- */
-void validate_creds_for_do_exit(struct task_struct *tsk)
-{
-       kdebug("validate_creds_for_do_exit(%p,%p{%d,%d})",
-              tsk->real_cred, tsk->cred,
-              atomic_read(&tsk->cred->usage),
-              read_cred_subscribers(tsk->cred));
-
-       __validate_process_creds(tsk, __FILE__, __LINE__);
-}
-
-#endif /* CONFIG_DEBUG_CREDENTIALS */
index ee9f43bed49a240ac60c9f4054c663374e36ccf0..aedc0832c9f4ded6578233a611ee362e0dad77ff 100644 (file)
@@ -824,8 +824,6 @@ void __noreturn do_exit(long code)
        ptrace_event(PTRACE_EVENT_EXIT, code);
        user_events_exit(tsk);
 
-       validate_creds_for_do_exit(tsk);
-
        io_uring_files_cancel();
        exit_signals(tsk);  /* sets PF_EXITING */
 
@@ -909,7 +907,6 @@ void __noreturn do_exit(long code)
        if (tsk->task_frag.page)
                put_page(tsk->task_frag.page);
 
-       validate_creds_for_do_exit(tsk);
        exit_task_stack_account(tsk);
 
        check_stack_usage();
index 866ef3663a0b65ac8f6d6dc3acebbbb051c8d67a..91be1bc50b60e96204d95ad792cc71e5152c5e64 100644 (file)
@@ -1844,8 +1844,8 @@ get_free_mem_region(struct device *dev, struct resource *base,
 
        write_lock(&resource_lock);
        for (addr = gfr_start(base, size, align, flags);
-            gfr_continue(base, addr, size, flags);
-            addr = gfr_next(addr, size, flags)) {
+            gfr_continue(base, addr, align, flags);
+            addr = gfr_next(addr, align, flags)) {
                if (__region_intersects(base, addr, size, 0, IORES_DESC_NONE) !=
                    REGION_DISJOINT)
                        continue;
index 8d2a4f00eca9f0e3d3c065504f46940902f6a6f0..5a114e752f1101707eed15fc03521501211260fa 100644 (file)
@@ -644,8 +644,8 @@ static inline bool __rb_time_read(rb_time_t *t, u64 *ret, unsigned long *cnt)
 
        *cnt = rb_time_cnt(top);
 
-       /* If top and msb counts don't match, this interrupted a write */
-       if (*cnt != rb_time_cnt(msb))
+       /* If top, msb or bottom counts don't match, this interrupted a write */
+       if (*cnt != rb_time_cnt(msb) || *cnt != rb_time_cnt(bottom))
                return false;
 
        /* The shift to msb will lose its cnt bits */
@@ -706,6 +706,9 @@ static bool rb_time_cmpxchg(rb_time_t *t, u64 expect, u64 set)
        unsigned long cnt2, top2, bottom2, msb2;
        u64 val;
 
+       /* Any interruptions in this function should cause a failure */
+       cnt = local_read(&t->cnt);
+
        /* The cmpxchg always fails if it interrupted an update */
         if (!__rb_time_read(t, &val, &cnt2))
                 return false;
@@ -713,17 +716,18 @@ static bool rb_time_cmpxchg(rb_time_t *t, u64 expect, u64 set)
         if (val != expect)
                 return false;
 
-        cnt = local_read(&t->cnt);
         if ((cnt & 3) != cnt2)
                 return false;
 
         cnt2 = cnt + 1;
 
         rb_time_split(val, &top, &bottom, &msb);
+        msb = rb_time_val_cnt(msb, cnt);
         top = rb_time_val_cnt(top, cnt);
         bottom = rb_time_val_cnt(bottom, cnt);
 
         rb_time_split(set, &top2, &bottom2, &msb2);
+        msb2 = rb_time_val_cnt(msb2, cnt);
         top2 = rb_time_val_cnt(top2, cnt2);
         bottom2 = rb_time_val_cnt(bottom2, cnt2);
 
@@ -1787,6 +1791,8 @@ static void rb_free_cpu_buffer(struct ring_buffer_per_cpu *cpu_buffer)
                free_buffer_page(bpage);
        }
 
+       free_page((unsigned long)cpu_buffer->free_page);
+
        kfree(cpu_buffer);
 }
 
@@ -2407,7 +2413,7 @@ rb_iter_head_event(struct ring_buffer_iter *iter)
         */
        barrier();
 
-       if ((iter->head + length) > commit || length > BUF_MAX_DATA_SIZE)
+       if ((iter->head + length) > commit || length > BUF_PAGE_SIZE)
                /* Writer corrupted the read? */
                goto reset;
 
@@ -2981,25 +2987,6 @@ static unsigned rb_calculate_event_length(unsigned length)
        return length;
 }
 
-static u64 rb_time_delta(struct ring_buffer_event *event)
-{
-       switch (event->type_len) {
-       case RINGBUF_TYPE_PADDING:
-               return 0;
-
-       case RINGBUF_TYPE_TIME_EXTEND:
-               return rb_event_time_stamp(event);
-
-       case RINGBUF_TYPE_TIME_STAMP:
-               return 0;
-
-       case RINGBUF_TYPE_DATA:
-               return event->time_delta;
-       default:
-               return 0;
-       }
-}
-
 static inline bool
 rb_try_to_discard(struct ring_buffer_per_cpu *cpu_buffer,
                  struct ring_buffer_event *event)
@@ -3007,8 +2994,6 @@ rb_try_to_discard(struct ring_buffer_per_cpu *cpu_buffer,
        unsigned long new_index, old_index;
        struct buffer_page *bpage;
        unsigned long addr;
-       u64 write_stamp;
-       u64 delta;
 
        new_index = rb_event_index(event);
        old_index = new_index + rb_event_ts_length(event);
@@ -3017,14 +3002,10 @@ rb_try_to_discard(struct ring_buffer_per_cpu *cpu_buffer,
 
        bpage = READ_ONCE(cpu_buffer->tail_page);
 
-       delta = rb_time_delta(event);
-
-       if (!rb_time_read(&cpu_buffer->write_stamp, &write_stamp))
-               return false;
-
-       /* Make sure the write stamp is read before testing the location */
-       barrier();
-
+       /*
+        * Make sure the tail_page is still the same and
+        * the next write location is the end of this event
+        */
        if (bpage->page == (void *)addr && rb_page_write(bpage) == old_index) {
                unsigned long write_mask =
                        local_read(&bpage->write) & ~RB_WRITE_MASK;
@@ -3035,20 +3016,20 @@ rb_try_to_discard(struct ring_buffer_per_cpu *cpu_buffer,
                 * to make sure that the next event adds an absolute
                 * value and does not rely on the saved write stamp, which
                 * is now going to be bogus.
+                *
+                * By setting the before_stamp to zero, the next event
+                * is not going to use the write_stamp and will instead
+                * create an absolute timestamp. This means there's no
+                * reason to update the wirte_stamp!
                 */
                rb_time_set(&cpu_buffer->before_stamp, 0);
 
-               /* Something came in, can't discard */
-               if (!rb_time_cmpxchg(&cpu_buffer->write_stamp,
-                                      write_stamp, write_stamp - delta))
-                       return false;
-
                /*
                 * If an event were to come in now, it would see that the
                 * write_stamp and the before_stamp are different, and assume
                 * that this event just added itself before updating
                 * the write stamp. The interrupting event will fix the
-                * write stamp for us, and use the before stamp as its delta.
+                * write stamp for us, and use an absolute timestamp.
                 */
 
                /*
@@ -3485,7 +3466,7 @@ static void check_buffer(struct ring_buffer_per_cpu *cpu_buffer,
                return;
 
        /*
-        * If this interrupted another event, 
+        * If this interrupted another event,
         */
        if (atomic_inc_return(this_cpu_ptr(&checking)) != 1)
                goto out;
@@ -3579,7 +3560,10 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer,
                 * absolute timestamp.
                 * Don't bother if this is the start of a new page (w == 0).
                 */
-               if (unlikely(!a_ok || !b_ok || (info->before != info->after && w))) {
+               if (!w) {
+                       /* Use the sub-buffer timestamp */
+                       info->delta = 0;
+               } else if (unlikely(!a_ok || !b_ok || info->before != info->after)) {
                        info->add_timestamp |= RB_ADD_STAMP_FORCE | RB_ADD_STAMP_EXTEND;
                        info->length += RB_LEN_TIME_EXTEND;
                } else {
@@ -3602,26 +3586,19 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer,
 
        /* See if we shot pass the end of this buffer page */
        if (unlikely(write > BUF_PAGE_SIZE)) {
-               /* before and after may now different, fix it up*/
-               b_ok = rb_time_read(&cpu_buffer->before_stamp, &info->before);
-               a_ok = rb_time_read(&cpu_buffer->write_stamp, &info->after);
-               if (a_ok && b_ok && info->before != info->after)
-                       (void)rb_time_cmpxchg(&cpu_buffer->before_stamp,
-                                             info->before, info->after);
-               if (a_ok && b_ok)
-                       check_buffer(cpu_buffer, info, CHECK_FULL_PAGE);
+               check_buffer(cpu_buffer, info, CHECK_FULL_PAGE);
                return rb_move_tail(cpu_buffer, tail, info);
        }
 
        if (likely(tail == w)) {
-               u64 save_before;
-               bool s_ok;
-
                /* Nothing interrupted us between A and C */
  /*D*/         rb_time_set(&cpu_buffer->write_stamp, info->ts);
-               barrier();
- /*E*/         s_ok = rb_time_read(&cpu_buffer->before_stamp, &save_before);
-               RB_WARN_ON(cpu_buffer, !s_ok);
+               /*
+                * If something came in between C and D, the write stamp
+                * may now not be in sync. But that's fine as the before_stamp
+                * will be different and then next event will just be forced
+                * to use an absolute timestamp.
+                */
                if (likely(!(info->add_timestamp &
                             (RB_ADD_STAMP_FORCE | RB_ADD_STAMP_ABSOLUTE))))
                        /* This did not interrupt any time update */
@@ -3629,24 +3606,7 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer,
                else
                        /* Just use full timestamp for interrupting event */
                        info->delta = info->ts;
-               barrier();
                check_buffer(cpu_buffer, info, tail);
-               if (unlikely(info->ts != save_before)) {
-                       /* SLOW PATH - Interrupted between C and E */
-
-                       a_ok = rb_time_read(&cpu_buffer->write_stamp, &info->after);
-                       RB_WARN_ON(cpu_buffer, !a_ok);
-
-                       /* Write stamp must only go forward */
-                       if (save_before > info->after) {
-                               /*
-                                * We do not care about the result, only that
-                                * it gets updated atomically.
-                                */
-                               (void)rb_time_cmpxchg(&cpu_buffer->write_stamp,
-                                                     info->after, save_before);
-                       }
-               }
        } else {
                u64 ts;
                /* SLOW PATH - Interrupted between A and C */
@@ -3714,6 +3674,12 @@ rb_reserve_next_event(struct trace_buffer *buffer,
        int nr_loops = 0;
        int add_ts_default;
 
+       /* ring buffer does cmpxchg, make sure it is safe in NMI context */
+       if (!IS_ENABLED(CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG) &&
+           (unlikely(in_nmi()))) {
+               return NULL;
+       }
+
        rb_start_commit(cpu_buffer);
        /* The commit page can not change after this */
 
@@ -3737,6 +3703,8 @@ rb_reserve_next_event(struct trace_buffer *buffer,
        if (ring_buffer_time_stamp_abs(cpu_buffer->buffer)) {
                add_ts_default = RB_ADD_STAMP_ABSOLUTE;
                info.length += RB_LEN_TIME_EXTEND;
+               if (info.length > BUF_MAX_DATA_SIZE)
+                       goto out_fail;
        } else {
                add_ts_default = RB_ADD_STAMP_NONE;
        }
@@ -5118,7 +5086,8 @@ ring_buffer_read_prepare(struct trace_buffer *buffer, int cpu, gfp_t flags)
        if (!iter)
                return NULL;
 
-       iter->event = kmalloc(BUF_MAX_DATA_SIZE, flags);
+       /* Holds the entire event: data and meta data */
+       iter->event = kmalloc(BUF_PAGE_SIZE, flags);
        if (!iter->event) {
                kfree(iter);
                return NULL;
index fbcd3bafb93e2cc2b93e9716ce58b413f3912233..199df497db07eb0b6f80d679c8ac77606996205e 100644 (file)
@@ -4722,7 +4722,11 @@ static int s_show(struct seq_file *m, void *v)
                iter->leftover = ret;
 
        } else {
-               print_trace_line(iter);
+               ret = print_trace_line(iter);
+               if (ret == TRACE_TYPE_PARTIAL_LINE) {
+                       iter->seq.full = 0;
+                       trace_seq_puts(&iter->seq, "[LINE TOO BIG]\n");
+               }
                ret = trace_print_seq(m, &iter->seq);
                /*
                 * If we overflow the seq_file buffer, then it will
@@ -4964,6 +4968,12 @@ int tracing_release_file_tr(struct inode *inode, struct file *filp)
        return 0;
 }
 
+int tracing_single_release_file_tr(struct inode *inode, struct file *filp)
+{
+       tracing_release_file_tr(inode, filp);
+       return single_release(inode, filp);
+}
+
 static int tracing_mark_open(struct inode *inode, struct file *filp)
 {
        stream_open(inode, filp);
@@ -6344,7 +6354,7 @@ static int __tracing_resize_ring_buffer(struct trace_array *tr,
        if (!tr->array_buffer.buffer)
                return 0;
 
-       /* Do not allow tracing while resizng ring buffer */
+       /* Do not allow tracing while resizing ring buffer */
        tracing_stop_tr(tr);
 
        ret = ring_buffer_resize(tr->array_buffer.buffer, size, cpu);
@@ -6352,7 +6362,7 @@ static int __tracing_resize_ring_buffer(struct trace_array *tr,
                goto out_start;
 
 #ifdef CONFIG_TRACER_MAX_TRACE
-       if (!tr->current_trace->use_max_tr)
+       if (!tr->allocated_snapshot)
                goto out;
 
        ret = ring_buffer_resize(tr->max_buffer.buffer, size, cpu);
index b7f4ea25a19431d1a78c5f21e15298dea3c51897..0489e72c8169c19754159efa623057ae72a0c5db 100644 (file)
@@ -617,6 +617,7 @@ int tracing_open_generic(struct inode *inode, struct file *filp);
 int tracing_open_generic_tr(struct inode *inode, struct file *filp);
 int tracing_open_file_tr(struct inode *inode, struct file *filp);
 int tracing_release_file_tr(struct inode *inode, struct file *filp);
+int tracing_single_release_file_tr(struct inode *inode, struct file *filp);
 bool tracing_is_disabled(void);
 bool tracer_tracing_is_on(struct trace_array *tr);
 void tracer_tracing_on(struct trace_array *tr);
index 1abc07fba1b91ddea5b1f2c6446d1fe03275ba31..5ecf3c8bde205f360e880b608b11abcddb689a70 100644 (file)
@@ -5623,10 +5623,12 @@ static int event_hist_open(struct inode *inode, struct file *file)
 {
        int ret;
 
-       ret = security_locked_down(LOCKDOWN_TRACEFS);
+       ret = tracing_open_file_tr(inode, file);
        if (ret)
                return ret;
 
+       /* Clear private_data to avoid warning in single_open() */
+       file->private_data = NULL;
        return single_open(file, hist_show, file);
 }
 
@@ -5634,7 +5636,7 @@ const struct file_operations event_hist_fops = {
        .open = event_hist_open,
        .read = seq_read,
        .llseek = seq_lseek,
-       .release = single_release,
+       .release = tracing_single_release_file_tr,
 };
 
 #ifdef CONFIG_HIST_TRIGGERS_DEBUG
@@ -5900,10 +5902,12 @@ static int event_hist_debug_open(struct inode *inode, struct file *file)
 {
        int ret;
 
-       ret = security_locked_down(LOCKDOWN_TRACEFS);
+       ret = tracing_open_file_tr(inode, file);
        if (ret)
                return ret;
 
+       /* Clear private_data to avoid warning in single_open() */
+       file->private_data = NULL;
        return single_open(file, hist_debug_show, file);
 }
 
@@ -5911,7 +5915,7 @@ const struct file_operations event_hist_debug_fops = {
        .open = event_hist_debug_open,
        .read = seq_read,
        .llseek = seq_lseek,
-       .release = single_release,
+       .release = tracing_single_release_file_tr,
 };
 #endif
 
index d8b302d0108302d9ef2debe735c4b7778a217f90..3e7fa44dc2b24850f8b836f6bd223807fbcf0c48 100644 (file)
@@ -1587,11 +1587,12 @@ static enum print_line_t trace_print_print(struct trace_iterator *iter,
 {
        struct print_entry *field;
        struct trace_seq *s = &iter->seq;
+       int max = iter->ent_size - offsetof(struct print_entry, buf);
 
        trace_assign_type(field, iter->ent);
 
        seq_print_ip_sym(s, field->ip, flags);
-       trace_seq_printf(s, ": %s", field->buf);
+       trace_seq_printf(s, ": %.*s", max, field->buf);
 
        return trace_handle_return(s);
 }
@@ -1600,10 +1601,11 @@ static enum print_line_t trace_print_raw(struct trace_iterator *iter, int flags,
                                         struct trace_event *event)
 {
        struct print_entry *field;
+       int max = iter->ent_size - offsetof(struct print_entry, buf);
 
        trace_assign_type(field, iter->ent);
 
-       trace_seq_printf(&iter->seq, "# %lx %s", field->ip, field->buf);
+       trace_seq_printf(&iter->seq, "# %lx %.*s", field->ip, max, field->buf);
 
        return trace_handle_return(&iter->seq);
 }
index cc7d53d9dc0191c544b0e2a71d0a6500b854924c..4405f81248fbc72530d7f4882706d7499c5ea3c5 100644 (file)
@@ -1739,21 +1739,6 @@ config DEBUG_MAPLE_TREE
 
 endmenu
 
-config DEBUG_CREDENTIALS
-       bool "Debug credential management"
-       depends on DEBUG_KERNEL
-       help
-         Enable this to turn on some debug checking for credential
-         management.  The additional code keeps track of the number of
-         pointers from task_structs to any given cred struct, and checks to
-         see that this number never exceeds the usage count of the cred
-         struct.
-
-         Furthermore, if SELinux is enabled, this also checks that the
-         security pointer in the cred struct is never seen to be invalid.
-
-         If unsure, say N.
-
 source "kernel/rcu/Kconfig.debug"
 
 config DEBUG_WQ_FORCE_RR_CPU
index ce1562783e7e5df9941cd66e8eaf57db90f176de..3a05e71509b9db527e7938896dcde44521fe1735 100644 (file)
@@ -445,6 +445,8 @@ struct damon_ctx *damon_new_ctx(void)
        if (!ctx)
                return NULL;
 
+       init_completion(&ctx->kdamond_started);
+
        ctx->attrs.sample_interval = 5 * 1000;
        ctx->attrs.aggr_interval = 100 * 1000;
        ctx->attrs.ops_update_interval = 60 * 1000 * 1000;
@@ -668,11 +670,14 @@ static int __damon_start(struct damon_ctx *ctx)
        mutex_lock(&ctx->kdamond_lock);
        if (!ctx->kdamond) {
                err = 0;
+               reinit_completion(&ctx->kdamond_started);
                ctx->kdamond = kthread_run(kdamond_fn, ctx, "kdamond.%d",
                                nr_running_ctxs);
                if (IS_ERR(ctx->kdamond)) {
                        err = PTR_ERR(ctx->kdamond);
                        ctx->kdamond = NULL;
+               } else {
+                       wait_for_completion(&ctx->kdamond_started);
                }
        }
        mutex_unlock(&ctx->kdamond_lock);
@@ -1433,6 +1438,7 @@ static int kdamond_fn(void *data)
 
        pr_debug("kdamond (%d) starts\n", current->pid);
 
+       complete(&ctx->kdamond_started);
        kdamond_init_intervals_sis(ctx);
 
        if (ctx->ops.init)
index 91e2620148b2f6d789420e6736daef7a53e2cc5c..0d1ce70bce38028970802375b2409e9e6400364f 100644 (file)
@@ -1080,7 +1080,24 @@ whole_folios:
                                }
                                VM_BUG_ON_FOLIO(folio_test_writeback(folio),
                                                folio);
-                               truncate_inode_folio(mapping, folio);
+
+                               if (!folio_test_large(folio)) {
+                                       truncate_inode_folio(mapping, folio);
+                               } else if (truncate_inode_partial_folio(folio, lstart, lend)) {
+                                       /*
+                                        * If we split a page, reset the loop so
+                                        * that we pick up the new sub pages.
+                                        * Otherwise the THP was entirely
+                                        * dropped or the target range was
+                                        * zeroed, so just continue the loop as
+                                        * is.
+                                        */
+                                       if (!folio_test_large(folio)) {
+                                               folio_unlock(folio);
+                                               index = start;
+                                               break;
+                                       }
+                               }
                        }
                        folio_unlock(folio);
                }
index 506f8220c5fe5384678182628b78d1519ea8fc26..9dd8977de5a22345bdc40cf56680438226b4f4a8 100644 (file)
@@ -4089,6 +4089,9 @@ static void lru_gen_rotate_memcg(struct lruvec *lruvec, int op)
        else
                VM_WARN_ON_ONCE(true);
 
+       WRITE_ONCE(lruvec->lrugen.seg, seg);
+       WRITE_ONCE(lruvec->lrugen.gen, new);
+
        hlist_nulls_del_rcu(&lruvec->lrugen.list);
 
        if (op == MEMCG_LRU_HEAD || op == MEMCG_LRU_OLD)
@@ -4099,9 +4102,6 @@ static void lru_gen_rotate_memcg(struct lruvec *lruvec, int op)
        pgdat->memcg_lru.nr_memcgs[old]--;
        pgdat->memcg_lru.nr_memcgs[new]++;
 
-       lruvec->lrugen.gen = new;
-       WRITE_ONCE(lruvec->lrugen.seg, seg);
-
        if (!pgdat->memcg_lru.nr_memcgs[old] && old == get_memcg_gen(pgdat->memcg_lru.seq))
                WRITE_ONCE(pgdat->memcg_lru.seq, pgdat->memcg_lru.seq + 1);
 
@@ -4124,11 +4124,11 @@ void lru_gen_online_memcg(struct mem_cgroup *memcg)
 
                gen = get_memcg_gen(pgdat->memcg_lru.seq);
 
+               lruvec->lrugen.gen = gen;
+
                hlist_nulls_add_tail_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[gen][bin]);
                pgdat->memcg_lru.nr_memcgs[gen]++;
 
-               lruvec->lrugen.gen = gen;
-
                spin_unlock_irq(&pgdat->memcg_lru.lock);
        }
 }
@@ -4232,7 +4232,7 @@ static bool sort_folio(struct lruvec *lruvec, struct folio *folio, struct scan_c
        }
 
        /* protected */
-       if (tier > tier_idx) {
+       if (tier > tier_idx || refs == BIT(LRU_REFS_WIDTH)) {
                int hist = lru_hist_from_seq(lrugen->min_seq[type]);
 
                gen = folio_inc_gen(lruvec, folio, false);
@@ -4598,7 +4598,12 @@ static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq,
        }
 
        /* try to scrape all its memory if this memcg was deleted */
-       *nr_to_scan = mem_cgroup_online(memcg) ? (total >> sc->priority) : total;
+       if (!mem_cgroup_online(memcg)) {
+               *nr_to_scan = total;
+               return false;
+       }
+
+       *nr_to_scan = total >> sc->priority;
 
        /*
         * The aging tries to be lazy to reduce the overhead, while the eviction
@@ -4635,7 +4640,7 @@ static long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *sc, bool
        DEFINE_MAX_SEQ(lruvec);
 
        if (mem_cgroup_below_min(sc->target_mem_cgroup, memcg))
-               return 0;
+               return -1;
 
        if (!should_run_aging(lruvec, max_seq, sc, can_swap, &nr_to_scan))
                return nr_to_scan;
@@ -4648,20 +4653,41 @@ static long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *sc, bool
        return try_to_inc_max_seq(lruvec, max_seq, sc, can_swap, false) ? -1 : 0;
 }
 
-static unsigned long get_nr_to_reclaim(struct scan_control *sc)
+static bool should_abort_scan(struct lruvec *lruvec, struct scan_control *sc)
 {
+       int i;
+       enum zone_watermarks mark;
+
        /* don't abort memcg reclaim to ensure fairness */
        if (!root_reclaim(sc))
-               return -1;
+               return false;
+
+       if (sc->nr_reclaimed >= max(sc->nr_to_reclaim, compact_gap(sc->order)))
+               return true;
+
+       /* check the order to exclude compaction-induced reclaim */
+       if (!current_is_kswapd() || sc->order)
+               return false;
+
+       mark = sysctl_numa_balancing_mode & NUMA_BALANCING_MEMORY_TIERING ?
+              WMARK_PROMO : WMARK_HIGH;
+
+       for (i = 0; i <= sc->reclaim_idx; i++) {
+               struct zone *zone = lruvec_pgdat(lruvec)->node_zones + i;
+               unsigned long size = wmark_pages(zone, mark) + MIN_LRU_BATCH;
+
+               if (managed_zone(zone) && !zone_watermark_ok(zone, 0, size, sc->reclaim_idx, 0))
+                       return false;
+       }
 
-       return max(sc->nr_to_reclaim, compact_gap(sc->order));
+       /* kswapd should abort if all eligible zones are safe */
+       return true;
 }
 
 static bool try_to_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc)
 {
        long nr_to_scan;
        unsigned long scanned = 0;
-       unsigned long nr_to_reclaim = get_nr_to_reclaim(sc);
        int swappiness = get_swappiness(lruvec, sc);
 
        /* clean file folios are more likely to exist */
@@ -4683,13 +4709,13 @@ static bool try_to_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc)
                if (scanned >= nr_to_scan)
                        break;
 
-               if (sc->nr_reclaimed >= nr_to_reclaim)
+               if (should_abort_scan(lruvec, sc))
                        break;
 
                cond_resched();
        }
 
-       /* whether try_to_inc_max_seq() was successful */
+       /* whether this lruvec should be rotated */
        return nr_to_scan < 0;
 }
 
@@ -4698,14 +4724,9 @@ static int shrink_one(struct lruvec *lruvec, struct scan_control *sc)
        bool success;
        unsigned long scanned = sc->nr_scanned;
        unsigned long reclaimed = sc->nr_reclaimed;
-       int seg = lru_gen_memcg_seg(lruvec);
        struct mem_cgroup *memcg = lruvec_memcg(lruvec);
        struct pglist_data *pgdat = lruvec_pgdat(lruvec);
 
-       /* see the comment on MEMCG_NR_GENS */
-       if (!lruvec_is_sizable(lruvec, sc))
-               return seg != MEMCG_LRU_TAIL ? MEMCG_LRU_TAIL : MEMCG_LRU_YOUNG;
-
        mem_cgroup_calculate_protection(NULL, memcg);
 
        if (mem_cgroup_below_min(NULL, memcg))
@@ -4713,7 +4734,7 @@ static int shrink_one(struct lruvec *lruvec, struct scan_control *sc)
 
        if (mem_cgroup_below_low(NULL, memcg)) {
                /* see the comment on MEMCG_NR_GENS */
-               if (seg != MEMCG_LRU_TAIL)
+               if (lru_gen_memcg_seg(lruvec) != MEMCG_LRU_TAIL)
                        return MEMCG_LRU_TAIL;
 
                memcg_memory_event(memcg, MEMCG_LOW);
@@ -4729,7 +4750,15 @@ static int shrink_one(struct lruvec *lruvec, struct scan_control *sc)
 
        flush_reclaim_state(sc);
 
-       return success ? MEMCG_LRU_YOUNG : 0;
+       if (success && mem_cgroup_online(memcg))
+               return MEMCG_LRU_YOUNG;
+
+       if (!success && lruvec_is_sizable(lruvec, sc))
+               return 0;
+
+       /* one retry if offlined or too small */
+       return lru_gen_memcg_seg(lruvec) != MEMCG_LRU_TAIL ?
+              MEMCG_LRU_TAIL : MEMCG_LRU_YOUNG;
 }
 
 #ifdef CONFIG_MEMCG
@@ -4743,14 +4772,13 @@ static void shrink_many(struct pglist_data *pgdat, struct scan_control *sc)
        struct lruvec *lruvec;
        struct lru_gen_folio *lrugen;
        struct mem_cgroup *memcg;
-       const struct hlist_nulls_node *pos;
-       unsigned long nr_to_reclaim = get_nr_to_reclaim(sc);
+       struct hlist_nulls_node *pos;
 
+       gen = get_memcg_gen(READ_ONCE(pgdat->memcg_lru.seq));
        bin = first_bin = get_random_u32_below(MEMCG_NR_BINS);
 restart:
        op = 0;
        memcg = NULL;
-       gen = get_memcg_gen(READ_ONCE(pgdat->memcg_lru.seq));
 
        rcu_read_lock();
 
@@ -4761,6 +4789,10 @@ restart:
                }
 
                mem_cgroup_put(memcg);
+               memcg = NULL;
+
+               if (gen != READ_ONCE(lrugen->gen))
+                       continue;
 
                lruvec = container_of(lrugen, struct lruvec, lrugen);
                memcg = lruvec_memcg(lruvec);
@@ -4777,7 +4809,7 @@ restart:
 
                rcu_read_lock();
 
-               if (sc->nr_reclaimed >= nr_to_reclaim)
+               if (should_abort_scan(lruvec, sc))
                        break;
        }
 
@@ -4788,7 +4820,7 @@ restart:
 
        mem_cgroup_put(memcg);
 
-       if (sc->nr_reclaimed >= nr_to_reclaim)
+       if (!is_a_nulls(pos))
                return;
 
        /* restart if raced with lru_gen_rotate_memcg() */
@@ -4845,16 +4877,14 @@ static void set_initial_priority(struct pglist_data *pgdat, struct scan_control
        if (sc->priority != DEF_PRIORITY || sc->nr_to_reclaim < MIN_LRU_BATCH)
                return;
        /*
-        * Determine the initial priority based on ((total / MEMCG_NR_GENS) >>
-        * priority) * reclaimed_to_scanned_ratio = nr_to_reclaim, where the
-        * estimated reclaimed_to_scanned_ratio = inactive / total.
+        * Determine the initial priority based on
+        * (total >> priority) * reclaimed_to_scanned_ratio = nr_to_reclaim,
+        * where reclaimed_to_scanned_ratio = inactive / total.
         */
        reclaimable = node_page_state(pgdat, NR_INACTIVE_FILE);
        if (get_swappiness(lruvec, sc))
                reclaimable += node_page_state(pgdat, NR_INACTIVE_ANON);
 
-       reclaimable /= MEMCG_NR_GENS;
-
        /* round down reclaimable and round up sc->nr_to_reclaim */
        priority = fls_long(reclaimable) - 1 - fls_long(sc->nr_to_reclaim - 1);
 
index b192e44a0e7ccc08815e9b1f826d60f0038a5fa2..33baad203277d1e335dfbc44b72a1c7f520c3736 100644 (file)
@@ -313,10 +313,10 @@ static void lru_gen_refault(struct folio *folio, void *shadow)
         * 1. For pages accessed through page tables, hotter pages pushed out
         *    hot pages which refaulted immediately.
         * 2. For pages accessed multiple times through file descriptors,
-        *    numbers of accesses might have been out of the range.
+        *    they would have been protected by sort_folio().
         */
-       if (lru_gen_in_fault() || refs == BIT(LRU_REFS_WIDTH)) {
-               folio_set_workingset(folio);
+       if (lru_gen_in_fault() || refs >= BIT(LRU_REFS_WIDTH) - 1) {
+               set_mask_bits(&folio->flags, 0, LRU_REFS_MASK | BIT(PG_workingset));
                mod_lruvec_state(lruvec, WORKINGSET_RESTORE_BASE + type, delta);
        }
 unlock:
index 9ba04a69ec2ae70e0f5907215288208062d34ad4..a852ec093fa8b9f8e314f12a51ad78e8f2b3c851 100644 (file)
@@ -1775,15 +1775,14 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                break;
        }
        case TIOCINQ: {
-               /*
-                * These two are safe on a single CPU system as only
-                * user tasks fiddle here
-                */
-               struct sk_buff *skb = skb_peek(&sk->sk_receive_queue);
+               struct sk_buff *skb;
                long amount = 0;
 
+               spin_lock_irq(&sk->sk_receive_queue.lock);
+               skb = skb_peek(&sk->sk_receive_queue);
                if (skb)
                        amount = skb->len - sizeof(struct ddpehdr);
+               spin_unlock_irq(&sk->sk_receive_queue.lock);
                rc = put_user(amount, (int __user *)argp);
                break;
        }
index 838ebf0cabbfb72f370d2794212d67466f79b81e..f81f8d56f5c0c574d60b7bb552c3cc62bca40f9e 100644 (file)
@@ -73,14 +73,17 @@ static int do_vcc_ioctl(struct socket *sock, unsigned int cmd,
        case SIOCINQ:
        {
                struct sk_buff *skb;
+               int amount;
 
                if (sock->state != SS_CONNECTED) {
                        error = -EINVAL;
                        goto done;
                }
+               spin_lock_irq(&sk->sk_receive_queue.lock);
                skb = skb_peek(&sk->sk_receive_queue);
-               error = put_user(skb ? skb->len : 0,
-                                (int __user *)argp) ? -EFAULT : 0;
+               amount = skb ? skb->len : 0;
+               spin_unlock_irq(&sk->sk_receive_queue.lock);
+               error = put_user(amount, (int __user *)argp) ? -EFAULT : 0;
                goto done;
        }
        case ATM_SETSC:
index df81c1f0a57047e176b7c7e4809d2dae59ba6be5..552719c3bbc3d7869c49028f4c5c9102d1ae9b0a 100644 (file)
@@ -253,9 +253,11 @@ static int neigh_forced_gc(struct neigh_table *tbl)
 {
        int max_clean = atomic_read(&tbl->gc_entries) -
                        READ_ONCE(tbl->gc_thresh2);
+       u64 tmax = ktime_get_ns() + NSEC_PER_MSEC;
        unsigned long tref = jiffies - 5 * HZ;
        struct neighbour *n, *tmp;
        int shrunk = 0;
+       int loop = 0;
 
        NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs);
 
@@ -278,11 +280,16 @@ static int neigh_forced_gc(struct neigh_table *tbl)
                                shrunk++;
                        if (shrunk >= max_clean)
                                break;
+                       if (++loop == 16) {
+                               if (ktime_get_ns() > tmax)
+                                       goto unlock;
+                               loop = 0;
+                       }
                }
        }
 
        WRITE_ONCE(tbl->last_flush, jiffies);
-
+unlock:
        write_unlock_bh(&tbl->lock);
 
        return shrunk;
index b157efea5dea88745f9a2ae547d39fdf7e622627..83af8aaeb893b1a89bc034ee0d034d4f96318c6f 100644 (file)
@@ -4522,8 +4522,9 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
                /* GSO partial only requires that we trim off any excess that
                 * doesn't fit into an MSS sized block, so take care of that
                 * now.
+                * Cap len to not accidentally hit GSO_BY_FRAGS.
                 */
-               partial_segs = len / mss;
+               partial_segs = min(len, GSO_BY_FRAGS - 1) / mss;
                if (partial_segs > 1)
                        mss *= partial_segs;
                else
index 90de838a274519110ce0ac84552c4caedb826eb7..701cb87043f28079286044208128c2d687908991 100644 (file)
@@ -4368,6 +4368,23 @@ EXPORT_SYMBOL(tcp_do_parse_auth_options);
  * up to bandwidth of 18Gigabit/sec. 8) ]
  */
 
+/* Estimates max number of increments of remote peer TSval in
+ * a replay window (based on our current RTO estimation).
+ */
+static u32 tcp_tsval_replay(const struct sock *sk)
+{
+       /* If we use usec TS resolution,
+        * then expect the remote peer to use the same resolution.
+        */
+       if (tcp_sk(sk)->tcp_usec_ts)
+               return inet_csk(sk)->icsk_rto * (USEC_PER_SEC / HZ);
+
+       /* RFC 7323 recommends a TSval clock between 1ms and 1sec.
+        * We know that some OS (including old linux) can use 1200 Hz.
+        */
+       return inet_csk(sk)->icsk_rto * 1200 / HZ;
+}
+
 static int tcp_disordered_ack(const struct sock *sk, const struct sk_buff *skb)
 {
        const struct tcp_sock *tp = tcp_sk(sk);
@@ -4375,7 +4392,7 @@ static int tcp_disordered_ack(const struct sock *sk, const struct sk_buff *skb)
        u32 seq = TCP_SKB_CB(skb)->seq;
        u32 ack = TCP_SKB_CB(skb)->ack_seq;
 
-       return (/* 1. Pure ACK with correct sequence number. */
+       return  /* 1. Pure ACK with correct sequence number. */
                (th->ack && seq == TCP_SKB_CB(skb)->end_seq && seq == tp->rcv_nxt) &&
 
                /* 2. ... and duplicate ACK. */
@@ -4385,7 +4402,8 @@ static int tcp_disordered_ack(const struct sock *sk, const struct sk_buff *skb)
                !tcp_may_update_window(tp, ack, seq, ntohs(th->window) << tp->rx_opt.snd_wscale) &&
 
                /* 4. ... and sits in replay window. */
-               (s32)(tp->rx_opt.ts_recent - tp->rx_opt.rcv_tsval) <= (inet_csk(sk)->icsk_rto * 1024) / HZ);
+               (s32)(tp->rx_opt.ts_recent - tp->rx_opt.rcv_tsval) <=
+               tcp_tsval_replay(sk);
 }
 
 static inline bool tcp_paws_discard(const struct sock *sk,
index f5ef15e1d9ac38ff9866d913056b2d0cc5ee685f..e3167ad965676facaacd8f82848c52cf966f97c3 100644 (file)
@@ -3293,7 +3293,13 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs)
        if (skb_still_in_host_queue(sk, skb))
                return -EBUSY;
 
+start:
        if (before(TCP_SKB_CB(skb)->seq, tp->snd_una)) {
+               if (unlikely(TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN)) {
+                       TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_SYN;
+                       TCP_SKB_CB(skb)->seq++;
+                       goto start;
+               }
                if (unlikely(before(TCP_SKB_CB(skb)->end_seq, tp->snd_una))) {
                        WARN_ON_ONCE(1);
                        return -EINVAL;
index 3aaea56b516601070a11ec2c00150b8268bd481d..2692a7b24c40977a44c33358f558090036338f2c 100644 (file)
@@ -6149,11 +6149,7 @@ static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev,
        pmsg->prefix_len = pinfo->prefix_len;
        pmsg->prefix_type = pinfo->type;
        pmsg->prefix_pad3 = 0;
-       pmsg->prefix_flags = 0;
-       if (pinfo->onlink)
-               pmsg->prefix_flags |= IF_PREFIX_ONLINK;
-       if (pinfo->autoconf)
-               pmsg->prefix_flags |= IF_PREFIX_AUTOCONF;
+       pmsg->prefix_flags = pinfo->flags;
 
        if (nla_put(skb, PREFIX_ADDRESS, sizeof(pinfo->prefix), &pinfo->prefix))
                goto nla_put_failure;
index 0cc5a4e19900e10b31172433f36f5835101908ed..ecb91ad4ce639e7f8f3d2a9698e005cf696b123f 100644 (file)
@@ -1315,9 +1315,11 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
        case TIOCINQ: {
                struct sk_buff *skb;
                long amount = 0L;
-               /* These two are safe on a single CPU system as only user tasks fiddle here */
+
+               spin_lock_irq(&sk->sk_receive_queue.lock);
                if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)
                        amount = skb->len;
+               spin_unlock_irq(&sk->sk_receive_queue.lock);
                return put_user(amount, (unsigned int __user *) argp);
        }
 
index b3f4a503ee2ba4fd9620567208e2e77ed80b41b1..f69c47945175b657da6d7368c94693e81465296f 100644 (file)
@@ -286,9 +286,31 @@ static bool tcf_ct_flow_is_outdated(const struct flow_offload *flow)
               !test_bit(NF_FLOW_HW_ESTABLISHED, &flow->flags);
 }
 
+static void tcf_ct_flow_table_get_ref(struct tcf_ct_flow_table *ct_ft);
+
+static void tcf_ct_nf_get(struct nf_flowtable *ft)
+{
+       struct tcf_ct_flow_table *ct_ft =
+               container_of(ft, struct tcf_ct_flow_table, nf_ft);
+
+       tcf_ct_flow_table_get_ref(ct_ft);
+}
+
+static void tcf_ct_flow_table_put(struct tcf_ct_flow_table *ct_ft);
+
+static void tcf_ct_nf_put(struct nf_flowtable *ft)
+{
+       struct tcf_ct_flow_table *ct_ft =
+               container_of(ft, struct tcf_ct_flow_table, nf_ft);
+
+       tcf_ct_flow_table_put(ct_ft);
+}
+
 static struct nf_flowtable_type flowtable_ct = {
        .gc             = tcf_ct_flow_is_outdated,
        .action         = tcf_ct_flow_table_fill_actions,
+       .get            = tcf_ct_nf_get,
+       .put            = tcf_ct_nf_put,
        .owner          = THIS_MODULE,
 };
 
@@ -337,9 +359,13 @@ err_alloc:
        return err;
 }
 
+static void tcf_ct_flow_table_get_ref(struct tcf_ct_flow_table *ct_ft)
+{
+       refcount_inc(&ct_ft->ref);
+}
+
 static void tcf_ct_flow_table_cleanup_work(struct work_struct *work)
 {
-       struct flow_block_cb *block_cb, *tmp_cb;
        struct tcf_ct_flow_table *ct_ft;
        struct flow_block *block;
 
@@ -347,13 +373,9 @@ static void tcf_ct_flow_table_cleanup_work(struct work_struct *work)
                             rwork);
        nf_flow_table_free(&ct_ft->nf_ft);
 
-       /* Remove any remaining callbacks before cleanup */
        block = &ct_ft->nf_ft.flow_block;
        down_write(&ct_ft->nf_ft.flow_block_lock);
-       list_for_each_entry_safe(block_cb, tmp_cb, &block->cb_list, list) {
-               list_del(&block_cb->list);
-               flow_block_cb_free(block_cb);
-       }
+       WARN_ON(!list_empty(&block->cb_list));
        up_write(&ct_ft->nf_ft.flow_block_lock);
        kfree(ct_ft);
 
index 7bfe7d9a32aa601d352038b105dbcfe3604a0534..04534ea537c8fd15082a2c5b23b02472f9175c3b 100644 (file)
@@ -40,9 +40,6 @@ static unsigned long number_cred_unused;
 
 static struct cred machine_cred = {
        .usage = ATOMIC_INIT(1),
-#ifdef CONFIG_DEBUG_CREDENTIALS
-       .magic = CRED_MAGIC,
-#endif
 };
 
 /*
index c8e162c9d1df9265bd6e93586fca9e721fae979e..6df246b532606312f2cbf547c7332fa3463a7e3e 100644 (file)
@@ -843,7 +843,7 @@ static s64 virtio_transport_has_space(struct vsock_sock *vsk)
        struct virtio_vsock_sock *vvs = vsk->trans;
        s64 bytes;
 
-       bytes = vvs->peer_buf_alloc - (vvs->tx_cnt - vvs->peer_fwd_cnt);
+       bytes = (s64)vvs->peer_buf_alloc - (vvs->tx_cnt - vvs->peer_fwd_cnt);
        if (bytes < 0)
                bytes = 0;
 
index 598ef5465f8256214cb0ad29d5fe91a37872df2e..3edb156ae52c30d8e314ed9097bdae8b3cadb02b 100644 (file)
@@ -322,7 +322,7 @@ int main(int argc, char **argv)
                                     CMS_NOSMIMECAP | use_keyid |
                                     use_signed_attrs),
                    "CMS_add1_signer");
-               ERR(CMS_final(cms, bm, NULL, CMS_NOCERTS | CMS_BINARY) < 0,
+               ERR(CMS_final(cms, bm, NULL, CMS_NOCERTS | CMS_BINARY) != 1,
                    "CMS_final");
 
 #else
@@ -341,10 +341,10 @@ int main(int argc, char **argv)
                        b = BIO_new_file(sig_file_name, "wb");
                        ERR(!b, "%s", sig_file_name);
 #ifndef USE_PKCS7
-                       ERR(i2d_CMS_bio_stream(b, cms, NULL, 0) < 0,
+                       ERR(i2d_CMS_bio_stream(b, cms, NULL, 0) != 1,
                            "%s", sig_file_name);
 #else
-                       ERR(i2d_PKCS7_bio(b, pkcs7) < 0,
+                       ERR(i2d_PKCS7_bio(b, pkcs7) != 1,
                            "%s", sig_file_name);
 #endif
                        BIO_free(b);
@@ -374,9 +374,9 @@ int main(int argc, char **argv)
 
        if (!raw_sig) {
 #ifndef USE_PKCS7
-               ERR(i2d_CMS_bio_stream(bd, cms, NULL, 0) < 0, "%s", dest_name);
+               ERR(i2d_CMS_bio_stream(bd, cms, NULL, 0) != 1, "%s", dest_name);
 #else
-               ERR(i2d_PKCS7_bio(bd, pkcs7) < 0, "%s", dest_name);
+               ERR(i2d_PKCS7_bio(bd, pkcs7) != 1, "%s", dest_name);
 #endif
        } else {
                BIO *b;
@@ -396,7 +396,7 @@ int main(int argc, char **argv)
        ERR(BIO_write(bd, &sig_info, sizeof(sig_info)) < 0, "%s", dest_name);
        ERR(BIO_write(bd, magic_number, sizeof(magic_number) - 1) < 0, "%s", dest_name);
 
-       ERR(BIO_free(bd) < 0, "%s", dest_name);
+       ERR(BIO_free(bd) != 1, "%s", dest_name);
 
        /* Finally, if we're signing in place, replace the original. */
        if (replace_orig)
index feda711c6b7b84c19099568b96b3b5cbf121886d..340b2bbbb2dd357a5b2704f205a7dc70b28bdbe4 100644 (file)
@@ -1660,8 +1660,6 @@ static int inode_has_perm(const struct cred *cred,
        struct inode_security_struct *isec;
        u32 sid;
 
-       validate_creds(cred);
-
        if (unlikely(IS_PRIVATE(inode)))
                return 0;
 
@@ -3056,8 +3054,6 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
        struct inode_security_struct *isec;
        u32 sid;
 
-       validate_creds(cred);
-
        ad.type = LSM_AUDIT_DATA_DENTRY;
        ad.u.dentry = dentry;
        sid = cred_sid(cred);
@@ -3101,8 +3097,6 @@ static int selinux_inode_permission(struct inode *inode, int mask)
        if (!mask)
                return 0;
 
-       validate_creds(cred);
-
        if (unlikely(IS_PRIVATE(inode)))
                return 0;
 
index 1cde2a69bdb4baa0d95d34dde3e1a86933931268..78cee53fee02aad32dce7340be21901f0d394bb2 100644 (file)
@@ -1993,7 +1993,10 @@ static const struct snd_pci_quirk force_connect_list[] = {
        SND_PCI_QUIRK(0x103c, 0x871a, "HP", 1),
        SND_PCI_QUIRK(0x103c, 0x8711, "HP", 1),
        SND_PCI_QUIRK(0x103c, 0x8715, "HP", 1),
+       SND_PCI_QUIRK(0x1043, 0x86ae, "ASUS", 1),  /* Z170 PRO */
+       SND_PCI_QUIRK(0x1043, 0x86c7, "ASUS", 1),  /* Z170M PLUS */
        SND_PCI_QUIRK(0x1462, 0xec94, "MS-7C94", 1),
+       SND_PCI_QUIRK(0x8086, 0x2060, "Intel NUC5CPYB", 1),
        SND_PCI_QUIRK(0x8086, 0x2081, "Intel NUC 10", 1),
        {}
 };
index 0377912e926435d0b69c68d25c926fda85c2cd9f..e45d4c405f8ff1916fcf54ea9d3c231210f1d21c 100644 (file)
@@ -9795,6 +9795,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x83b9, "HP Spectre x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
        SND_PCI_QUIRK(0x103c, 0x841c, "HP Pavilion 15-CK0xx", ALC269_FIXUP_HP_MUTE_LED_MIC3),
        SND_PCI_QUIRK(0x103c, 0x8497, "HP Envy x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
+       SND_PCI_QUIRK(0x103c, 0x84ae, "HP 15-db0403ng", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
        SND_PCI_QUIRK(0x103c, 0x84da, "HP OMEN dc0019-ur", ALC295_FIXUP_HP_OMEN),
        SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
        SND_PCI_QUIRK(0x103c, 0x8519, "HP Spectre x360 15-df0xxx", ALC285_FIXUP_HP_SPECTRE_X360),
index fb802802939e170f73e87c85ec223ebf40fab4e8..63a90c7e897685e05c8b325c2f9d89942bec05ce 100644 (file)
@@ -455,9 +455,9 @@ static int tas2781_save_calibration(struct tasdevice_priv *tas_priv)
                status = efi.get_variable(efi_name, &efi_guid, &attr,
                        &tas_priv->cali_data.total_sz,
                        tas_priv->cali_data.data);
-               if (status != EFI_SUCCESS)
-                       return -EINVAL;
        }
+       if (status != EFI_SUCCESS)
+               return -EINVAL;
 
        tmp_val = (unsigned int *)tas_priv->cali_data.data;
 
@@ -550,11 +550,6 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
        tas2781_save_calibration(tas_priv);
 
 out:
-       if (tas_priv->fw_state == TASDEVICE_DSP_FW_FAIL) {
-               /*If DSP FW fail, kcontrol won't be created */
-               tasdevice_config_info_remove(tas_priv);
-               tasdevice_dsp_remove(tas_priv);
-       }
        mutex_unlock(&tas_priv->codec_lock);
        if (fmw)
                release_firmware(fmw);
@@ -612,9 +607,13 @@ static void tas2781_hda_unbind(struct device *dev,
 {
        struct tasdevice_priv *tas_priv = dev_get_drvdata(dev);
        struct hda_component *comps = master_data;
+       comps = &comps[tas_priv->index];
 
-       if (comps[tas_priv->index].dev == dev)
-               memset(&comps[tas_priv->index], 0, sizeof(*comps));
+       if (comps->dev == dev) {
+               comps->dev = NULL;
+               memset(comps->name, 0, sizeof(comps->name));
+               comps->playback_hook = NULL;
+       }
 
        tasdevice_config_info_remove(tas_priv);
        tasdevice_dsp_remove(tas_priv);
@@ -675,14 +674,14 @@ static int tas2781_hda_i2c_probe(struct i2c_client *clt)
 
        pm_runtime_put_autosuspend(tas_priv->dev);
 
+       tas2781_reset(tas_priv);
+
        ret = component_add(tas_priv->dev, &tas2781_hda_comp_ops);
        if (ret) {
                dev_err(tas_priv->dev, "Register component failed: %d\n", ret);
                pm_runtime_disable(tas_priv->dev);
-               goto err;
        }
 
-       tas2781_reset(tas_priv);
 err:
        if (ret)
                tas2781_hda_remove(&clt->dev);
index 649ebdef9c3fa0ac5fd052e397ff4ce23f229ee1..1685d7ea6a9f70021d8ea3fcb10ad5eb316176d8 100644 (file)
@@ -6,7 +6,6 @@
  *
  * Yes, this is unfortunate.  A better solution is in the works.
  */
-NORETURN(__invalid_creds)
 NORETURN(__kunit_abort)
 NORETURN(__module_put_and_kthread_exit)
 NORETURN(__reiserfs_panic)
index 90f3c9802ffb80fcb1c8a083835e1447087fcae6..95dc58b94178bf00b447b04440644bba1cd2209d 100644 (file)
@@ -62,5 +62,6 @@ cxl_core-$(CONFIG_TRACING) += $(CXL_CORE_SRC)/trace.o
 cxl_core-$(CONFIG_CXL_REGION) += $(CXL_CORE_SRC)/region.o
 cxl_core-y += config_check.o
 cxl_core-y += cxl_core_test.o
+cxl_core-y += cxl_core_exports.o
 
 obj-m += test/
diff --git a/tools/testing/cxl/cxl_core_exports.c b/tools/testing/cxl/cxl_core_exports.c
new file mode 100644 (file)
index 0000000..077e688
--- /dev/null
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2022 Intel Corporation. All rights reserved. */
+
+#include "cxl.h"
+
+/* Exporting of cxl_core symbols that are only used by cxl_test */
+EXPORT_SYMBOL_NS_GPL(cxl_num_decoders_committed, CXL);
index b8854629990227d9f3f984298db0e70ce95849d4..f4e517a0c7740ffa2dfb4889231d42fad438a5a9 100644 (file)
@@ -669,10 +669,11 @@ static int mock_decoder_commit(struct cxl_decoder *cxld)
                return 0;
 
        dev_dbg(&port->dev, "%s commit\n", dev_name(&cxld->dev));
-       if (port->commit_end + 1 != id) {
+       if (cxl_num_decoders_committed(port) != id) {
                dev_dbg(&port->dev,
                        "%s: out of order commit, expected decoder%d.%d\n",
-                       dev_name(&cxld->dev), port->id, port->commit_end + 1);
+                       dev_name(&cxld->dev), port->id,
+                       cxl_num_decoders_committed(port));
                return -EBUSY;
        }
 
index 3b2061d1c1a527c9868d8a80c18a1a91781f27e4..8247a7c69c36d7d446083d422ada0c5c6d897625 100644 (file)
@@ -155,12 +155,10 @@ ifneq ($(KBUILD_OUTPUT),)
   abs_objtree := $(realpath $(abs_objtree))
   BUILD := $(abs_objtree)/kselftest
   KHDR_INCLUDES := -isystem ${abs_objtree}/usr/include
-  KHDR_DIR := ${abs_objtree}/usr/include
 else
   BUILD := $(CURDIR)
   abs_srctree := $(shell cd $(top_srcdir) && pwd)
   KHDR_INCLUDES := -isystem ${abs_srctree}/usr/include
-  KHDR_DIR := ${abs_srctree}/usr/include
   DEFAULT_INSTALL_HDR_PATH := 1
 endif
 
@@ -174,7 +172,7 @@ export KHDR_INCLUDES
 # all isn't the first target in the file.
 .DEFAULT_GOAL := all
 
-all: kernel_header_files
+all:
        @ret=1;                                                 \
        for TARGET in $(TARGETS); do                            \
                BUILD_TARGET=$$BUILD/$$TARGET;                  \
@@ -185,23 +183,6 @@ all: kernel_header_files
                ret=$$((ret * $$?));                            \
        done; exit $$ret;
 
-kernel_header_files:
-       @ls $(KHDR_DIR)/linux/*.h >/dev/null 2>/dev/null;                          \
-       if [ $$? -ne 0 ]; then                                                     \
-            RED='\033[1;31m';                                                  \
-            NOCOLOR='\033[0m';                                                 \
-            echo;                                                              \
-            echo -e "$${RED}error$${NOCOLOR}: missing kernel header files.";   \
-            echo "Please run this and try again:";                             \
-            echo;                                                              \
-            echo "    cd $(top_srcdir)";                                       \
-            echo "    make headers";                                           \
-            echo;                                                              \
-           exit 1;                                                                \
-       fi
-
-.PHONY: kernel_header_files
-
 run_tests: all
        @for TARGET in $(TARGETS); do \
                BUILD_TARGET=$$BUILD/$$TARGET;  \
index 2e70a6048278459e889574972ce29221510221a3..49a29dbc19107229c52b1b2bdd055854295fca4f 100644 (file)
@@ -50,7 +50,6 @@ CONFIG_CRYPTO_SEQIV=y
 CONFIG_CRYPTO_XXHASH=y
 CONFIG_DCB=y
 CONFIG_DEBUG_ATOMIC_SLEEP=y
-CONFIG_DEBUG_CREDENTIALS=y
 CONFIG_DEBUG_INFO_BTF=y
 CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
 CONFIG_DEBUG_MEMORY_INIT=y
index 0617275d93cc70d6495680e9abc15148b628feb1..0f456dbab62f37ada813badfda6c3a1a07174412 100644 (file)
@@ -46,7 +46,6 @@ CONFIG_CRYPTO_SEQIV=y
 CONFIG_CRYPTO_XXHASH=y
 CONFIG_DCB=y
 CONFIG_DEBUG_ATOMIC_SLEEP=y
-CONFIG_DEBUG_CREDENTIALS=y
 CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
 CONFIG_DEBUG_MEMORY_INIT=y
 CONFIG_DEFAULT_FQ_CODEL=y
index 118e0964bda9468364e38c08e18a2b1f84de4b10..aa646e0661f36cac428395667f47ed11013ef083 100644 (file)
@@ -44,26 +44,10 @@ endif
 selfdir = $(realpath $(dir $(filter %/lib.mk,$(MAKEFILE_LIST))))
 top_srcdir = $(selfdir)/../../..
 
-ifeq ("$(origin O)", "command line")
-  KBUILD_OUTPUT := $(O)
+ifeq ($(KHDR_INCLUDES),)
+KHDR_INCLUDES := -isystem $(top_srcdir)/usr/include
 endif
 
-ifneq ($(KBUILD_OUTPUT),)
-  # Make's built-in functions such as $(abspath ...), $(realpath ...) cannot
-  # expand a shell special character '~'. We use a somewhat tedious way here.
-  abs_objtree := $(shell cd $(top_srcdir) && mkdir -p $(KBUILD_OUTPUT) && cd $(KBUILD_OUTPUT) && pwd)
-  $(if $(abs_objtree),, \
-    $(error failed to create output directory "$(KBUILD_OUTPUT)"))
-  # $(realpath ...) resolves symlinks
-  abs_objtree := $(realpath $(abs_objtree))
-  KHDR_DIR := ${abs_objtree}/usr/include
-else
-  abs_srctree := $(shell cd $(top_srcdir) && pwd)
-  KHDR_DIR := ${abs_srctree}/usr/include
-endif
-
-KHDR_INCLUDES := -isystem $(KHDR_DIR)
-
 # The following are built by lib.mk common compile rules.
 # TEST_CUSTOM_PROGS should be used by tests that require
 # custom build rule and prevent common build rule use.
@@ -74,25 +58,7 @@ TEST_GEN_PROGS := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_PROGS))
 TEST_GEN_PROGS_EXTENDED := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_PROGS_EXTENDED))
 TEST_GEN_FILES := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_FILES))
 
-all: kernel_header_files $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) \
-     $(TEST_GEN_FILES)
-
-kernel_header_files:
-       @ls $(KHDR_DIR)/linux/*.h >/dev/null 2>/dev/null;                      \
-       if [ $$? -ne 0 ]; then                                                 \
-            RED='\033[1;31m';                                                  \
-            NOCOLOR='\033[0m';                                                 \
-            echo;                                                              \
-            echo -e "$${RED}error$${NOCOLOR}: missing kernel header files.";   \
-            echo "Please run this and try again:";                             \
-            echo;                                                              \
-            echo "    cd $(top_srcdir)";                                       \
-            echo "    make headers";                                           \
-            echo;                                                              \
-           exit 1; \
-       fi
-
-.PHONY: kernel_header_files
+all: $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES)
 
 define RUN_TESTS
        BASE_DIR="$(selfdir)";                  \
index 7324ce5363c0c98103aced7d686f373089db60de..6f2f839904416c4d1dce542b2dd04250e2bddaa2 100644 (file)
@@ -1680,6 +1680,8 @@ int main(int argc, char **argv)
 {
        int err;
 
+       ksft_print_header();
+
        pagesize = getpagesize();
        thpsize = read_pmd_pagesize();
        if (thpsize)
@@ -1689,7 +1691,6 @@ int main(int argc, char **argv)
                                                    ARRAY_SIZE(hugetlbsizes));
        detect_huge_zeropage();
 
-       ksft_print_header();
        ksft_set_plan(ARRAY_SIZE(anon_test_cases) * tests_per_anon_test_case() +
                      ARRAY_SIZE(anon_thp_test_cases) * tests_per_anon_thp_test_case() +
                      ARRAY_SIZE(non_anon_test_cases) * tests_per_non_anon_test_case());