Merge tag 'email' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 20 Apr 2024 18:17:22 +0000 (11:17 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 20 Apr 2024 18:17:22 +0000 (11:17 -0700)
Pull email address update from James Bottomley:
 "My IBM email has stopped working, so update to a working email
  address"

* tag 'email' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  MAINTAINERS: update to working email address

244 files changed:
.mailmap
Documentation/devicetree/bindings/pwm/mediatek,pwm-disp.yaml
Documentation/mm/page_owner.rst
MAINTAINERS
arch/arm64/kernel/head.S
arch/arm64/mm/hugetlbpage.c
arch/arm64/mm/pageattr.c
arch/powerpc/crypto/chacha-p10-glue.c
arch/powerpc/kernel/iommu.c
arch/s390/kernel/entry.S
arch/x86/events/intel/lbr.c
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/perf_event.h
arch/x86/kvm/Makefile
arch/x86/kvm/cpuid.c
arch/x86/kvm/cpuid.h
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu/mmu.c
arch/x86/kvm/mmu/tdp_mmu.c
arch/x86/kvm/pmu.c
arch/x86/kvm/svm/sev.c
arch/x86/kvm/svm/svm.c
arch/x86/kvm/svm/svm.h
arch/x86/kvm/svm/vmenter.S
arch/x86/kvm/vmx/pmu_intel.c
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/vmx/vmx.h
arch/x86/kvm/x86.c
drivers/char/random.c
drivers/clk/clk.c
drivers/clk/mediatek/clk-mt7988-infracfg.c
drivers/clk/mediatek/clk-mtk.c
drivers/gpio/gpio-crystalcove.c
drivers/gpio/gpio-lpc32xx.c
drivers/gpio/gpio-wcove.c
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
drivers/gpu/drm/amd/amdkfd/kfd_process.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c
drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c
drivers/gpu/drm/nouveau/nouveau_bios.c
drivers/gpu/drm/nouveau/nouveau_dp.c
drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
drivers/gpu/drm/panel/panel-novatek-nt36672e.c
drivers/gpu/drm/panel/panel-visionox-rm69299.c
drivers/gpu/drm/radeon/pptable.h
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/ttm/ttm_pool.c
drivers/gpu/drm/v3d/v3d_irq.c
drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
drivers/gpu/drm/vmwgfx/vmwgfx_bo.h
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/drm/vmwgfx/vmwgfx_gem.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
drivers/gpu/drm/vmwgfx/vmwgfx_prime.c
drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c
drivers/gpu/drm/xe/display/intel_fb_bo.c
drivers/gpu/drm/xe/xe_vm.c
drivers/infiniband/core/cm.c
drivers/infiniband/hw/mlx5/mad.c
drivers/infiniband/sw/rxe/rxe.c
drivers/iommu/iommufd/Kconfig
drivers/net/dsa/mt7530.c
drivers/net/dsa/mt7530.h
drivers/net/ethernet/intel/ice/ice_tc_lib.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
drivers/net/ethernet/mediatek/mtk_wed.c
drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c
drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/stmicro/stmmac/common.h
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/ti/am65-cpsw-nuss.c
drivers/net/tun.c
drivers/net/usb/ax88179_178a.c
drivers/net/usb/qmi_wwan.c
drivers/platform/x86/amd/pmc/pmc-quirks.c
drivers/platform/x86/amd/pmf/Makefile
drivers/platform/x86/amd/pmf/acpi.c
drivers/platform/x86/amd/pmf/core.c
drivers/platform/x86/amd/pmf/pmf-quirks.c [new file with mode: 0644]
drivers/platform/x86/amd/pmf/pmf.h
drivers/platform/x86/intel/speed_select_if/isst_if_common.c
drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
drivers/pwm/pwm-dwc-core.c
drivers/pwm/pwm-dwc.c
drivers/pwm/pwm-dwc.h
drivers/s390/cio/device.c
drivers/s390/cio/device_fsm.c
drivers/s390/cio/device_ops.c
drivers/s390/cio/qdio_main.c
drivers/s390/net/ism_drv.c
drivers/scsi/scsi_lib.c
drivers/thermal/thermal_debugfs.c
drivers/ufs/host/ufs-qcom.c
drivers/virt/vmgenid.c
fs/9p/fid.h
fs/9p/vfs_file.c
fs/9p/vfs_inode.c
fs/9p/vfs_super.c
fs/bcachefs/backpointers.c
fs/bcachefs/backpointers.h
fs/bcachefs/bcachefs.h
fs/bcachefs/bcachefs_format.h
fs/bcachefs/bkey.h
fs/bcachefs/bkey_methods.c
fs/bcachefs/btree_cache.c
fs/bcachefs/btree_gc.c
fs/bcachefs/btree_io.c
fs/bcachefs/btree_iter.h
fs/bcachefs/btree_node_scan.c
fs/bcachefs/btree_trans_commit.c
fs/bcachefs/btree_update_interior.c
fs/bcachefs/btree_write_buffer.c
fs/bcachefs/buckets.h
fs/bcachefs/checksum.c
fs/bcachefs/checksum.h
fs/bcachefs/compress.h
fs/bcachefs/ec.c
fs/bcachefs/ec.h
fs/bcachefs/extents.c
fs/bcachefs/fs-io-direct.c
fs/bcachefs/fs-io.c
fs/bcachefs/journal_io.c
fs/bcachefs/opts.c
fs/bcachefs/opts.h
fs/bcachefs/recovery_passes.c
fs/bcachefs/sb-downgrade.c
fs/bcachefs/sb-errors_types.h
fs/bcachefs/sb-members.c
fs/bcachefs/sb-members.h
fs/bcachefs/super-io.c
fs/bcachefs/super_types.h
fs/bcachefs/sysfs.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/fuse/cuse.c
fs/fuse/dir.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/fuse/inode.c
fs/fuse/iomode.c
fs/nfsd/nfs4xdr.c
fs/nilfs2/dir.c
fs/squashfs/inode.c
include/linux/bootconfig.h
include/linux/clk.h
include/linux/gpio/property.h
include/linux/shmem_fs.h
include/linux/swapops.h
include/linux/udp.h
include/net/netfilter/nf_flow_table.h
include/net/netfilter/nf_tables.h
include/net/sch_generic.h
include/trace/events/rpcgss.h
init/main.c
kernel/configs/hardening.config
kernel/fork.c
lib/bootconfig.c
lib/ubsan.c
mm/gup.c
mm/huge_memory.c
mm/hugetlb.c
mm/internal.h
mm/madvise.c
mm/memory-failure.c
mm/page_owner.c
mm/shmem.c
net/bridge/br_input.c
net/bridge/br_netfilter_hooks.c
net/bridge/br_private.h
net/bridge/netfilter/nf_conntrack_bridge.c
net/core/dev.c
net/ipv4/fib_frontend.c
net/netfilter/nf_flow_table_inet.c
net/netfilter/nf_flow_table_ip.c
net/netfilter/nf_tables_api.c
net/netfilter/nft_lookup.c
net/netfilter/nft_set_bitmap.c
net/netfilter/nft_set_hash.c
net/netfilter/nft_set_pipapo.c
net/netfilter/nft_set_rbtree.c
net/sched/sch_generic.c
net/unix/af_unix.c
sound/core/seq/seq_ump_convert.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/tas2781_hda_i2c.c
tools/arch/arm64/include/asm/cputype.h
tools/arch/arm64/include/uapi/asm/kvm.h
tools/arch/powerpc/include/uapi/asm/kvm.h
tools/arch/s390/include/uapi/asm/kvm.h
tools/arch/x86/include/asm/cpufeatures.h
tools/arch/x86/include/asm/disabled-features.h
tools/arch/x86/include/asm/irq_vectors.h
tools/arch/x86/include/asm/msr-index.h
tools/arch/x86/include/asm/required-features.h
tools/arch/x86/include/uapi/asm/kvm.h
tools/include/asm-generic/bitops/__fls.h
tools/include/asm-generic/bitops/fls.h
tools/include/uapi/drm/i915_drm.h
tools/include/uapi/linux/fs.h
tools/include/uapi/linux/kvm.h
tools/include/uapi/sound/asound.h
tools/perf/ui/browsers/annotate.c
tools/perf/util/annotate.c
tools/perf/util/bpf_skel/lock_contention.bpf.c
tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc
tools/testing/selftests/iommu/config
tools/testing/selftests/kselftest.h
tools/testing/selftests/kselftest_harness.h
tools/testing/selftests/kvm/max_guest_memory_test.c
tools/testing/selftests/kvm/set_memory_region_test.c
tools/testing/selftests/kvm/x86_64/pmu_counters_test.c
tools/testing/selftests/kvm/x86_64/vmx_dirty_log_test.c
tools/testing/selftests/net/tcp_ao/lib/proc.c
tools/testing/selftests/net/tcp_ao/lib/setup.c
tools/testing/selftests/net/tcp_ao/rst.c
tools/testing/selftests/net/tcp_ao/setsockopt-closed.c
tools/testing/selftests/net/udpgso.c
tools/testing/selftests/powerpc/papr_vpd/papr_vpd.c
virt/kvm/kvm_main.c
virt/kvm/kvm_mm.h
virt/kvm/pfncache.c

index 8284692f9610715fa2bc04f8771cb45d1b5ebf88..625b496bf5f45100b8c563349eb077059cfa0138 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -446,7 +446,8 @@ Mythri P K <mythripk@ti.com>
 Nadav Amit <nadav.amit@gmail.com> <namit@vmware.com>
 Nadav Amit <nadav.amit@gmail.com> <namit@cs.technion.ac.il>
 Nadia Yvette Chambers <nyc@holomorphy.com> William Lee Irwin III <wli@holomorphy.com>
-Naoya Horiguchi <naoya.horiguchi@nec.com> <n-horiguchi@ah.jp.nec.com>
+Naoya Horiguchi <nao.horiguchi@gmail.com> <n-horiguchi@ah.jp.nec.com>
+Naoya Horiguchi <nao.horiguchi@gmail.com> <naoya.horiguchi@nec.com>
 Nathan Chancellor <nathan@kernel.org> <natechancellor@gmail.com>
 Neeraj Upadhyay <quic_neeraju@quicinc.com> <neeraju@codeaurora.org>
 Neil Armstrong <neil.armstrong@linaro.org> <narmstrong@baylibre.com>
index afcdeed4e88af625ea4f0f371cc11ffdbe824859..bc813fe74faba5ae50bc81ecb2f75f9e1d8803c9 100644 (file)
@@ -52,6 +52,9 @@ properties:
       - const: main
       - const: mm
 
+  power-domains:
+    maxItems: 1
+
 required:
   - compatible
   - reg
index 0d0334cd51798b63af73cb86f891c07e1c7e587c..3a45a20fc05a1f90a67b5b61e6bbb654145928a3 100644 (file)
@@ -24,10 +24,10 @@ fragmentation statistics can be obtained through gfp flag information of
 each page. It is already implemented and activated if page owner is
 enabled. Other usages are more than welcome.
 
-It can also be used to show all the stacks and their outstanding
-allocations, which gives us a quick overview of where the memory is going
-without the need to screen through all the pages and match the allocation
-and free operation.
+It can also be used to show all the stacks and their current number of
+allocated base pages, which gives us a quick overview of where the memory
+is going without the need to screen through all the pages and match the
+allocation and free operation.
 
 page owner is disabled by default. So, if you'd like to use it, you need
 to add "page_owner=on" to your boot cmdline. If the kernel is built
@@ -75,42 +75,45 @@ Usage
 
        cat /sys/kernel/debug/page_owner_stacks/show_stacks > stacks.txt
        cat stacks.txt
-        prep_new_page+0xa9/0x120
-        get_page_from_freelist+0x7e6/0x2140
-        __alloc_pages+0x18a/0x370
-        new_slab+0xc8/0x580
-        ___slab_alloc+0x1f2/0xaf0
-        __slab_alloc.isra.86+0x22/0x40
-        kmem_cache_alloc+0x31b/0x350
-        __khugepaged_enter+0x39/0x100
-        dup_mmap+0x1c7/0x5ce
-        copy_process+0x1afe/0x1c90
-        kernel_clone+0x9a/0x3c0
-        __do_sys_clone+0x66/0x90
-        do_syscall_64+0x7f/0x160
-        entry_SYSCALL_64_after_hwframe+0x6c/0x74
-       stack_count: 234
+        post_alloc_hook+0x177/0x1a0
+        get_page_from_freelist+0xd01/0xd80
+        __alloc_pages+0x39e/0x7e0
+        allocate_slab+0xbc/0x3f0
+        ___slab_alloc+0x528/0x8a0
+        kmem_cache_alloc+0x224/0x3b0
+        sk_prot_alloc+0x58/0x1a0
+        sk_alloc+0x32/0x4f0
+        inet_create+0x427/0xb50
+        __sock_create+0x2e4/0x650
+        inet_ctl_sock_create+0x30/0x180
+        igmp_net_init+0xc1/0x130
+        ops_init+0x167/0x410
+        setup_net+0x304/0xa60
+        copy_net_ns+0x29b/0x4a0
+        create_new_namespaces+0x4a1/0x820
+       nr_base_pages: 16
        ...
        ...
        echo 7000 > /sys/kernel/debug/page_owner_stacks/count_threshold
        cat /sys/kernel/debug/page_owner_stacks/show_stacks> stacks_7000.txt
        cat stacks_7000.txt
-        prep_new_page+0xa9/0x120
-        get_page_from_freelist+0x7e6/0x2140
-        __alloc_pages+0x18a/0x370
-        alloc_pages_mpol+0xdf/0x1e0
-        folio_alloc+0x14/0x50
-        filemap_alloc_folio+0xb0/0x100
-        page_cache_ra_unbounded+0x97/0x180
-        filemap_fault+0x4b4/0x1200
-        __do_fault+0x2d/0x110
-        do_pte_missing+0x4b0/0xa30
-        __handle_mm_fault+0x7fa/0xb70
-        handle_mm_fault+0x125/0x300
-        do_user_addr_fault+0x3c9/0x840
-        exc_page_fault+0x68/0x150
-        asm_exc_page_fault+0x22/0x30
-       stack_count: 8248
+        post_alloc_hook+0x177/0x1a0
+        get_page_from_freelist+0xd01/0xd80
+        __alloc_pages+0x39e/0x7e0
+        alloc_pages_mpol+0x22e/0x490
+        folio_alloc+0xd5/0x110
+        filemap_alloc_folio+0x78/0x230
+        page_cache_ra_order+0x287/0x6f0
+        filemap_get_pages+0x517/0x1160
+        filemap_read+0x304/0x9f0
+        xfs_file_buffered_read+0xe6/0x1d0 [xfs]
+        xfs_file_read_iter+0x1f0/0x380 [xfs]
+        __kernel_read+0x3b9/0x730
+        kernel_read_file+0x309/0x4d0
+        __do_sys_finit_module+0x381/0x730
+        do_syscall_64+0x8d/0x150
+        entry_SYSCALL_64_after_hwframe+0x62/0x6a
+       nr_base_pages: 20824
        ...
 
        cat /sys/kernel/debug/page_owner > page_owner_full.txt
index e5121ff5e60ef750a6a82db71465b368081bcfef..261023998c5b437d9942a5919097ff2d71806855 100644 (file)
@@ -10024,7 +10024,7 @@ F:      drivers/media/platform/st/sti/hva
 
 HWPOISON MEMORY FAILURE HANDLING
 M:     Miaohe Lin <linmiaohe@huawei.com>
-R:     Naoya Horiguchi <naoya.horiguchi@nec.com>
+R:     Naoya Horiguchi <nao.horiguchi@gmail.com>
 L:     linux-mm@kvack.org
 S:     Maintained
 F:     mm/hwpoison-inject.c
index 06234c3a15f3dbe7a5ee874c41b05bb72c2894d4..cb68adcabe0789201aa4b37befaa686c67dc7db7 100644 (file)
@@ -289,6 +289,11 @@ SYM_INNER_LABEL(init_el2, SYM_L_LOCAL)
        adr_l   x1, __hyp_text_end
        adr_l   x2, dcache_clean_poc
        blr     x2
+
+       mov_q   x0, INIT_SCTLR_EL2_MMU_OFF
+       pre_disable_mmu_workaround
+       msr     sctlr_el2, x0
+       isb
 0:
        mov_q   x0, HCR_HOST_NVHE_FLAGS
 
@@ -323,13 +328,11 @@ SYM_INNER_LABEL(init_el2, SYM_L_LOCAL)
        cbz     x0, 2f
 
        /* Set a sane SCTLR_EL1, the VHE way */
-       pre_disable_mmu_workaround
        msr_s   SYS_SCTLR_EL12, x1
        mov     x2, #BOOT_CPU_FLAG_E2H
        b       3f
 
 2:
-       pre_disable_mmu_workaround
        msr     sctlr_el1, x1
        mov     x2, xzr
 3:
index 0f0e10bb0a9540a9a18ab6c9cf0ed509d2a11e14..b872b003a55f3d672b638b88b75c4d5af39056ff 100644 (file)
@@ -276,7 +276,10 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma,
        pte_t *ptep = NULL;
 
        pgdp = pgd_offset(mm, addr);
-       p4dp = p4d_offset(pgdp, addr);
+       p4dp = p4d_alloc(mm, pgdp, addr);
+       if (!p4dp)
+               return NULL;
+
        pudp = pud_alloc(mm, p4dp, addr);
        if (!pudp)
                return NULL;
index 0c4e3ecf989d434ae96b6620e72448c57e9eeb67..0e270a1c51e6450f64cf30d2b357dc4a5472add1 100644 (file)
@@ -219,9 +219,6 @@ bool kernel_page_present(struct page *page)
        pte_t *ptep;
        unsigned long addr = (unsigned long)page_address(page);
 
-       if (!can_set_direct_map())
-               return true;
-
        pgdp = pgd_offset_k(addr);
        if (pgd_none(READ_ONCE(*pgdp)))
                return false;
index 74fb86b0d2097c658128a7f55bdce30110faeb87..7c728755852e1a2cfe06f46cca29eb339be8f4b8 100644 (file)
@@ -197,6 +197,9 @@ static struct skcipher_alg algs[] = {
 
 static int __init chacha_p10_init(void)
 {
+       if (!cpu_has_feature(CPU_FTR_ARCH_31))
+               return 0;
+
        static_branch_enable(&have_p10);
 
        return crypto_register_skciphers(algs, ARRAY_SIZE(algs));
@@ -204,10 +207,13 @@ static int __init chacha_p10_init(void)
 
 static void __exit chacha_p10_exit(void)
 {
+       if (!static_branch_likely(&have_p10))
+               return;
+
        crypto_unregister_skciphers(algs, ARRAY_SIZE(algs));
 }
 
-module_cpu_feature_match(PPC_MODULE_FEATURE_P10, chacha_p10_init);
+module_init(chacha_p10_init);
 module_exit(chacha_p10_exit);
 
 MODULE_DESCRIPTION("ChaCha and XChaCha stream ciphers (P10 accelerated)");
index 1185efebf032b6e7d2cf08db4c953938948a44b1..29a8c8e185851ba1e710146e3abae7d07e8a8dc8 100644 (file)
@@ -1285,15 +1285,14 @@ spapr_tce_platform_iommu_attach_dev(struct iommu_domain *platform_domain,
                                    struct device *dev)
 {
        struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
-       struct iommu_group *grp = iommu_group_get(dev);
        struct iommu_table_group *table_group;
+       struct iommu_group *grp;
 
        /* At first attach the ownership is already set */
-       if (!domain) {
-               iommu_group_put(grp);
+       if (!domain)
                return 0;
-       }
 
+       grp = iommu_group_get(dev);
        table_group = iommu_group_get_iommudata(grp);
        /*
         * The domain being set to PLATFORM from earlier
index 3dc85638bc63b7d96eb3ebc25c558cff967395c6..6a1e0fbbaa15b325c898548afe1189905d4b0520 100644 (file)
@@ -340,7 +340,8 @@ SYM_CODE_START(pgm_check_handler)
        mvc     __PT_LAST_BREAK(8,%r11),__LC_PGM_LAST_BREAK
        stctg   %c1,%c1,__PT_CR1(%r11)
 #if IS_ENABLED(CONFIG_KVM)
-       lg      %r12,__LC_GMAP
+       ltg     %r12,__LC_GMAP
+       jz      5f
        clc     __GMAP_ASCE(8,%r12), __PT_CR1(%r11)
        jne     5f
        BPENTER __SF_SIE_FLAGS(%r10),_TIF_ISOLATE_BP_GUEST
index 78cd5084104e9c205a6e949f6ee1ce6b93060fb0..4367aa77cb8d9f6f18adabebe39d3ef0ddc4dcf5 100644 (file)
@@ -1693,6 +1693,7 @@ void x86_perf_get_lbr(struct x86_pmu_lbr *lbr)
        lbr->from = x86_pmu.lbr_from;
        lbr->to = x86_pmu.lbr_to;
        lbr->info = x86_pmu.lbr_info;
+       lbr->has_callstack = x86_pmu_has_lbr_callstack();
 }
 EXPORT_SYMBOL_GPL(x86_perf_get_lbr);
 
index 16e07a2eee195d48e29536dc69c5d6e975c99d7f..6efd1497b02636bcabfcbd10aa02a618a089c554 100644 (file)
@@ -855,6 +855,7 @@ struct kvm_vcpu_arch {
        int cpuid_nent;
        struct kvm_cpuid_entry2 *cpuid_entries;
        struct kvm_hypervisor_cpuid kvm_cpuid;
+       bool is_amd_compatible;
 
        /*
         * FIXME: Drop this macro and use KVM_NR_GOVERNED_FEATURES directly
index 3736b8a46c04de58784396e10b016c51966ed43f..7f1e17250546bdb02e948907e23598097652e85a 100644 (file)
@@ -555,6 +555,7 @@ struct x86_pmu_lbr {
        unsigned int    from;
        unsigned int    to;
        unsigned int    info;
+       bool            has_callstack;
 };
 
 extern void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap);
index a88bb14266b69fe9805cb864cbe4c02e928e460b..addc44fc7187d63b5ed8c9acc7790efd61d4cf5c 100644 (file)
@@ -3,11 +3,6 @@
 ccflags-y += -I $(srctree)/arch/x86/kvm
 ccflags-$(CONFIG_KVM_WERROR) += -Werror
 
-ifeq ($(CONFIG_FRAME_POINTER),y)
-OBJECT_FILES_NON_STANDARD_vmx/vmenter.o := y
-OBJECT_FILES_NON_STANDARD_svm/vmenter.o := y
-endif
-
 include $(srctree)/virt/kvm/Makefile.kvm
 
 kvm-y                  += x86.o emulate.o i8259.o irq.o lapic.o \
index bfc0bfcb2bc60dd2860fa4617f3dc92dea1f3a97..77352a4abd87f839a0a5b7adfb54301cb13ce02c 100644 (file)
@@ -376,6 +376,7 @@ static void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
 
        kvm_update_pv_runtime(vcpu);
 
+       vcpu->arch.is_amd_compatible = guest_cpuid_is_amd_or_hygon(vcpu);
        vcpu->arch.maxphyaddr = cpuid_query_maxphyaddr(vcpu);
        vcpu->arch.reserved_gpa_bits = kvm_vcpu_reserved_gpa_bits_raw(vcpu);
 
index 856e3037e74f3ffc7fdeb72f2067812080d71910..23dbb9eb277c7465f19bc5af137b79d5a2b894d1 100644 (file)
@@ -120,6 +120,16 @@ static inline bool guest_cpuid_is_intel(struct kvm_vcpu *vcpu)
        return best && is_guest_vendor_intel(best->ebx, best->ecx, best->edx);
 }
 
+static inline bool guest_cpuid_is_amd_compatible(struct kvm_vcpu *vcpu)
+{
+       return vcpu->arch.is_amd_compatible;
+}
+
+static inline bool guest_cpuid_is_intel_compatible(struct kvm_vcpu *vcpu)
+{
+       return !guest_cpuid_is_amd_compatible(vcpu);
+}
+
 static inline int guest_cpuid_family(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpuid_entry2 *best;
index cf37586f04668df976c983e89b7c37ae3c58e23a..ebf41023be38293dbc248d75a7125b63cd46c189 100644 (file)
@@ -2776,7 +2776,8 @@ int kvm_apic_local_deliver(struct kvm_lapic *apic, int lvt_type)
                trig_mode = reg & APIC_LVT_LEVEL_TRIGGER;
 
                r = __apic_accept_irq(apic, mode, vector, 1, trig_mode, NULL);
-               if (r && lvt_type == APIC_LVTPC)
+               if (r && lvt_type == APIC_LVTPC &&
+                   guest_cpuid_is_intel_compatible(apic->vcpu))
                        kvm_lapic_set_reg(apic, APIC_LVTPC, reg | APIC_LVT_MASKED);
                return r;
        }
index 992e651540e8523aadbd15f2cb8dc748850c6a49..db007a4dffa2e1ae11fced21f052f7fd23f68a7e 100644 (file)
@@ -4935,7 +4935,7 @@ static void reset_guest_rsvds_bits_mask(struct kvm_vcpu *vcpu,
                                context->cpu_role.base.level, is_efer_nx(context),
                                guest_can_use(vcpu, X86_FEATURE_GBPAGES),
                                is_cr4_pse(context),
-                               guest_cpuid_is_amd_or_hygon(vcpu));
+                               guest_cpuid_is_amd_compatible(vcpu));
 }
 
 static void __reset_rsvds_bits_mask_ept(struct rsvd_bits_validate *rsvd_check,
@@ -5576,9 +5576,9 @@ void kvm_mmu_after_set_cpuid(struct kvm_vcpu *vcpu)
         * that problem is swept under the rug; KVM's CPUID API is horrific and
         * it's all but impossible to solve it without introducing a new API.
         */
-       vcpu->arch.root_mmu.root_role.word = 0;
-       vcpu->arch.guest_mmu.root_role.word = 0;
-       vcpu->arch.nested_mmu.root_role.word = 0;
+       vcpu->arch.root_mmu.root_role.invalid = 1;
+       vcpu->arch.guest_mmu.root_role.invalid = 1;
+       vcpu->arch.nested_mmu.root_role.invalid = 1;
        vcpu->arch.root_mmu.cpu_role.ext.valid = 0;
        vcpu->arch.guest_mmu.cpu_role.ext.valid = 0;
        vcpu->arch.nested_mmu.cpu_role.ext.valid = 0;
@@ -7399,7 +7399,8 @@ bool kvm_arch_post_set_memory_attributes(struct kvm *kvm,
                         * by the memslot, KVM can't use a hugepage due to the
                         * misaligned address regardless of memory attributes.
                         */
-                       if (gfn >= slot->base_gfn) {
+                       if (gfn >= slot->base_gfn &&
+                           gfn + nr_pages <= slot->base_gfn + slot->npages) {
                                if (hugepage_has_attrs(kvm, slot, gfn, level, attrs))
                                        hugepage_clear_mixed(slot, gfn, level);
                                else
index d078157e62aa4025e6a3a6411e0d6b118245f3b8..04c1f0957fea875a5a17b1eccc5efddb53996624 100644 (file)
@@ -1548,17 +1548,21 @@ void kvm_tdp_mmu_try_split_huge_pages(struct kvm *kvm,
        }
 }
 
-/*
- * Clear the dirty status of all the SPTEs mapping GFNs in the memslot. If
- * AD bits are enabled, this will involve clearing the dirty bit on each SPTE.
- * If AD bits are not enabled, this will require clearing the writable bit on
- * each SPTE. Returns true if an SPTE has been changed and the TLBs need to
- * be flushed.
- */
+static bool tdp_mmu_need_write_protect(struct kvm_mmu_page *sp)
+{
+       /*
+        * All TDP MMU shadow pages share the same role as their root, aside
+        * from level, so it is valid to key off any shadow page to determine if
+        * write protection is needed for an entire tree.
+        */
+       return kvm_mmu_page_ad_need_write_protect(sp) || !kvm_ad_enabled();
+}
+
 static bool clear_dirty_gfn_range(struct kvm *kvm, struct kvm_mmu_page *root,
                           gfn_t start, gfn_t end)
 {
-       u64 dbit = kvm_ad_enabled() ? shadow_dirty_mask : PT_WRITABLE_MASK;
+       const u64 dbit = tdp_mmu_need_write_protect(root) ? PT_WRITABLE_MASK :
+                                                           shadow_dirty_mask;
        struct tdp_iter iter;
        bool spte_set = false;
 
@@ -1573,7 +1577,7 @@ retry:
                if (tdp_mmu_iter_cond_resched(kvm, &iter, false, true))
                        continue;
 
-               KVM_MMU_WARN_ON(kvm_ad_enabled() &&
+               KVM_MMU_WARN_ON(dbit == shadow_dirty_mask &&
                                spte_ad_need_write_protect(iter.old_spte));
 
                if (!(iter.old_spte & dbit))
@@ -1590,11 +1594,9 @@ retry:
 }
 
 /*
- * Clear the dirty status of all the SPTEs mapping GFNs in the memslot. If
- * AD bits are enabled, this will involve clearing the dirty bit on each SPTE.
- * If AD bits are not enabled, this will require clearing the writable bit on
- * each SPTE. Returns true if an SPTE has been changed and the TLBs need to
- * be flushed.
+ * Clear the dirty status (D-bit or W-bit) of all the SPTEs mapping GFNs in the
+ * memslot. Returns true if an SPTE has been changed and the TLBs need to be
+ * flushed.
  */
 bool kvm_tdp_mmu_clear_dirty_slot(struct kvm *kvm,
                                  const struct kvm_memory_slot *slot)
@@ -1610,18 +1612,11 @@ bool kvm_tdp_mmu_clear_dirty_slot(struct kvm *kvm,
        return spte_set;
 }
 
-/*
- * Clears the dirty status of all the 4k SPTEs mapping GFNs for which a bit is
- * set in mask, starting at gfn. The given memslot is expected to contain all
- * the GFNs represented by set bits in the mask. If AD bits are enabled,
- * clearing the dirty status will involve clearing the dirty bit on each SPTE
- * or, if AD bits are not enabled, clearing the writable bit on each SPTE.
- */
 static void clear_dirty_pt_masked(struct kvm *kvm, struct kvm_mmu_page *root,
                                  gfn_t gfn, unsigned long mask, bool wrprot)
 {
-       u64 dbit = (wrprot || !kvm_ad_enabled()) ? PT_WRITABLE_MASK :
-                                                  shadow_dirty_mask;
+       const u64 dbit = (wrprot || tdp_mmu_need_write_protect(root)) ? PT_WRITABLE_MASK :
+                                                                       shadow_dirty_mask;
        struct tdp_iter iter;
 
        lockdep_assert_held_write(&kvm->mmu_lock);
@@ -1633,7 +1628,7 @@ static void clear_dirty_pt_masked(struct kvm *kvm, struct kvm_mmu_page *root,
                if (!mask)
                        break;
 
-               KVM_MMU_WARN_ON(kvm_ad_enabled() &&
+               KVM_MMU_WARN_ON(dbit == shadow_dirty_mask &&
                                spte_ad_need_write_protect(iter.old_spte));
 
                if (iter.level > PG_LEVEL_4K ||
@@ -1659,11 +1654,9 @@ static void clear_dirty_pt_masked(struct kvm *kvm, struct kvm_mmu_page *root,
 }
 
 /*
- * Clears the dirty status of all the 4k SPTEs mapping GFNs for which a bit is
- * set in mask, starting at gfn. The given memslot is expected to contain all
- * the GFNs represented by set bits in the mask. If AD bits are enabled,
- * clearing the dirty status will involve clearing the dirty bit on each SPTE
- * or, if AD bits are not enabled, clearing the writable bit on each SPTE.
+ * Clear the dirty status (D-bit or W-bit) of all the 4k SPTEs mapping GFNs for
+ * which a bit is set in mask, starting at gfn. The given memslot is expected to
+ * contain all the GFNs represented by set bits in the mask.
  */
 void kvm_tdp_mmu_clear_dirty_pt_masked(struct kvm *kvm,
                                       struct kvm_memory_slot *slot,
index c397b28e3d1b680788249daa32f36c12c80bd1a1..a593b03c9aed677efb34c5925c57887023bae0f4 100644 (file)
@@ -775,8 +775,20 @@ void kvm_pmu_refresh(struct kvm_vcpu *vcpu)
        pmu->pebs_data_cfg_mask = ~0ull;
        bitmap_zero(pmu->all_valid_pmc_idx, X86_PMC_IDX_MAX);
 
-       if (vcpu->kvm->arch.enable_pmu)
-               static_call(kvm_x86_pmu_refresh)(vcpu);
+       if (!vcpu->kvm->arch.enable_pmu)
+               return;
+
+       static_call(kvm_x86_pmu_refresh)(vcpu);
+
+       /*
+        * At RESET, both Intel and AMD CPUs set all enable bits for general
+        * purpose counters in IA32_PERF_GLOBAL_CTRL (so that software that
+        * was written for v1 PMUs don't unknowingly leave GP counters disabled
+        * in the global controls).  Emulate that behavior when refreshing the
+        * PMU so that userspace doesn't need to manually set PERF_GLOBAL_CTRL.
+        */
+       if (kvm_pmu_has_perf_global_ctrl(pmu) && pmu->nr_arch_gp_counters)
+               pmu->global_ctrl = GENMASK_ULL(pmu->nr_arch_gp_counters - 1, 0);
 }
 
 void kvm_pmu_init(struct kvm_vcpu *vcpu)
index 61a7531d41b019a7f263b9c4e02ccfdf960dd09f..759581bb2128da1829b52e854329b6151147c9f8 100644 (file)
@@ -434,7 +434,7 @@ static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr,
        /* Avoid using vmalloc for smaller buffers. */
        size = npages * sizeof(struct page *);
        if (size > PAGE_SIZE)
-               pages = __vmalloc(size, GFP_KERNEL_ACCOUNT | __GFP_ZERO);
+               pages = __vmalloc(size, GFP_KERNEL_ACCOUNT);
        else
                pages = kmalloc(size, GFP_KERNEL_ACCOUNT);
 
index d1a9f9951635819c7a585882f06bcf6415ac2cdc..9aaf83c8d57df7d3877484a87060769956dbb9cb 100644 (file)
@@ -1503,6 +1503,11 @@ static void svm_vcpu_free(struct kvm_vcpu *vcpu)
        __free_pages(virt_to_page(svm->msrpm), get_order(MSRPM_SIZE));
 }
 
+static struct sev_es_save_area *sev_es_host_save_area(struct svm_cpu_data *sd)
+{
+       return page_address(sd->save_area) + 0x400;
+}
+
 static void svm_prepare_switch_to_guest(struct kvm_vcpu *vcpu)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
@@ -1519,12 +1524,8 @@ static void svm_prepare_switch_to_guest(struct kvm_vcpu *vcpu)
         * or subsequent vmload of host save area.
         */
        vmsave(sd->save_area_pa);
-       if (sev_es_guest(vcpu->kvm)) {
-               struct sev_es_save_area *hostsa;
-               hostsa = (struct sev_es_save_area *)(page_address(sd->save_area) + 0x400);
-
-               sev_es_prepare_switch_to_guest(hostsa);
-       }
+       if (sev_es_guest(vcpu->kvm))
+               sev_es_prepare_switch_to_guest(sev_es_host_save_area(sd));
 
        if (tsc_scaling)
                __svm_write_tsc_multiplier(vcpu->arch.tsc_scaling_ratio);
@@ -4101,6 +4102,7 @@ static fastpath_t svm_exit_handlers_fastpath(struct kvm_vcpu *vcpu)
 
 static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu, bool spec_ctrl_intercepted)
 {
+       struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, vcpu->cpu);
        struct vcpu_svm *svm = to_svm(vcpu);
 
        guest_state_enter_irqoff();
@@ -4108,7 +4110,8 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu, bool spec_ctrl_in
        amd_clear_divider();
 
        if (sev_es_guest(vcpu->kvm))
-               __svm_sev_es_vcpu_run(svm, spec_ctrl_intercepted);
+               __svm_sev_es_vcpu_run(svm, spec_ctrl_intercepted,
+                                     sev_es_host_save_area(sd));
        else
                __svm_vcpu_run(svm, spec_ctrl_intercepted);
 
index 7f1fbd874c4582b0b6d3735b62c3c85de2021074..33878efdebc82987efb574ce1e49e2f3df5637b8 100644 (file)
@@ -698,7 +698,8 @@ struct page *snp_safe_alloc_page(struct kvm_vcpu *vcpu);
 
 /* vmenter.S */
 
-void __svm_sev_es_vcpu_run(struct vcpu_svm *svm, bool spec_ctrl_intercepted);
+void __svm_sev_es_vcpu_run(struct vcpu_svm *svm, bool spec_ctrl_intercepted,
+                          struct sev_es_save_area *hostsa);
 void __svm_vcpu_run(struct vcpu_svm *svm, bool spec_ctrl_intercepted);
 
 #define DEFINE_KVM_GHCB_ACCESSORS(field)                                               \
index 187018c424bfb4ba8cadfa71a0f4ec7d4c63d766..a0c8eb37d3e1c62dc4390e6b61ccbbeff6845bff 100644 (file)
@@ -3,6 +3,7 @@
 #include <asm/asm.h>
 #include <asm/asm-offsets.h>
 #include <asm/bitsperlong.h>
+#include <asm/frame.h>
 #include <asm/kvm_vcpu_regs.h>
 #include <asm/nospec-branch.h>
 #include "kvm-asm-offsets.h"
@@ -67,7 +68,7 @@
                "", X86_FEATURE_V_SPEC_CTRL
 901:
 .endm
-.macro RESTORE_HOST_SPEC_CTRL_BODY
+.macro RESTORE_HOST_SPEC_CTRL_BODY spec_ctrl_intercepted:req
 900:
        /* Same for after vmexit.  */
        mov $MSR_IA32_SPEC_CTRL, %ecx
@@ -76,7 +77,7 @@
         * Load the value that the guest had written into MSR_IA32_SPEC_CTRL,
         * if it was not intercepted during guest execution.
         */
-       cmpb $0, (%_ASM_SP)
+       cmpb $0, \spec_ctrl_intercepted
        jnz 998f
        rdmsr
        movl %eax, SVM_spec_ctrl(%_ASM_DI)
  */
 SYM_FUNC_START(__svm_vcpu_run)
        push %_ASM_BP
+       mov  %_ASM_SP, %_ASM_BP
 #ifdef CONFIG_X86_64
        push %r15
        push %r14
@@ -268,7 +270,7 @@ SYM_FUNC_START(__svm_vcpu_run)
        RET
 
        RESTORE_GUEST_SPEC_CTRL_BODY
-       RESTORE_HOST_SPEC_CTRL_BODY
+       RESTORE_HOST_SPEC_CTRL_BODY (%_ASM_SP)
 
 10:    cmpb $0, _ASM_RIP(kvm_rebooting)
        jne 2b
@@ -290,66 +292,68 @@ SYM_FUNC_START(__svm_vcpu_run)
 
 SYM_FUNC_END(__svm_vcpu_run)
 
+#ifdef CONFIG_KVM_AMD_SEV
+
+
+#ifdef CONFIG_X86_64
+#define SEV_ES_GPRS_BASE 0x300
+#define SEV_ES_RBX     (SEV_ES_GPRS_BASE + __VCPU_REGS_RBX * WORD_SIZE)
+#define SEV_ES_RBP     (SEV_ES_GPRS_BASE + __VCPU_REGS_RBP * WORD_SIZE)
+#define SEV_ES_RSI     (SEV_ES_GPRS_BASE + __VCPU_REGS_RSI * WORD_SIZE)
+#define SEV_ES_RDI     (SEV_ES_GPRS_BASE + __VCPU_REGS_RDI * WORD_SIZE)
+#define SEV_ES_R12     (SEV_ES_GPRS_BASE + __VCPU_REGS_R12 * WORD_SIZE)
+#define SEV_ES_R13     (SEV_ES_GPRS_BASE + __VCPU_REGS_R13 * WORD_SIZE)
+#define SEV_ES_R14     (SEV_ES_GPRS_BASE + __VCPU_REGS_R14 * WORD_SIZE)
+#define SEV_ES_R15     (SEV_ES_GPRS_BASE + __VCPU_REGS_R15 * WORD_SIZE)
+#endif
+
 /**
  * __svm_sev_es_vcpu_run - Run a SEV-ES vCPU via a transition to SVM guest mode
  * @svm:       struct vcpu_svm *
  * @spec_ctrl_intercepted: bool
  */
 SYM_FUNC_START(__svm_sev_es_vcpu_run)
-       push %_ASM_BP
-#ifdef CONFIG_X86_64
-       push %r15
-       push %r14
-       push %r13
-       push %r12
-#else
-       push %edi
-       push %esi
-#endif
-       push %_ASM_BX
+       FRAME_BEGIN
 
        /*
-        * Save variables needed after vmexit on the stack, in inverse
-        * order compared to when they are needed.
+        * Save non-volatile (callee-saved) registers to the host save area.
+        * Except for RAX and RSP, all GPRs are restored on #VMEXIT, but not
+        * saved on VMRUN.
         */
+       mov %rbp, SEV_ES_RBP (%rdx)
+       mov %r15, SEV_ES_R15 (%rdx)
+       mov %r14, SEV_ES_R14 (%rdx)
+       mov %r13, SEV_ES_R13 (%rdx)
+       mov %r12, SEV_ES_R12 (%rdx)
+       mov %rbx, SEV_ES_RBX (%rdx)
 
-       /* Accessed directly from the stack in RESTORE_HOST_SPEC_CTRL.  */
-       push %_ASM_ARG2
-
-       /* Save @svm. */
-       push %_ASM_ARG1
-
-.ifnc _ASM_ARG1, _ASM_DI
        /*
-        * Stash @svm in RDI early. On 32-bit, arguments are in RAX, RCX
-        * and RDX which are clobbered by RESTORE_GUEST_SPEC_CTRL.
+        * Save volatile registers that hold arguments that are needed after
+        * #VMEXIT (RDI=@svm and RSI=@spec_ctrl_intercepted).
         */
-       mov %_ASM_ARG1, %_ASM_DI
-.endif
+       mov %rdi, SEV_ES_RDI (%rdx)
+       mov %rsi, SEV_ES_RSI (%rdx)
 
-       /* Clobbers RAX, RCX, RDX */
+       /* Clobbers RAX, RCX, RDX (@hostsa). */
        RESTORE_GUEST_SPEC_CTRL
 
        /* Get svm->current_vmcb->pa into RAX. */
-       mov SVM_current_vmcb(%_ASM_DI), %_ASM_AX
-       mov KVM_VMCB_pa(%_ASM_AX), %_ASM_AX
+       mov SVM_current_vmcb(%rdi), %rax
+       mov KVM_VMCB_pa(%rax), %rax
 
        /* Enter guest mode */
        sti
 
-1:     vmrun %_ASM_AX
+1:     vmrun %rax
 
 2:     cli
 
-       /* Pop @svm to RDI, guest registers have been saved already. */
-       pop %_ASM_DI
-
 #ifdef CONFIG_MITIGATION_RETPOLINE
        /* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */
-       FILL_RETURN_BUFFER %_ASM_AX, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE
+       FILL_RETURN_BUFFER %rax, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE
 #endif
 
-       /* Clobbers RAX, RCX, RDX */
+       /* Clobbers RAX, RCX, RDX, consumes RDI (@svm) and RSI (@spec_ctrl_intercepted). */
        RESTORE_HOST_SPEC_CTRL
 
        /*
@@ -361,30 +365,17 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run)
         */
        UNTRAIN_RET_VM
 
-       /* "Pop" @spec_ctrl_intercepted.  */
-       pop %_ASM_BX
-
-       pop %_ASM_BX
-
-#ifdef CONFIG_X86_64
-       pop %r12
-       pop %r13
-       pop %r14
-       pop %r15
-#else
-       pop %esi
-       pop %edi
-#endif
-       pop %_ASM_BP
+       FRAME_END
        RET
 
        RESTORE_GUEST_SPEC_CTRL_BODY
-       RESTORE_HOST_SPEC_CTRL_BODY
+       RESTORE_HOST_SPEC_CTRL_BODY %sil
 
-3:     cmpb $0, _ASM_RIP(kvm_rebooting)
+3:     cmpb $0, kvm_rebooting(%rip)
        jne 2b
        ud2
 
        _ASM_EXTABLE(1b, 3b)
 
 SYM_FUNC_END(__svm_sev_es_vcpu_run)
+#endif /* CONFIG_KVM_AMD_SEV */
index 12ade343a17ed5c7aaa2efc1ebf3b3b40046d907..be40474de6e4dbd28379780c075385a79ed776d2 100644 (file)
@@ -535,7 +535,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
        perf_capabilities = vcpu_get_perf_capabilities(vcpu);
        if (cpuid_model_is_consistent(vcpu) &&
            (perf_capabilities & PMU_CAP_LBR_FMT))
-               x86_perf_get_lbr(&lbr_desc->records);
+               memcpy(&lbr_desc->records, &vmx_lbr_caps, sizeof(vmx_lbr_caps));
        else
                lbr_desc->records.nr = 0;
 
index c37a89eda90f8219de02c96452a5cdbe5d13da83..22411f4aff5303db5b27ee737ba1565f91585bd1 100644 (file)
@@ -218,6 +218,8 @@ module_param(ple_window_max, uint, 0444);
 int __read_mostly pt_mode = PT_MODE_SYSTEM;
 module_param(pt_mode, int, S_IRUGO);
 
+struct x86_pmu_lbr __ro_after_init vmx_lbr_caps;
+
 static DEFINE_STATIC_KEY_FALSE(vmx_l1d_should_flush);
 static DEFINE_STATIC_KEY_FALSE(vmx_l1d_flush_cond);
 static DEFINE_MUTEX(vmx_l1d_flush_mutex);
@@ -7862,10 +7864,9 @@ static void vmx_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
        vmx_update_exception_bitmap(vcpu);
 }
 
-static u64 vmx_get_perf_capabilities(void)
+static __init u64 vmx_get_perf_capabilities(void)
 {
        u64 perf_cap = PMU_CAP_FW_WRITES;
-       struct x86_pmu_lbr lbr;
        u64 host_perf_cap = 0;
 
        if (!enable_pmu)
@@ -7875,15 +7876,43 @@ static u64 vmx_get_perf_capabilities(void)
                rdmsrl(MSR_IA32_PERF_CAPABILITIES, host_perf_cap);
 
        if (!cpu_feature_enabled(X86_FEATURE_ARCH_LBR)) {
-               x86_perf_get_lbr(&lbr);
-               if (lbr.nr)
+               x86_perf_get_lbr(&vmx_lbr_caps);
+
+               /*
+                * KVM requires LBR callstack support, as the overhead due to
+                * context switching LBRs without said support is too high.
+                * See intel_pmu_create_guest_lbr_event() for more info.
+                */
+               if (!vmx_lbr_caps.has_callstack)
+                       memset(&vmx_lbr_caps, 0, sizeof(vmx_lbr_caps));
+               else if (vmx_lbr_caps.nr)
                        perf_cap |= host_perf_cap & PMU_CAP_LBR_FMT;
        }
 
        if (vmx_pebs_supported()) {
                perf_cap |= host_perf_cap & PERF_CAP_PEBS_MASK;
-               if ((perf_cap & PERF_CAP_PEBS_FORMAT) < 4)
-                       perf_cap &= ~PERF_CAP_PEBS_BASELINE;
+
+               /*
+                * Disallow adaptive PEBS as it is functionally broken, can be
+                * used by the guest to read *host* LBRs, and can be used to
+                * bypass userspace event filters.  To correctly and safely
+                * support adaptive PEBS, KVM needs to:
+                *
+                * 1. Account for the ADAPTIVE flag when (re)programming fixed
+                *    counters.
+                *
+                * 2. Gain support from perf (or take direct control of counter
+                *    programming) to support events without adaptive PEBS
+                *    enabled for the hardware counter.
+                *
+                * 3. Ensure LBR MSRs cannot hold host data on VM-Entry with
+                *    adaptive PEBS enabled and MSR_PEBS_DATA_CFG.LBRS=1.
+                *
+                * 4. Document which PMU events are effectively exposed to the
+                *    guest via adaptive PEBS, and make adaptive PEBS mutually
+                *    exclusive with KVM_SET_PMU_EVENT_FILTER if necessary.
+                */
+               perf_cap &= ~PERF_CAP_PEBS_BASELINE;
        }
 
        return perf_cap;
index 65786dbe7d60bdf753db779312bb70754ccc6f1e..90f9e443464645507ba767d246290e13079fa397 100644 (file)
@@ -15,6 +15,7 @@
 #include "vmx_ops.h"
 #include "../cpuid.h"
 #include "run_flags.h"
+#include "../mmu.h"
 
 #define MSR_TYPE_R     1
 #define MSR_TYPE_W     2
@@ -109,6 +110,8 @@ struct lbr_desc {
        bool msr_passthrough;
 };
 
+extern struct x86_pmu_lbr vmx_lbr_caps;
+
 /*
  * The nested_vmx structure is part of vcpu_vmx, and holds information we need
  * for correct emulation of VMX (i.e., nested VMX) on this vcpu.
@@ -719,7 +722,8 @@ static inline bool vmx_need_pf_intercept(struct kvm_vcpu *vcpu)
        if (!enable_ept)
                return true;
 
-       return allow_smaller_maxphyaddr && cpuid_maxphyaddr(vcpu) < boot_cpu_data.x86_phys_bits;
+       return allow_smaller_maxphyaddr &&
+              cpuid_maxphyaddr(vcpu) < kvm_get_shadow_phys_bits();
 }
 
 static inline bool is_unrestricted_guest(struct kvm_vcpu *vcpu)
index 984ea2089efc3132154527508976879a4e11cb10..91478b769af0896cd8bdb8db9bc0ff0861a8d6f5 100644 (file)
@@ -3470,7 +3470,7 @@ static bool is_mci_status_msr(u32 msr)
 static bool can_set_mci_status(struct kvm_vcpu *vcpu)
 {
        /* McStatusWrEn enabled? */
-       if (guest_cpuid_is_amd_or_hygon(vcpu))
+       if (guest_cpuid_is_amd_compatible(vcpu))
                return !!(vcpu->arch.msr_hwcr & BIT_ULL(18));
 
        return false;
index 456be28ba67cb476846c83c532e7bd04e521463f..2597cb43f43871dc0dc629c13b0b0ee3acf1398a 100644 (file)
@@ -702,7 +702,7 @@ static void extract_entropy(void *buf, size_t len)
 
 static void __cold _credit_init_bits(size_t bits)
 {
-       static struct execute_work set_ready;
+       static DECLARE_WORK(set_ready, crng_set_ready);
        unsigned int new, orig, add;
        unsigned long flags;
 
@@ -718,8 +718,8 @@ static void __cold _credit_init_bits(size_t bits)
 
        if (orig < POOL_READY_BITS && new >= POOL_READY_BITS) {
                crng_reseed(NULL); /* Sets crng_init to CRNG_READY under base_crng.lock. */
-               if (static_key_initialized)
-                       execute_in_process_context(crng_set_ready, &set_ready);
+               if (static_key_initialized && system_unbound_wq)
+                       queue_work(system_unbound_wq, &set_ready);
                atomic_notifier_call_chain(&random_ready_notifier, 0, NULL);
                wake_up_interruptible(&crng_init_wait);
                kill_fasync(&fasync, SIGIO, POLL_IN);
@@ -890,8 +890,8 @@ void __init random_init(void)
 
        /*
         * If we were initialized by the cpu or bootloader before jump labels
-        * are initialized, then we should enable the static branch here, where
-        * it's guaranteed that jump labels have been initialized.
+        * or workqueues are initialized, then we should enable the static
+        * branch here, where it's guaranteed that these have been initialized.
         */
        if (!static_branch_likely(&crng_is_ready) && crng_init >= CRNG_READY)
                crng_set_ready(NULL);
index 25371c91a58fe7cc45a0ae681221d25f801cafb7..8cca52be993f4c831660f0c0d13bac290a37e4de 100644 (file)
@@ -37,6 +37,10 @@ static HLIST_HEAD(clk_root_list);
 static HLIST_HEAD(clk_orphan_list);
 static LIST_HEAD(clk_notifier_list);
 
+/* List of registered clks that use runtime PM */
+static HLIST_HEAD(clk_rpm_list);
+static DEFINE_MUTEX(clk_rpm_list_lock);
+
 static const struct hlist_head *all_lists[] = {
        &clk_root_list,
        &clk_orphan_list,
@@ -59,6 +63,7 @@ struct clk_core {
        struct clk_hw           *hw;
        struct module           *owner;
        struct device           *dev;
+       struct hlist_node       rpm_node;
        struct device_node      *of_node;
        struct clk_core         *parent;
        struct clk_parent_map   *parents;
@@ -122,6 +127,89 @@ static void clk_pm_runtime_put(struct clk_core *core)
        pm_runtime_put_sync(core->dev);
 }
 
+/**
+ * clk_pm_runtime_get_all() - Runtime "get" all clk provider devices
+ *
+ * Call clk_pm_runtime_get() on all runtime PM enabled clks in the clk tree so
+ * that disabling unused clks avoids a deadlock where a device is runtime PM
+ * resuming/suspending and the runtime PM callback is trying to grab the
+ * prepare_lock for something like clk_prepare_enable() while
+ * clk_disable_unused_subtree() holds the prepare_lock and is trying to runtime
+ * PM resume/suspend the device as well.
+ *
+ * Context: Acquires the 'clk_rpm_list_lock' and returns with the lock held on
+ * success. Otherwise the lock is released on failure.
+ *
+ * Return: 0 on success, negative errno otherwise.
+ */
+static int clk_pm_runtime_get_all(void)
+{
+       int ret;
+       struct clk_core *core, *failed;
+
+       /*
+        * Grab the list lock to prevent any new clks from being registered
+        * or unregistered until clk_pm_runtime_put_all().
+        */
+       mutex_lock(&clk_rpm_list_lock);
+
+       /*
+        * Runtime PM "get" all the devices that are needed for the clks
+        * currently registered. Do this without holding the prepare_lock, to
+        * avoid the deadlock.
+        */
+       hlist_for_each_entry(core, &clk_rpm_list, rpm_node) {
+               ret = clk_pm_runtime_get(core);
+               if (ret) {
+                       failed = core;
+                       pr_err("clk: Failed to runtime PM get '%s' for clk '%s'\n",
+                              dev_name(failed->dev), failed->name);
+                       goto err;
+               }
+       }
+
+       return 0;
+
+err:
+       hlist_for_each_entry(core, &clk_rpm_list, rpm_node) {
+               if (core == failed)
+                       break;
+
+               clk_pm_runtime_put(core);
+       }
+       mutex_unlock(&clk_rpm_list_lock);
+
+       return ret;
+}
+
+/**
+ * clk_pm_runtime_put_all() - Runtime "put" all clk provider devices
+ *
+ * Put the runtime PM references taken in clk_pm_runtime_get_all() and release
+ * the 'clk_rpm_list_lock'.
+ */
+static void clk_pm_runtime_put_all(void)
+{
+       struct clk_core *core;
+
+       hlist_for_each_entry(core, &clk_rpm_list, rpm_node)
+               clk_pm_runtime_put(core);
+       mutex_unlock(&clk_rpm_list_lock);
+}
+
+static void clk_pm_runtime_init(struct clk_core *core)
+{
+       struct device *dev = core->dev;
+
+       if (dev && pm_runtime_enabled(dev)) {
+               core->rpm_enabled = true;
+
+               mutex_lock(&clk_rpm_list_lock);
+               hlist_add_head(&core->rpm_node, &clk_rpm_list);
+               mutex_unlock(&clk_rpm_list_lock);
+       }
+}
+
 /***           locking             ***/
 static void clk_prepare_lock(void)
 {
@@ -1381,9 +1469,6 @@ static void __init clk_unprepare_unused_subtree(struct clk_core *core)
        if (core->flags & CLK_IGNORE_UNUSED)
                return;
 
-       if (clk_pm_runtime_get(core))
-               return;
-
        if (clk_core_is_prepared(core)) {
                trace_clk_unprepare(core);
                if (core->ops->unprepare_unused)
@@ -1392,8 +1477,6 @@ static void __init clk_unprepare_unused_subtree(struct clk_core *core)
                        core->ops->unprepare(core->hw);
                trace_clk_unprepare_complete(core);
        }
-
-       clk_pm_runtime_put(core);
 }
 
 static void __init clk_disable_unused_subtree(struct clk_core *core)
@@ -1409,9 +1492,6 @@ static void __init clk_disable_unused_subtree(struct clk_core *core)
        if (core->flags & CLK_OPS_PARENT_ENABLE)
                clk_core_prepare_enable(core->parent);
 
-       if (clk_pm_runtime_get(core))
-               goto unprepare_out;
-
        flags = clk_enable_lock();
 
        if (core->enable_count)
@@ -1436,8 +1516,6 @@ static void __init clk_disable_unused_subtree(struct clk_core *core)
 
 unlock_out:
        clk_enable_unlock(flags);
-       clk_pm_runtime_put(core);
-unprepare_out:
        if (core->flags & CLK_OPS_PARENT_ENABLE)
                clk_core_disable_unprepare(core->parent);
 }
@@ -1453,6 +1531,7 @@ __setup("clk_ignore_unused", clk_ignore_unused_setup);
 static int __init clk_disable_unused(void)
 {
        struct clk_core *core;
+       int ret;
 
        if (clk_ignore_unused) {
                pr_warn("clk: Not disabling unused clocks\n");
@@ -1461,6 +1540,13 @@ static int __init clk_disable_unused(void)
 
        pr_info("clk: Disabling unused clocks\n");
 
+       ret = clk_pm_runtime_get_all();
+       if (ret)
+               return ret;
+       /*
+        * Grab the prepare lock to keep the clk topology stable while iterating
+        * over clks.
+        */
        clk_prepare_lock();
 
        hlist_for_each_entry(core, &clk_root_list, child_node)
@@ -1477,6 +1563,8 @@ static int __init clk_disable_unused(void)
 
        clk_prepare_unlock();
 
+       clk_pm_runtime_put_all();
+
        return 0;
 }
 late_initcall_sync(clk_disable_unused);
@@ -3252,9 +3340,7 @@ static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
 {
        struct clk_core *child;
 
-       clk_pm_runtime_get(c);
        clk_summary_show_one(s, c, level);
-       clk_pm_runtime_put(c);
 
        hlist_for_each_entry(child, &c->children, child_node)
                clk_summary_show_subtree(s, child, level + 1);
@@ -3264,11 +3350,15 @@ static int clk_summary_show(struct seq_file *s, void *data)
 {
        struct clk_core *c;
        struct hlist_head **lists = s->private;
+       int ret;
 
        seq_puts(s, "                                 enable  prepare  protect                                duty  hardware                            connection\n");
        seq_puts(s, "   clock                          count    count    count        rate   accuracy phase  cycle    enable   consumer                         id\n");
        seq_puts(s, "---------------------------------------------------------------------------------------------------------------------------------------------\n");
 
+       ret = clk_pm_runtime_get_all();
+       if (ret)
+               return ret;
 
        clk_prepare_lock();
 
@@ -3277,6 +3367,7 @@ static int clk_summary_show(struct seq_file *s, void *data)
                        clk_summary_show_subtree(s, c, 0);
 
        clk_prepare_unlock();
+       clk_pm_runtime_put_all();
 
        return 0;
 }
@@ -3324,8 +3415,14 @@ static int clk_dump_show(struct seq_file *s, void *data)
        struct clk_core *c;
        bool first_node = true;
        struct hlist_head **lists = s->private;
+       int ret;
+
+       ret = clk_pm_runtime_get_all();
+       if (ret)
+               return ret;
 
        seq_putc(s, '{');
+
        clk_prepare_lock();
 
        for (; *lists; lists++) {
@@ -3338,6 +3435,7 @@ static int clk_dump_show(struct seq_file *s, void *data)
        }
 
        clk_prepare_unlock();
+       clk_pm_runtime_put_all();
 
        seq_puts(s, "}\n");
        return 0;
@@ -3981,8 +4079,6 @@ static int __clk_core_init(struct clk_core *core)
        }
 
        clk_core_reparent_orphans_nolock();
-
-       kref_init(&core->ref);
 out:
        clk_pm_runtime_put(core);
 unlock:
@@ -4211,6 +4307,22 @@ static void clk_core_free_parent_map(struct clk_core *core)
        kfree(core->parents);
 }
 
+/* Free memory allocated for a struct clk_core */
+static void __clk_release(struct kref *ref)
+{
+       struct clk_core *core = container_of(ref, struct clk_core, ref);
+
+       if (core->rpm_enabled) {
+               mutex_lock(&clk_rpm_list_lock);
+               hlist_del(&core->rpm_node);
+               mutex_unlock(&clk_rpm_list_lock);
+       }
+
+       clk_core_free_parent_map(core);
+       kfree_const(core->name);
+       kfree(core);
+}
+
 static struct clk *
 __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
 {
@@ -4231,6 +4343,8 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
                goto fail_out;
        }
 
+       kref_init(&core->ref);
+
        core->name = kstrdup_const(init->name, GFP_KERNEL);
        if (!core->name) {
                ret = -ENOMEM;
@@ -4243,9 +4357,8 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
        }
        core->ops = init->ops;
 
-       if (dev && pm_runtime_enabled(dev))
-               core->rpm_enabled = true;
        core->dev = dev;
+       clk_pm_runtime_init(core);
        core->of_node = np;
        if (dev && dev->driver)
                core->owner = dev->driver->owner;
@@ -4285,12 +4398,10 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
        hw->clk = NULL;
 
 fail_create_clk:
-       clk_core_free_parent_map(core);
 fail_parents:
 fail_ops:
-       kfree_const(core->name);
 fail_name:
-       kfree(core);
+       kref_put(&core->ref, __clk_release);
 fail_out:
        return ERR_PTR(ret);
 }
@@ -4370,18 +4481,6 @@ int of_clk_hw_register(struct device_node *node, struct clk_hw *hw)
 }
 EXPORT_SYMBOL_GPL(of_clk_hw_register);
 
-/* Free memory allocated for a clock. */
-static void __clk_release(struct kref *ref)
-{
-       struct clk_core *core = container_of(ref, struct clk_core, ref);
-
-       lockdep_assert_held(&prepare_lock);
-
-       clk_core_free_parent_map(core);
-       kfree_const(core->name);
-       kfree(core);
-}
-
 /*
  * Empty clk_ops for unregistered clocks. These are used temporarily
  * after clk_unregister() was called on a clock and until last clock
@@ -4472,7 +4571,8 @@ void clk_unregister(struct clk *clk)
        if (ops == &clk_nodrv_ops) {
                pr_err("%s: unregistered clock: %s\n", __func__,
                       clk->core->name);
-               goto unlock;
+               clk_prepare_unlock();
+               return;
        }
        /*
         * Assign empty clock ops for consumers that might still hold
@@ -4506,11 +4606,10 @@ void clk_unregister(struct clk *clk)
        if (clk->core->protect_count)
                pr_warn("%s: unregistering protected clock: %s\n",
                                        __func__, clk->core->name);
+       clk_prepare_unlock();
 
        kref_put(&clk->core->ref, __clk_release);
        free_clk(clk);
-unlock:
-       clk_prepare_unlock();
 }
 EXPORT_SYMBOL_GPL(clk_unregister);
 
@@ -4669,13 +4768,11 @@ void __clk_put(struct clk *clk)
        if (clk->min_rate > 0 || clk->max_rate < ULONG_MAX)
                clk_set_rate_range_nolock(clk, 0, ULONG_MAX);
 
-       owner = clk->core->owner;
-       kref_put(&clk->core->ref, __clk_release);
-
        clk_prepare_unlock();
 
+       owner = clk->core->owner;
+       kref_put(&clk->core->ref, __clk_release);
        module_put(owner);
-
        free_clk(clk);
 }
 
index 449041f8abbc9a1cd97fa7d3807634653e677849..c8c023afe3e5adaf416ac413c7767812f7b97ab3 100644 (file)
@@ -156,7 +156,7 @@ static const struct mtk_gate infra_clks[] = {
        GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P1, "infra_pcie_peri_ck_26m_ck_p1",
                    "csw_infra_f26m_sel", 8),
        GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P2, "infra_pcie_peri_ck_26m_ck_p2",
-                   "csw_infra_f26m_sel", 9),
+                   "infra_pcie_peri_ck_26m_ck_p3", 9),
        GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P3, "infra_pcie_peri_ck_26m_ck_p3",
                    "csw_infra_f26m_sel", 10),
        /* INFRA1 */
index 2e55368dc4d82095b5baceb7b744a9ed4b1350b4..bd37ab4d1a9bb3252ae54a2f3a3d3d241b1daa3a 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/slab.h>
 
 #include "clk-mtk.h"
@@ -494,6 +495,16 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev,
                        return IS_ERR(base) ? PTR_ERR(base) : -ENOMEM;
        }
 
+
+       devm_pm_runtime_enable(&pdev->dev);
+       /*
+        * Do a pm_runtime_resume_and_get() to workaround a possible
+        * deadlock between clk_register() and the genpd framework.
+        */
+       r = pm_runtime_resume_and_get(&pdev->dev);
+       if (r)
+               return r;
+
        /* Calculate how many clk_hw_onecell_data entries to allocate */
        num_clks = mcd->num_clks + mcd->num_composite_clks;
        num_clks += mcd->num_fixed_clks + mcd->num_factor_clks;
@@ -574,6 +585,8 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev,
                        goto unregister_clks;
        }
 
+       pm_runtime_put(&pdev->dev);
+
        return r;
 
 unregister_clks:
@@ -604,6 +617,8 @@ free_data:
 free_base:
        if (mcd->shared_io && base)
                iounmap(base);
+
+       pm_runtime_put(&pdev->dev);
        return r;
 }
 
index 1ee62cd58582b6496f0536fa7c45e2dc0305797f..25db014494a4de9bb8c44d0b2bd39d8786c3bb59 100644 (file)
@@ -92,7 +92,7 @@ static inline int to_reg(int gpio, enum ctrl_register reg_type)
                case 0x5e:
                        return GPIOPANELCTL;
                default:
-                       return -EOPNOTSUPP;
+                       return -ENOTSUPP;
                }
        }
 
index 5ef8af8249806aa6c1b226ed4ab9219cca91d936..c097e310c9e841044a3ef214444170721d116537 100644 (file)
@@ -529,6 +529,7 @@ static const struct of_device_id lpc32xx_gpio_of_match[] = {
        { .compatible = "nxp,lpc3220-gpio", },
        { },
 };
+MODULE_DEVICE_TABLE(of, lpc32xx_gpio_of_match);
 
 static struct platform_driver lpc32xx_gpio_driver = {
        .driver         = {
index c18b6b47384f1b8b9a3a26c3ac7c5f125e82d365..94ca9d03c0949453abf3ad82e013698a7a97ffda 100644 (file)
@@ -104,7 +104,7 @@ static inline int to_reg(int gpio, enum ctrl_register type)
        unsigned int reg = type == CTRL_IN ? GPIO_IN_CTRL_BASE : GPIO_OUT_CTRL_BASE;
 
        if (gpio >= WCOVE_GPIO_NUM)
-               return -EOPNOTSUPP;
+               return -ENOTSUPP;
 
        return reg + gpio;
 }
index 0a4b09709cfb149078c6284f2a0908cbde928430..ec888fc6ead8df0ce52ec00439e5f22ca7f4e9ff 100644 (file)
@@ -819,7 +819,7 @@ retry:
 
        p->bytes_moved += ctx.bytes_moved;
        if (!amdgpu_gmc_vram_full_visible(&adev->gmc) &&
-           amdgpu_bo_in_cpu_visible_vram(bo))
+           amdgpu_res_cpu_visible(adev, bo->tbo.resource))
                p->bytes_moved_vis += ctx.bytes_moved;
 
        if (unlikely(r == -ENOMEM) && domain != bo->allowed_domains) {
index 010b0cb7693c9c3be5608f192cb19e583a285893..2099159a693fa02e7c508c3aecdc9f695498cecd 100644 (file)
@@ -617,8 +617,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
                return r;
 
        if (!amdgpu_gmc_vram_full_visible(&adev->gmc) &&
-           bo->tbo.resource->mem_type == TTM_PL_VRAM &&
-           amdgpu_bo_in_cpu_visible_vram(bo))
+           amdgpu_res_cpu_visible(adev, bo->tbo.resource))
                amdgpu_cs_report_moved_bytes(adev, ctx.bytes_moved,
                                             ctx.bytes_moved);
        else
@@ -1272,23 +1271,25 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, bool evict)
 void amdgpu_bo_get_memory(struct amdgpu_bo *bo,
                          struct amdgpu_mem_stats *stats)
 {
+       struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
+       struct ttm_resource *res = bo->tbo.resource;
        uint64_t size = amdgpu_bo_size(bo);
        struct drm_gem_object *obj;
        unsigned int domain;
        bool shared;
 
        /* Abort if the BO doesn't currently have a backing store */
-       if (!bo->tbo.resource)
+       if (!res)
                return;
 
        obj = &bo->tbo.base;
        shared = drm_gem_object_is_shared_for_memory_stats(obj);
 
-       domain = amdgpu_mem_type_to_domain(bo->tbo.resource->mem_type);
+       domain = amdgpu_mem_type_to_domain(res->mem_type);
        switch (domain) {
        case AMDGPU_GEM_DOMAIN_VRAM:
                stats->vram += size;
-               if (amdgpu_bo_in_cpu_visible_vram(bo))
+               if (amdgpu_res_cpu_visible(adev, bo->tbo.resource))
                        stats->visible_vram += size;
                if (shared)
                        stats->vram_shared += size;
@@ -1389,10 +1390,7 @@ vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
        /* Remember that this BO was accessed by the CPU */
        abo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
 
-       if (bo->resource->mem_type != TTM_PL_VRAM)
-               return 0;
-
-       if (amdgpu_bo_in_cpu_visible_vram(abo))
+       if (amdgpu_res_cpu_visible(adev, bo->resource))
                return 0;
 
        /* Can't move a pinned BO to visible VRAM */
@@ -1415,7 +1413,7 @@ vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
 
        /* this should never happen */
        if (bo->resource->mem_type == TTM_PL_VRAM &&
-           !amdgpu_bo_in_cpu_visible_vram(abo))
+           !amdgpu_res_cpu_visible(adev, bo->resource))
                return VM_FAULT_SIGBUS;
 
        ttm_bo_move_to_lru_tail_unlocked(bo);
@@ -1579,6 +1577,7 @@ uint32_t amdgpu_bo_get_preferred_domain(struct amdgpu_device *adev,
  */
 u64 amdgpu_bo_print_info(int id, struct amdgpu_bo *bo, struct seq_file *m)
 {
+       struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
        struct dma_buf_attachment *attachment;
        struct dma_buf *dma_buf;
        const char *placement;
@@ -1587,10 +1586,11 @@ u64 amdgpu_bo_print_info(int id, struct amdgpu_bo *bo, struct seq_file *m)
 
        if (dma_resv_trylock(bo->tbo.base.resv)) {
                unsigned int domain;
+
                domain = amdgpu_mem_type_to_domain(bo->tbo.resource->mem_type);
                switch (domain) {
                case AMDGPU_GEM_DOMAIN_VRAM:
-                       if (amdgpu_bo_in_cpu_visible_vram(bo))
+                       if (amdgpu_res_cpu_visible(adev, bo->tbo.resource))
                                placement = "VRAM VISIBLE";
                        else
                                placement = "VRAM";
index be679c42b0b8cb5d127910803e79593910c72952..fa03d9e4874cc65b39e038014ab15fc4e58ba858 100644 (file)
@@ -250,28 +250,6 @@ static inline u64 amdgpu_bo_mmap_offset(struct amdgpu_bo *bo)
        return drm_vma_node_offset_addr(&bo->tbo.base.vma_node);
 }
 
-/**
- * amdgpu_bo_in_cpu_visible_vram - check if BO is (partly) in visible VRAM
- */
-static inline bool amdgpu_bo_in_cpu_visible_vram(struct amdgpu_bo *bo)
-{
-       struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
-       struct amdgpu_res_cursor cursor;
-
-       if (!bo->tbo.resource || bo->tbo.resource->mem_type != TTM_PL_VRAM)
-               return false;
-
-       amdgpu_res_first(bo->tbo.resource, 0, amdgpu_bo_size(bo), &cursor);
-       while (cursor.remaining) {
-               if (cursor.start < adev->gmc.visible_vram_size)
-                       return true;
-
-               amdgpu_res_next(&cursor, cursor.size);
-       }
-
-       return false;
-}
-
 /**
  * amdgpu_bo_explicit_sync - return whether the bo is explicitly synced
  */
index fc418e670fdae27b699bdbefce8051ab128ab76c..1d71729e3f6bcef2c02f9e1ce252dc6cd6461b94 100644 (file)
@@ -133,7 +133,7 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo,
 
                } else if (!amdgpu_gmc_vram_full_visible(&adev->gmc) &&
                           !(abo->flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) &&
-                          amdgpu_bo_in_cpu_visible_vram(abo)) {
+                          amdgpu_res_cpu_visible(adev, bo->resource)) {
 
                        /* Try evicting to the CPU inaccessible part of VRAM
                         * first, but only set GTT as busy placement, so this
@@ -403,40 +403,55 @@ error:
        return r;
 }
 
-/*
- * amdgpu_mem_visible - Check that memory can be accessed by ttm_bo_move_memcpy
+/**
+ * amdgpu_res_cpu_visible - Check that resource can be accessed by CPU
+ * @adev: amdgpu device
+ * @res: the resource to check
  *
- * Called by amdgpu_bo_move()
+ * Returns: true if the full resource is CPU visible, false otherwise.
  */
-static bool amdgpu_mem_visible(struct amdgpu_device *adev,
-                              struct ttm_resource *mem)
+bool amdgpu_res_cpu_visible(struct amdgpu_device *adev,
+                           struct ttm_resource *res)
 {
-       u64 mem_size = (u64)mem->size;
        struct amdgpu_res_cursor cursor;
-       u64 end;
 
-       if (mem->mem_type == TTM_PL_SYSTEM ||
-           mem->mem_type == TTM_PL_TT)
+       if (!res)
+               return false;
+
+       if (res->mem_type == TTM_PL_SYSTEM || res->mem_type == TTM_PL_TT ||
+           res->mem_type == AMDGPU_PL_PREEMPT)
                return true;
-       if (mem->mem_type != TTM_PL_VRAM)
+
+       if (res->mem_type != TTM_PL_VRAM)
                return false;
 
-       amdgpu_res_first(mem, 0, mem_size, &cursor);
-       end = cursor.start + cursor.size;
+       amdgpu_res_first(res, 0, res->size, &cursor);
        while (cursor.remaining) {
+               if ((cursor.start + cursor.size) >= adev->gmc.visible_vram_size)
+                       return false;
                amdgpu_res_next(&cursor, cursor.size);
+       }
 
-               if (!cursor.remaining)
-                       break;
+       return true;
+}
 
-               /* ttm_resource_ioremap only supports contiguous memory */
-               if (end != cursor.start)
-                       return false;
+/*
+ * amdgpu_res_copyable - Check that memory can be accessed by ttm_bo_move_memcpy
+ *
+ * Called by amdgpu_bo_move()
+ */
+static bool amdgpu_res_copyable(struct amdgpu_device *adev,
+                               struct ttm_resource *mem)
+{
+       if (!amdgpu_res_cpu_visible(adev, mem))
+               return false;
 
-               end = cursor.start + cursor.size;
-       }
+       /* ttm_resource_ioremap only supports contiguous memory */
+       if (mem->mem_type == TTM_PL_VRAM &&
+           !(mem->placement & TTM_PL_FLAG_CONTIGUOUS))
+               return false;
 
-       return end <= adev->gmc.visible_vram_size;
+       return true;
 }
 
 /*
@@ -529,8 +544,8 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
 
        if (r) {
                /* Check that all memory is CPU accessible */
-               if (!amdgpu_mem_visible(adev, old_mem) ||
-                   !amdgpu_mem_visible(adev, new_mem)) {
+               if (!amdgpu_res_copyable(adev, old_mem) ||
+                   !amdgpu_res_copyable(adev, new_mem)) {
                        pr_err("Move buffer fallback to memcpy unavailable\n");
                        return r;
                }
@@ -557,7 +572,6 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_device *bdev,
                                     struct ttm_resource *mem)
 {
        struct amdgpu_device *adev = amdgpu_ttm_adev(bdev);
-       size_t bus_size = (size_t)mem->size;
 
        switch (mem->mem_type) {
        case TTM_PL_SYSTEM:
@@ -568,9 +582,6 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_device *bdev,
                break;
        case TTM_PL_VRAM:
                mem->bus.offset = mem->start << PAGE_SHIFT;
-               /* check if it's visible */
-               if ((mem->bus.offset + bus_size) > adev->gmc.visible_vram_size)
-                       return -EINVAL;
 
                if (adev->mman.aper_base_kaddr &&
                    mem->placement & TTM_PL_FLAG_CONTIGUOUS)
index 65ec82141a8e012e8ba42b0bb627f1a4f504c465..32cf6b6f6efd96873c294648714f2c78f6ff9ec3 100644 (file)
@@ -139,6 +139,9 @@ int amdgpu_vram_mgr_reserve_range(struct amdgpu_vram_mgr *mgr,
 int amdgpu_vram_mgr_query_page_status(struct amdgpu_vram_mgr *mgr,
                                      uint64_t start);
 
+bool amdgpu_res_cpu_visible(struct amdgpu_device *adev,
+                           struct ttm_resource *res);
+
 int amdgpu_ttm_init(struct amdgpu_device *adev);
 void amdgpu_ttm_fini(struct amdgpu_device *adev);
 void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev,
index 4299ce386322e7cea27232ae05a1222f62f5a850..94089069c9ada61aa61b7c2b28601b764d47c172 100644 (file)
@@ -1613,6 +1613,37 @@ static void amdgpu_vm_bo_insert_map(struct amdgpu_device *adev,
        trace_amdgpu_vm_bo_map(bo_va, mapping);
 }
 
+/* Validate operation parameters to prevent potential abuse */
+static int amdgpu_vm_verify_parameters(struct amdgpu_device *adev,
+                                         struct amdgpu_bo *bo,
+                                         uint64_t saddr,
+                                         uint64_t offset,
+                                         uint64_t size)
+{
+       uint64_t tmp, lpfn;
+
+       if (saddr & AMDGPU_GPU_PAGE_MASK
+           || offset & AMDGPU_GPU_PAGE_MASK
+           || size & AMDGPU_GPU_PAGE_MASK)
+               return -EINVAL;
+
+       if (check_add_overflow(saddr, size, &tmp)
+           || check_add_overflow(offset, size, &tmp)
+           || size == 0 /* which also leads to end < begin */)
+               return -EINVAL;
+
+       /* make sure object fit at this offset */
+       if (bo && offset + size > amdgpu_bo_size(bo))
+               return -EINVAL;
+
+       /* Ensure last pfn not exceed max_pfn */
+       lpfn = (saddr + size - 1) >> AMDGPU_GPU_PAGE_SHIFT;
+       if (lpfn >= adev->vm_manager.max_pfn)
+               return -EINVAL;
+
+       return 0;
+}
+
 /**
  * amdgpu_vm_bo_map - map bo inside a vm
  *
@@ -1639,21 +1670,14 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
        struct amdgpu_bo *bo = bo_va->base.bo;
        struct amdgpu_vm *vm = bo_va->base.vm;
        uint64_t eaddr;
+       int r;
 
-       /* validate the parameters */
-       if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || size & ~PAGE_MASK)
-               return -EINVAL;
-       if (saddr + size <= saddr || offset + size <= offset)
-               return -EINVAL;
-
-       /* make sure object fit at this offset */
-       eaddr = saddr + size - 1;
-       if ((bo && offset + size > amdgpu_bo_size(bo)) ||
-           (eaddr >= adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT))
-               return -EINVAL;
+       r = amdgpu_vm_verify_parameters(adev, bo, saddr, offset, size);
+       if (r)
+               return r;
 
        saddr /= AMDGPU_GPU_PAGE_SIZE;
-       eaddr /= AMDGPU_GPU_PAGE_SIZE;
+       eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE;
 
        tmp = amdgpu_vm_it_iter_first(&vm->va, saddr, eaddr);
        if (tmp) {
@@ -1706,17 +1730,9 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev,
        uint64_t eaddr;
        int r;
 
-       /* validate the parameters */
-       if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || size & ~PAGE_MASK)
-               return -EINVAL;
-       if (saddr + size <= saddr || offset + size <= offset)
-               return -EINVAL;
-
-       /* make sure object fit at this offset */
-       eaddr = saddr + size - 1;
-       if ((bo && offset + size > amdgpu_bo_size(bo)) ||
-           (eaddr >= adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT))
-               return -EINVAL;
+       r = amdgpu_vm_verify_parameters(adev, bo, saddr, offset, size);
+       if (r)
+               return r;
 
        /* Allocate all the needed memory */
        mapping = kmalloc(sizeof(*mapping), GFP_KERNEL);
@@ -1730,7 +1746,7 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev,
        }
 
        saddr /= AMDGPU_GPU_PAGE_SIZE;
-       eaddr /= AMDGPU_GPU_PAGE_SIZE;
+       eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE;
 
        mapping->start = saddr;
        mapping->last = eaddr;
@@ -1817,10 +1833,14 @@ int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev,
        struct amdgpu_bo_va_mapping *before, *after, *tmp, *next;
        LIST_HEAD(removed);
        uint64_t eaddr;
+       int r;
+
+       r = amdgpu_vm_verify_parameters(adev, NULL, saddr, 0, size);
+       if (r)
+               return r;
 
-       eaddr = saddr + size - 1;
        saddr /= AMDGPU_GPU_PAGE_SIZE;
-       eaddr /= AMDGPU_GPU_PAGE_SIZE;
+       eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE;
 
        /* Allocate all the needed memory */
        before = kzalloc(sizeof(*before), GFP_KERNEL);
index 717a60d7a4ea953b8dfc369b09d855ad74b49659..b79986412cd839bc89741a0b3bc1986daa2b10e4 100644 (file)
@@ -819,9 +819,9 @@ struct kfd_process *kfd_create_process(struct task_struct *thread)
        mutex_lock(&kfd_processes_mutex);
 
        if (kfd_is_locked()) {
-               mutex_unlock(&kfd_processes_mutex);
                pr_debug("KFD is locked! Cannot create process");
-               return ERR_PTR(-EINVAL);
+               process = ERR_PTR(-EINVAL);
+               goto out;
        }
 
        /* A prior open of /dev/kfd could have already created the process. */
index e224a028d68accaf083a76a93eb7f0cdb940aedf..8a0460e86309775e83775093b04527f022e4a91c 100644 (file)
@@ -248,14 +248,12 @@ void dcn32_link_encoder_construct(
        enc10->base.hpd_source = init_data->hpd_source;
        enc10->base.connector = init_data->connector;
 
-       enc10->base.preferred_engine = ENGINE_ID_UNKNOWN;
-
-       enc10->base.features = *enc_features;
        if (enc10->base.connector.id == CONNECTOR_ID_USBC)
                enc10->base.features.flags.bits.DP_IS_USB_C = 1;
 
-       if (enc10->base.connector.id == CONNECTOR_ID_USBC)
-               enc10->base.features.flags.bits.DP_IS_USB_C = 1;
+       enc10->base.preferred_engine = ENGINE_ID_UNKNOWN;
+
+       enc10->base.features = *enc_features;
 
        enc10->base.transmitter = init_data->transmitter;
 
index 81e349d5835bbed499f03ef6eb33e5210c83d64b..da94e5309fbaf0f8e06a4a1aad4ce431a8d9f2cc 100644 (file)
@@ -184,6 +184,8 @@ void dcn35_link_encoder_construct(
        enc10->base.hpd_source = init_data->hpd_source;
        enc10->base.connector = init_data->connector;
 
+       if (enc10->base.connector.id == CONNECTOR_ID_USBC)
+               enc10->base.features.flags.bits.DP_IS_USB_C = 1;
 
        enc10->base.preferred_engine = ENGINE_ID_UNKNOWN;
 
@@ -238,8 +240,6 @@ void dcn35_link_encoder_construct(
        }
 
        enc10->base.features.flags.bits.HDMI_6GB_EN = 1;
-       if (enc10->base.connector.id == CONNECTOR_ID_USBC)
-               enc10->base.features.flags.bits.DP_IS_USB_C = 1;
 
        if (bp_funcs->get_connector_speed_cap_info)
                result = bp_funcs->get_connector_speed_cap_info(enc10->base.ctx->dc_bios,
index 479effcf607e261fac73361958a0a855cf90d315..79cfab53f80e259093b7ae0f04310f6470a3c930 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include "nouveau_drv.h"
+#include "nouveau_bios.h"
 #include "nouveau_reg.h"
 #include "dispnv04/hw.h"
 #include "nouveau_encoder.h"
@@ -1677,7 +1678,7 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf)
         */
        if (nv_match_device(dev, 0x0201, 0x1462, 0x8851)) {
                if (*conn == 0xf2005014 && *conf == 0xffffffff) {
-                       fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 1, 1, 1);
+                       fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 1, 1, DCB_OUTPUT_B);
                        return false;
                }
        }
@@ -1763,26 +1764,26 @@ fabricate_dcb_encoder_table(struct drm_device *dev, struct nvbios *bios)
 #ifdef __powerpc__
        /* Apple iMac G4 NV17 */
        if (of_machine_is_compatible("PowerMac4,5")) {
-               fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 0, all_heads, 1);
-               fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG, 1, all_heads, 2);
+               fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 0, all_heads, DCB_OUTPUT_B);
+               fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG, 1, all_heads, DCB_OUTPUT_C);
                return;
        }
 #endif
 
        /* Make up some sane defaults */
        fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG,
-                            bios->legacy.i2c_indices.crt, 1, 1);
+                            bios->legacy.i2c_indices.crt, 1, DCB_OUTPUT_B);
 
        if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0)
                fabricate_dcb_output(dcb, DCB_OUTPUT_TV,
                                     bios->legacy.i2c_indices.tv,
-                                    all_heads, 0);
+                                    all_heads, DCB_OUTPUT_A);
 
        else if (bios->tmds.output0_script_ptr ||
                 bios->tmds.output1_script_ptr)
                fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS,
                                     bios->legacy.i2c_indices.panel,
-                                    all_heads, 1);
+                                    all_heads, DCB_OUTPUT_B);
 }
 
 static int
index 7de7707ec6a895ee2a914150008425a21041bf9c..a72c45809484ab58023dfa0dc5172f67adcfdc23 100644 (file)
@@ -225,12 +225,18 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector,
        u8 *dpcd = nv_encoder->dp.dpcd;
        int ret = NOUVEAU_DP_NONE, hpd;
 
-       /* If we've already read the DPCD on an eDP device, we don't need to
-        * reread it as it won't change
+       /* eDP ports don't support hotplugging - so there's no point in probing eDP ports unless we
+        * haven't probed them once before.
         */
-       if (connector->connector_type == DRM_MODE_CONNECTOR_eDP &&
-           dpcd[DP_DPCD_REV] != 0)
-               return NOUVEAU_DP_SST;
+       if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+               if (connector->status == connector_status_connected)
+                       return NOUVEAU_DP_SST;
+               else if (connector->status == connector_status_disconnected)
+                       return NOUVEAU_DP_NONE;
+       }
+
+       // Ensure that the aux bus is enabled for probing
+       drm_dp_dpcd_set_powered(&nv_connector->aux, true);
 
        mutex_lock(&nv_encoder->dp.hpd_irq_lock);
        if (mstm) {
@@ -293,6 +299,13 @@ out:
        if (mstm && !mstm->suspended && ret != NOUVEAU_DP_MST)
                nv50_mstm_remove(mstm);
 
+       /* GSP doesn't like when we try to do aux transactions on a port it considers disconnected,
+        * and since we don't really have a usecase for that anyway - just disable the aux bus here
+        * if we've decided the connector is disconnected
+        */
+       if (ret == NOUVEAU_DP_NONE)
+               drm_dp_dpcd_set_powered(&nv_connector->aux, false);
+
        mutex_unlock(&nv_encoder->dp.hpd_irq_lock);
        return ret;
 }
index a7f3fc342d87e03b031b5008d939c2eb46f49404..dd5b5a17ece0beed225888888d6c01a0afcf67c9 100644 (file)
@@ -222,8 +222,11 @@ nv50_instobj_acquire(struct nvkm_memory *memory)
        void __iomem *map = NULL;
 
        /* Already mapped? */
-       if (refcount_inc_not_zero(&iobj->maps))
+       if (refcount_inc_not_zero(&iobj->maps)) {
+               /* read barrier match the wmb on refcount set */
+               smp_rmb();
                return iobj->map;
+       }
 
        /* Take the lock, and re-check that another thread hasn't
         * already mapped the object in the meantime.
@@ -250,6 +253,8 @@ nv50_instobj_acquire(struct nvkm_memory *memory)
                        iobj->base.memory.ptrs = &nv50_instobj_fast;
                else
                        iobj->base.memory.ptrs = &nv50_instobj_slow;
+               /* barrier to ensure the ptrs are written before refcount is set */
+               smp_wmb();
                refcount_set(&iobj->maps, 1);
        }
 
index cb7406d7446695ebd3566230f3e11fca3b4cc323..c39fe0fc5d69c646915561bc3d4cb5cfc5411ac1 100644 (file)
@@ -614,8 +614,6 @@ static void nt36672e_panel_remove(struct mipi_dsi_device *dsi)
        struct nt36672e_panel *ctx = mipi_dsi_get_drvdata(dsi);
 
        mipi_dsi_detach(ctx->dsi);
-       mipi_dsi_device_unregister(ctx->dsi);
-
        drm_panel_remove(&ctx->panel);
 }
 
index 775144695283f54dcb1c527e58c9604cfd6da207..b15ca56a09a74a06f8bfcd0b4053d554ced9b58d 100644 (file)
@@ -253,8 +253,6 @@ static void visionox_rm69299_remove(struct mipi_dsi_device *dsi)
        struct visionox_rm69299 *ctx = mipi_dsi_get_drvdata(dsi);
 
        mipi_dsi_detach(ctx->dsi);
-       mipi_dsi_device_unregister(ctx->dsi);
-
        drm_panel_remove(&ctx->panel);
 }
 
index 94947229888ba7888aa6992116af8ab985219dbe..b7f22597ee95e798bb104894052997e332c298c6 100644 (file)
@@ -424,7 +424,7 @@ typedef struct _ATOM_PPLIB_SUMO_CLOCK_INFO{
 typedef struct _ATOM_PPLIB_STATE_V2
 {
       //number of valid dpm levels in this state; Driver uses it to calculate the whole 
-      //size of the state: sizeof(ATOM_PPLIB_STATE_V2) + (ucNumDPMLevels - 1) * sizeof(UCHAR)
+      //size of the state: struct_size(ATOM_PPLIB_STATE_V2, clockInfoIndex, ucNumDPMLevels)
       UCHAR ucNumDPMLevels;
       
       //a index to the array of nonClockInfos
@@ -432,14 +432,14 @@ typedef struct _ATOM_PPLIB_STATE_V2
       /**
       * Driver will read the first ucNumDPMLevels in this array
       */
-      UCHAR clockInfoIndex[1];
+      UCHAR clockInfoIndex[] __counted_by(ucNumDPMLevels);
 } ATOM_PPLIB_STATE_V2;
 
 typedef struct _StateArray{
     //how many states we have 
     UCHAR ucNumEntries;
     
-    ATOM_PPLIB_STATE_V2 states[1];
+    ATOM_PPLIB_STATE_V2 states[] __counted_by(ucNumEntries);
 }StateArray;
 
 
@@ -450,7 +450,7 @@ typedef struct _ClockInfoArray{
     //sizeof(ATOM_PPLIB_CLOCK_INFO)
     UCHAR ucEntrySize;
     
-    UCHAR clockInfo[1];
+    UCHAR clockInfo[] __counted_by(ucNumEntries);
 }ClockInfoArray;
 
 typedef struct _NonClockInfoArray{
@@ -460,7 +460,7 @@ typedef struct _NonClockInfoArray{
     //sizeof(ATOM_PPLIB_NONCLOCK_INFO)
     UCHAR ucEntrySize;
     
-    ATOM_PPLIB_NONCLOCK_INFO nonClockInfo[1];
+    ATOM_PPLIB_NONCLOCK_INFO nonClockInfo[] __counted_by(ucNumEntries);
 }NonClockInfoArray;
 
 typedef struct _ATOM_PPLIB_Clock_Voltage_Dependency_Record
index bb1f0a3371ab5de484a81ad040347c9a5a8d4e76..10793a433bf58697fcdfce8e850ebfdd55ec7284 100644 (file)
@@ -923,8 +923,12 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
                max_device = ATOM_MAX_SUPPORTED_DEVICE_INFO;
 
        for (i = 0; i < max_device; i++) {
-               ATOM_CONNECTOR_INFO_I2C ci =
-                   supported_devices->info.asConnInfo[i];
+               ATOM_CONNECTOR_INFO_I2C ci;
+
+               if (frev > 1)
+                       ci = supported_devices->info_2d1.asConnInfo[i];
+               else
+                       ci = supported_devices->info.asConnInfo[i];
 
                bios_connectors[i].valid = false;
 
index 112438d965ffbefd4fa2cce5f246cc03a63759f9..6e1fd6985ffcb730eb7057c4509aec971dfa8266 100644 (file)
@@ -288,17 +288,23 @@ static struct ttm_pool_type *ttm_pool_select_type(struct ttm_pool *pool,
                                                  enum ttm_caching caching,
                                                  unsigned int order)
 {
-       if (pool->use_dma_alloc || pool->nid != NUMA_NO_NODE)
+       if (pool->use_dma_alloc)
                return &pool->caching[caching].orders[order];
 
 #ifdef CONFIG_X86
        switch (caching) {
        case ttm_write_combined:
+               if (pool->nid != NUMA_NO_NODE)
+                       return &pool->caching[caching].orders[order];
+
                if (pool->use_dma32)
                        return &global_dma32_write_combined[order];
 
                return &global_write_combined[order];
        case ttm_uncached:
+               if (pool->nid != NUMA_NO_NODE)
+                       return &pool->caching[caching].orders[order];
+
                if (pool->use_dma32)
                        return &global_dma32_uncached[order];
 
@@ -566,11 +572,17 @@ void ttm_pool_init(struct ttm_pool *pool, struct device *dev,
        pool->use_dma_alloc = use_dma_alloc;
        pool->use_dma32 = use_dma32;
 
-       if (use_dma_alloc || nid != NUMA_NO_NODE) {
-               for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i)
-                       for (j = 0; j < NR_PAGE_ORDERS; ++j)
-                               ttm_pool_type_init(&pool->caching[i].orders[j],
-                                                  pool, i, j);
+       for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i) {
+               for (j = 0; j < NR_PAGE_ORDERS; ++j) {
+                       struct ttm_pool_type *pt;
+
+                       /* Initialize only pool types which are actually used */
+                       pt = ttm_pool_select_type(pool, i, j);
+                       if (pt != &pool->caching[i].orders[j])
+                               continue;
+
+                       ttm_pool_type_init(pt, pool, i, j);
+               }
        }
 }
 EXPORT_SYMBOL(ttm_pool_init);
@@ -599,10 +611,16 @@ void ttm_pool_fini(struct ttm_pool *pool)
 {
        unsigned int i, j;
 
-       if (pool->use_dma_alloc || pool->nid != NUMA_NO_NODE) {
-               for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i)
-                       for (j = 0; j < NR_PAGE_ORDERS; ++j)
-                               ttm_pool_type_fini(&pool->caching[i].orders[j]);
+       for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i) {
+               for (j = 0; j < NR_PAGE_ORDERS; ++j) {
+                       struct ttm_pool_type *pt;
+
+                       pt = ttm_pool_select_type(pool, i, j);
+                       if (pt != &pool->caching[i].orders[j])
+                               continue;
+
+                       ttm_pool_type_fini(pt);
+               }
        }
 
        /* We removed the pool types from the LRU, but we need to also make sure
index 2e04f6cb661e4f42eeaaef3c5d7fcdaee501d457..ce6b2fb341d1f8a85bab6f0ed19fd3ccde39757b 100644 (file)
@@ -105,7 +105,6 @@ v3d_irq(int irq, void *arg)
                struct v3d_file_priv *file = v3d->bin_job->base.file->driver_priv;
                u64 runtime = local_clock() - file->start_ns[V3D_BIN];
 
-               file->enabled_ns[V3D_BIN] += local_clock() - file->start_ns[V3D_BIN];
                file->jobs_sent[V3D_BIN]++;
                v3d->queue[V3D_BIN].jobs_sent++;
 
@@ -126,7 +125,6 @@ v3d_irq(int irq, void *arg)
                struct v3d_file_priv *file = v3d->render_job->base.file->driver_priv;
                u64 runtime = local_clock() - file->start_ns[V3D_RENDER];
 
-               file->enabled_ns[V3D_RENDER] += local_clock() - file->start_ns[V3D_RENDER];
                file->jobs_sent[V3D_RENDER]++;
                v3d->queue[V3D_RENDER].jobs_sent++;
 
@@ -147,7 +145,6 @@ v3d_irq(int irq, void *arg)
                struct v3d_file_priv *file = v3d->csd_job->base.file->driver_priv;
                u64 runtime = local_clock() - file->start_ns[V3D_CSD];
 
-               file->enabled_ns[V3D_CSD] += local_clock() - file->start_ns[V3D_CSD];
                file->jobs_sent[V3D_CSD]++;
                v3d->queue[V3D_CSD].jobs_sent++;
 
@@ -195,7 +192,6 @@ v3d_hub_irq(int irq, void *arg)
                struct v3d_file_priv *file = v3d->tfu_job->base.file->driver_priv;
                u64 runtime = local_clock() - file->start_ns[V3D_TFU];
 
-               file->enabled_ns[V3D_TFU] += local_clock() - file->start_ns[V3D_TFU];
                file->jobs_sent[V3D_TFU]++;
                v3d->queue[V3D_TFU].jobs_sent++;
 
index c52c7bf1485b1fa95b1e9ca3f1e05135167a8c5c..717d624e9a052298d5d5070551e909cc65ee0cc5 100644 (file)
@@ -456,8 +456,10 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
                .no_wait_gpu = false
        };
        u32 j, initial_line = dst_offset / dst_stride;
-       struct vmw_bo_blit_line_data d;
+       struct vmw_bo_blit_line_data d = {0};
        int ret = 0;
+       struct page **dst_pages = NULL;
+       struct page **src_pages = NULL;
 
        /* Buffer objects need to be either pinned or reserved: */
        if (!(dst->pin_count))
@@ -477,12 +479,35 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
                        return ret;
        }
 
+       if (!src->ttm->pages && src->ttm->sg) {
+               src_pages = kvmalloc_array(src->ttm->num_pages,
+                                          sizeof(struct page *), GFP_KERNEL);
+               if (!src_pages)
+                       return -ENOMEM;
+               ret = drm_prime_sg_to_page_array(src->ttm->sg, src_pages,
+                                                src->ttm->num_pages);
+               if (ret)
+                       goto out;
+       }
+       if (!dst->ttm->pages && dst->ttm->sg) {
+               dst_pages = kvmalloc_array(dst->ttm->num_pages,
+                                          sizeof(struct page *), GFP_KERNEL);
+               if (!dst_pages) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+               ret = drm_prime_sg_to_page_array(dst->ttm->sg, dst_pages,
+                                                dst->ttm->num_pages);
+               if (ret)
+                       goto out;
+       }
+
        d.mapped_dst = 0;
        d.mapped_src = 0;
        d.dst_addr = NULL;
        d.src_addr = NULL;
-       d.dst_pages = dst->ttm->pages;
-       d.src_pages = src->ttm->pages;
+       d.dst_pages = dst->ttm->pages ? dst->ttm->pages : dst_pages;
+       d.src_pages = src->ttm->pages ? src->ttm->pages : src_pages;
        d.dst_num_pages = PFN_UP(dst->resource->size);
        d.src_num_pages = PFN_UP(src->resource->size);
        d.dst_prot = ttm_io_prot(dst, dst->resource, PAGE_KERNEL);
@@ -504,6 +529,10 @@ out:
                kunmap_atomic(d.src_addr);
        if (d.dst_addr)
                kunmap_atomic(d.dst_addr);
+       if (src_pages)
+               kvfree(src_pages);
+       if (dst_pages)
+               kvfree(dst_pages);
 
        return ret;
 }
index bfd41ce3c8f4fca1f5a659e4513e08f72ea95966..e5eb21a471a6010aa956c811522956f27b99a096 100644 (file)
@@ -377,7 +377,8 @@ static int vmw_bo_init(struct vmw_private *dev_priv,
 {
        struct ttm_operation_ctx ctx = {
                .interruptible = params->bo_type != ttm_bo_type_kernel,
-               .no_wait_gpu = false
+               .no_wait_gpu = false,
+               .resv = params->resv,
        };
        struct ttm_device *bdev = &dev_priv->bdev;
        struct drm_device *vdev = &dev_priv->drm;
@@ -394,8 +395,8 @@ static int vmw_bo_init(struct vmw_private *dev_priv,
 
        vmw_bo_placement_set(vmw_bo, params->domain, params->busy_domain);
        ret = ttm_bo_init_reserved(bdev, &vmw_bo->tbo, params->bo_type,
-                                  &vmw_bo->placement, 0, &ctx, NULL,
-                                  NULL, destroy);
+                                  &vmw_bo->placement, 0, &ctx,
+                                  params->sg, params->resv, destroy);
        if (unlikely(ret))
                return ret;
 
index 0d496dc9c6af7a352c0432f50f4dd9be37448b5e..f349642e6190d6933031d08ccd7f353231f0f1da 100644 (file)
@@ -55,6 +55,8 @@ struct vmw_bo_params {
        enum ttm_bo_type bo_type;
        size_t size;
        bool pin;
+       struct dma_resv *resv;
+       struct sg_table *sg;
 };
 
 /**
index 0a304706e01322a6372727a27eb3fd0330471b31..58fb40c93100a84ec8b1dd769f35ab31c00bd0dc 100644 (file)
@@ -1628,6 +1628,7 @@ static const struct drm_driver driver = {
 
        .prime_fd_to_handle = vmw_prime_fd_to_handle,
        .prime_handle_to_fd = vmw_prime_handle_to_fd,
+       .gem_prime_import_sg_table = vmw_prime_import_sg_table,
 
        .fops = &vmwgfx_driver_fops,
        .name = VMWGFX_DRIVER_NAME,
index 12efecc17df664968056906da40cdd46b5665ddf..b019a1a1787af59e3fca37f560db905d7b2b6ab0 100644 (file)
@@ -1130,6 +1130,9 @@ extern int vmw_prime_handle_to_fd(struct drm_device *dev,
                                  struct drm_file *file_priv,
                                  uint32_t handle, uint32_t flags,
                                  int *prime_fd);
+struct drm_gem_object *vmw_prime_import_sg_table(struct drm_device *dev,
+                                                struct dma_buf_attachment *attach,
+                                                struct sg_table *table);
 
 /*
  * MemoryOBject management -  vmwgfx_mob.c
index 12787bb9c111d10db997b9db650c6bb1069c26ef..d6bcaf078b1f40bbf75bdfb63fd1e00b7901e20f 100644 (file)
@@ -149,6 +149,38 @@ out_no_bo:
        return ret;
 }
 
+struct drm_gem_object *vmw_prime_import_sg_table(struct drm_device *dev,
+                                                struct dma_buf_attachment *attach,
+                                                struct sg_table *table)
+{
+       int ret;
+       struct vmw_private *dev_priv = vmw_priv(dev);
+       struct drm_gem_object *gem = NULL;
+       struct vmw_bo *vbo;
+       struct vmw_bo_params params = {
+               .domain = (dev_priv->has_mob) ? VMW_BO_DOMAIN_SYS : VMW_BO_DOMAIN_VRAM,
+               .busy_domain = VMW_BO_DOMAIN_SYS,
+               .bo_type = ttm_bo_type_sg,
+               .size = attach->dmabuf->size,
+               .pin = false,
+               .resv = attach->dmabuf->resv,
+               .sg = table,
+
+       };
+
+       dma_resv_lock(params.resv, NULL);
+
+       ret = vmw_bo_create(dev_priv, &params, &vbo);
+       if (ret != 0)
+               goto out_no_bo;
+
+       vbo->tbo.base.funcs = &vmw_gem_object_funcs;
+
+       gem = &vbo->tbo.base;
+out_no_bo:
+       dma_resv_unlock(params.resv);
+       return gem;
+}
 
 int vmw_gem_object_create_ioctl(struct drm_device *dev, void *data,
                                struct drm_file *filp)
index cd4925346ed45a1c10ae4e9d9b13c0066c71f168..84ae4e10a2ebec20c52a7eb42ea5455a0d22dfa5 100644 (file)
@@ -933,6 +933,7 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane,
 int vmw_du_crtc_atomic_check(struct drm_crtc *crtc,
                             struct drm_atomic_state *state)
 {
+       struct vmw_private *vmw = vmw_priv(crtc->dev);
        struct drm_crtc_state *new_state = drm_atomic_get_new_crtc_state(state,
                                                                         crtc);
        struct vmw_display_unit *du = vmw_crtc_to_du(new_state->crtc);
@@ -940,9 +941,13 @@ int vmw_du_crtc_atomic_check(struct drm_crtc *crtc,
        bool has_primary = new_state->plane_mask &
                           drm_plane_mask(crtc->primary);
 
-       /* We always want to have an active plane with an active CRTC */
-       if (has_primary != new_state->enable)
-               return -EINVAL;
+       /*
+        * This is fine in general, but broken userspace might expect
+        * some actual rendering so give a clue as why it's blank.
+        */
+       if (new_state->enable && !has_primary)
+               drm_dbg_driver(&vmw->drm,
+                              "CRTC without a primary plane will be blank.\n");
 
 
        if (new_state->connector_mask != connector_mask &&
index a94947b588e85f2c764aab60e11a84e59dd2a2ea..19a843da87b789b62279ecb9dccb8b2ddb19fe2f 100644 (file)
@@ -243,10 +243,10 @@ struct vmw_framebuffer_bo {
 
 
 static const uint32_t __maybe_unused vmw_primary_plane_formats[] = {
-       DRM_FORMAT_XRGB1555,
-       DRM_FORMAT_RGB565,
        DRM_FORMAT_XRGB8888,
        DRM_FORMAT_ARGB8888,
+       DRM_FORMAT_RGB565,
+       DRM_FORMAT_XRGB1555,
 };
 
 static const uint32_t __maybe_unused vmw_cursor_plane_formats[] = {
index 2d72a5ee7c0c710339d5d25c0a9376745a90f7af..c99cad444991579f6e665453b74f56cb35de2e15 100644 (file)
@@ -75,8 +75,12 @@ int vmw_prime_fd_to_handle(struct drm_device *dev,
                           int fd, u32 *handle)
 {
        struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+       int ret = ttm_prime_fd_to_handle(tfile, fd, handle);
 
-       return ttm_prime_fd_to_handle(tfile, fd, handle);
+       if (ret)
+               ret = drm_gem_prime_fd_to_handle(dev, file_priv, fd, handle);
+
+       return ret;
 }
 
 int vmw_prime_handle_to_fd(struct drm_device *dev,
@@ -85,5 +89,12 @@ int vmw_prime_handle_to_fd(struct drm_device *dev,
                           int *prime_fd)
 {
        struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
-       return ttm_prime_handle_to_fd(tfile, handle, flags, prime_fd);
+       int ret;
+
+       if (handle > VMWGFX_NUM_MOB)
+               ret = ttm_prime_handle_to_fd(tfile, handle, flags, prime_fd);
+       else
+               ret = drm_gem_prime_handle_to_fd(dev, file_priv, handle, flags, prime_fd);
+
+       return ret;
 }
index 4d23d0a70bcb7ef4901e9128b84cd7112ae8913a..621d98b376bbbc4b40cef6b9c6759b975610dd56 100644 (file)
@@ -188,13 +188,18 @@ static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt)
        switch (dev_priv->map_mode) {
        case vmw_dma_map_bind:
        case vmw_dma_map_populate:
-               vsgt->sgt = &vmw_tt->sgt;
-               ret = sg_alloc_table_from_pages_segment(
-                       &vmw_tt->sgt, vsgt->pages, vsgt->num_pages, 0,
-                       (unsigned long)vsgt->num_pages << PAGE_SHIFT,
-                       dma_get_max_seg_size(dev_priv->drm.dev), GFP_KERNEL);
-               if (ret)
-                       goto out_sg_alloc_fail;
+               if (vmw_tt->dma_ttm.page_flags  & TTM_TT_FLAG_EXTERNAL) {
+                       vsgt->sgt = vmw_tt->dma_ttm.sg;
+               } else {
+                       vsgt->sgt = &vmw_tt->sgt;
+                       ret = sg_alloc_table_from_pages_segment(&vmw_tt->sgt,
+                               vsgt->pages, vsgt->num_pages, 0,
+                               (unsigned long)vsgt->num_pages << PAGE_SHIFT,
+                               dma_get_max_seg_size(dev_priv->drm.dev),
+                               GFP_KERNEL);
+                       if (ret)
+                               goto out_sg_alloc_fail;
+               }
 
                ret = vmw_ttm_map_for_dma(vmw_tt);
                if (unlikely(ret != 0))
@@ -209,8 +214,9 @@ static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt)
        return 0;
 
 out_map_fail:
-       sg_free_table(vmw_tt->vsgt.sgt);
-       vmw_tt->vsgt.sgt = NULL;
+       drm_warn(&dev_priv->drm, "VSG table map failed!");
+       sg_free_table(vsgt->sgt);
+       vsgt->sgt = NULL;
 out_sg_alloc_fail:
        return ret;
 }
@@ -356,15 +362,17 @@ static void vmw_ttm_destroy(struct ttm_device *bdev, struct ttm_tt *ttm)
 static int vmw_ttm_populate(struct ttm_device *bdev,
                            struct ttm_tt *ttm, struct ttm_operation_ctx *ctx)
 {
-       int ret;
+       bool external = (ttm->page_flags & TTM_TT_FLAG_EXTERNAL) != 0;
 
-       /* TODO: maybe completely drop this ? */
        if (ttm_tt_is_populated(ttm))
                return 0;
 
-       ret = ttm_pool_alloc(&bdev->pool, ttm, ctx);
+       if (external && ttm->sg)
+               return  drm_prime_sg_to_dma_addr_array(ttm->sg,
+                                                      ttm->dma_address,
+                                                      ttm->num_pages);
 
-       return ret;
+       return ttm_pool_alloc(&bdev->pool, ttm, ctx);
 }
 
 static void vmw_ttm_unpopulate(struct ttm_device *bdev,
@@ -372,6 +380,10 @@ static void vmw_ttm_unpopulate(struct ttm_device *bdev,
 {
        struct vmw_ttm_tt *vmw_tt = container_of(ttm, struct vmw_ttm_tt,
                                                 dma_ttm);
+       bool external = (ttm->page_flags & TTM_TT_FLAG_EXTERNAL) != 0;
+
+       if (external)
+               return;
 
        vmw_ttm_unbind(bdev, ttm);
 
@@ -390,6 +402,7 @@ static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo,
 {
        struct vmw_ttm_tt *vmw_be;
        int ret;
+       bool external = bo->type == ttm_bo_type_sg;
 
        vmw_be = kzalloc(sizeof(*vmw_be), GFP_KERNEL);
        if (!vmw_be)
@@ -398,7 +411,10 @@ static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo,
        vmw_be->dev_priv = vmw_priv_from_ttm(bo->bdev);
        vmw_be->mob = NULL;
 
-       if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent)
+       if (external)
+               page_flags |= TTM_TT_FLAG_EXTERNAL | TTM_TT_FLAG_EXTERNAL_MAPPABLE;
+
+       if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent || external)
                ret = ttm_sg_tt_init(&vmw_be->dma_ttm, bo, page_flags,
                                     ttm_cached);
        else
index b21da7b745a5e7cd6b3e34e4fb8d42a45b2b6466..a9c1f9885c6bb4d2727cbce81d5be93cb9458a38 100644 (file)
@@ -31,7 +31,7 @@ int intel_fb_bo_framebuffer_init(struct intel_framebuffer *intel_fb,
 
        ret = ttm_bo_reserve(&bo->ttm, true, false, NULL);
        if (ret)
-               return ret;
+               goto err;
 
        if (!(bo->flags & XE_BO_SCANOUT_BIT)) {
                /*
@@ -42,12 +42,16 @@ int intel_fb_bo_framebuffer_init(struct intel_framebuffer *intel_fb,
                 */
                if (XE_IOCTL_DBG(i915, !list_empty(&bo->ttm.base.gpuva.list))) {
                        ttm_bo_unreserve(&bo->ttm);
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto err;
                }
                bo->flags |= XE_BO_SCANOUT_BIT;
        }
        ttm_bo_unreserve(&bo->ttm);
+       return 0;
 
+err:
+       xe_bo_put(bo);
        return ret;
 }
 
index 62d1ef8867a84351ae7444d63113d8867dfbb0c5..3d4c8f342e215ed39263ba5c4c01079072dfcbbd 100644 (file)
@@ -1577,6 +1577,16 @@ void xe_vm_close_and_put(struct xe_vm *vm)
                xe->usm.num_vm_in_fault_mode--;
        else if (!(vm->flags & XE_VM_FLAG_MIGRATION))
                xe->usm.num_vm_in_non_fault_mode--;
+
+       if (vm->usm.asid) {
+               void *lookup;
+
+               xe_assert(xe, xe->info.has_asid);
+               xe_assert(xe, !(vm->flags & XE_VM_FLAG_MIGRATION));
+
+               lookup = xa_erase(&xe->usm.asid_to_vm, vm->usm.asid);
+               xe_assert(xe, lookup == vm);
+       }
        mutex_unlock(&xe->usm.lock);
 
        for_each_tile(tile, xe, id)
@@ -1592,24 +1602,15 @@ static void vm_destroy_work_func(struct work_struct *w)
        struct xe_device *xe = vm->xe;
        struct xe_tile *tile;
        u8 id;
-       void *lookup;
 
        /* xe_vm_close_and_put was not called? */
        xe_assert(xe, !vm->size);
 
        mutex_destroy(&vm->snap_mutex);
 
-       if (!(vm->flags & XE_VM_FLAG_MIGRATION)) {
+       if (!(vm->flags & XE_VM_FLAG_MIGRATION))
                xe_device_mem_access_put(xe);
 
-               if (xe->info.has_asid && vm->usm.asid) {
-                       mutex_lock(&xe->usm.lock);
-                       lookup = xa_erase(&xe->usm.asid_to_vm, vm->usm.asid);
-                       xe_assert(xe, lookup == vm);
-                       mutex_unlock(&xe->usm.lock);
-               }
-       }
-
        for_each_tile(tile, xe, id)
                XE_WARN_ON(vm->pt_root[id]);
 
index bf0df6ee4f7857b4ac8d9ca1c9789b7ef3e4afa9..07fb8d3c037f004ccd34c5393a95c48bffdd8298 100644 (file)
@@ -1026,23 +1026,26 @@ static void cm_reset_to_idle(struct cm_id_private *cm_id_priv)
        }
 }
 
-static noinline void cm_destroy_id_wait_timeout(struct ib_cm_id *cm_id)
+static noinline void cm_destroy_id_wait_timeout(struct ib_cm_id *cm_id,
+                                               enum ib_cm_state old_state)
 {
        struct cm_id_private *cm_id_priv;
 
        cm_id_priv = container_of(cm_id, struct cm_id_private, id);
-       pr_err("%s: cm_id=%p timed out. state=%d refcnt=%d\n", __func__,
-              cm_id, cm_id->state, refcount_read(&cm_id_priv->refcount));
+       pr_err("%s: cm_id=%p timed out. state %d -> %d, refcnt=%d\n", __func__,
+              cm_id, old_state, cm_id->state, refcount_read(&cm_id_priv->refcount));
 }
 
 static void cm_destroy_id(struct ib_cm_id *cm_id, int err)
 {
        struct cm_id_private *cm_id_priv;
+       enum ib_cm_state old_state;
        struct cm_work *work;
        int ret;
 
        cm_id_priv = container_of(cm_id, struct cm_id_private, id);
        spin_lock_irq(&cm_id_priv->lock);
+       old_state = cm_id->state;
 retest:
        switch (cm_id->state) {
        case IB_CM_LISTEN:
@@ -1151,7 +1154,7 @@ retest:
                                                  msecs_to_jiffies(
                                                  CM_DESTROY_ID_WAIT_TIMEOUT));
                if (!ret) /* timeout happened */
-                       cm_destroy_id_wait_timeout(cm_id);
+                       cm_destroy_id_wait_timeout(cm_id, old_state);
        } while (!ret);
 
        while ((work = cm_dequeue_work(cm_id_priv)) != NULL)
index 0c3c4e64812c58cf8457dbaffeb7a28e31cebad1..3e43687a7f6f7313f4031955b1ad03fbc22b8bf9 100644 (file)
@@ -188,7 +188,8 @@ static int process_pma_cmd(struct mlx5_ib_dev *dev, u32 port_num,
                mdev = dev->mdev;
                mdev_port_num = 1;
        }
-       if (MLX5_CAP_GEN(dev->mdev, num_ports) == 1) {
+       if (MLX5_CAP_GEN(dev->mdev, num_ports) == 1 &&
+           !mlx5_core_mp_enabled(mdev)) {
                /* set local port to one for Function-Per-Port HCA. */
                mdev = dev->mdev;
                mdev_port_num = 1;
index ae466e72fc43b3811908cff9f92f6f94c3fb443e..255677bc12b2ab4006f7dd4b6a9f39ae5336ecb4 100644 (file)
@@ -33,6 +33,8 @@ void rxe_dealloc(struct ib_device *ib_dev)
 
        if (rxe->tfm)
                crypto_free_shash(rxe->tfm);
+
+       mutex_destroy(&rxe->usdev_lock);
 }
 
 /* initialize rxe device parameters */
index 99d4b075df49e446ef04295ab73020ae7b8f74c5..76656fe0470d7dce8aa49b201f59562e189da148 100644 (file)
@@ -37,6 +37,7 @@ config IOMMUFD_TEST
        depends on DEBUG_KERNEL
        depends on FAULT_INJECTION
        depends on RUNTIME_TESTING_MENU
+       select IOMMUFD_DRIVER
        default n
        help
          This is dangerous, do not enable unless running
index c0d0bce0b5942d67a139091f08441983f30dc074..8090390edaf9dbb6832c6e30c25bb0ad1068e6cc 100644 (file)
@@ -1883,14 +1883,16 @@ mt7530_port_vlan_del(struct dsa_switch *ds, int port,
 
 static int mt753x_mirror_port_get(unsigned int id, u32 val)
 {
-       return (id == ID_MT7531) ? MT7531_MIRROR_PORT_GET(val) :
-                                  MIRROR_PORT(val);
+       return (id == ID_MT7531 || id == ID_MT7988) ?
+                      MT7531_MIRROR_PORT_GET(val) :
+                      MIRROR_PORT(val);
 }
 
 static int mt753x_mirror_port_set(unsigned int id, u32 val)
 {
-       return (id == ID_MT7531) ? MT7531_MIRROR_PORT_SET(val) :
-                                  MIRROR_PORT(val);
+       return (id == ID_MT7531 || id == ID_MT7988) ?
+                      MT7531_MIRROR_PORT_SET(val) :
+                      MIRROR_PORT(val);
 }
 
 static int mt753x_port_mirror_add(struct dsa_switch *ds, int port,
@@ -2480,6 +2482,9 @@ mt7530_setup(struct dsa_switch *ds)
                           PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
        }
 
+       /* Allow mirroring frames received on the local port (monitor port). */
+       mt7530_set(priv, MT753X_AGC, LOCAL_EN);
+
        /* Setup VLAN ID 0 for VLAN-unaware bridges */
        ret = mt7530_setup_vlan0(priv);
        if (ret)
@@ -2591,6 +2596,9 @@ mt7531_setup_common(struct dsa_switch *ds)
                           PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
        }
 
+       /* Allow mirroring frames received on the local port (monitor port). */
+       mt7530_set(priv, MT753X_AGC, LOCAL_EN);
+
        /* Flush the FDB table */
        ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL);
        if (ret < 0)
index 585db03c054878f85ba69e6546cfc885491d8f4e..a08053390b285e3f27d0bc08a3acba3effd17007 100644 (file)
@@ -32,6 +32,10 @@ enum mt753x_id {
 #define SYSC_REG_RSTCTRL               0x34
 #define  RESET_MCM                     BIT(2)
 
+/* Register for ARL global control */
+#define MT753X_AGC                     0xc
+#define  LOCAL_EN                      BIT(7)
+
 /* Registers to mac forward control for unknown frames */
 #define MT7530_MFC                     0x10
 #define  BC_FFP(x)                     (((x) & 0xff) << 24)
index b890410a2bc0bacd27eab5acd6f87cd8b0110939..688ccb0615ab9f87e7caf9e6fa522444613b2bf3 100644 (file)
@@ -28,6 +28,8 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers,
         * - ICE_TC_FLWR_FIELD_VLAN_TPID (present if specified)
         * - Tunnel flag (present if tunnel)
         */
+       if (fltr->direction == ICE_ESWITCH_FLTR_EGRESS)
+               lkups_cnt++;
 
        if (flags & ICE_TC_FLWR_FIELD_TENANT_ID)
                lkups_cnt++;
@@ -363,6 +365,11 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags,
        /* Always add direction metadata */
        ice_rule_add_direction_metadata(&list[ICE_TC_METADATA_LKUP_IDX]);
 
+       if (tc_fltr->direction == ICE_ESWITCH_FLTR_EGRESS) {
+               ice_rule_add_src_vsi_metadata(&list[i]);
+               i++;
+       }
+
        rule_info->tun_type = ice_sw_type_from_tunnel(tc_fltr->tunnel_type);
        if (tc_fltr->tunnel_type != TNL_LAST) {
                i = ice_tc_fill_tunnel_outer(flags, tc_fltr, list, i);
@@ -772,7 +779,7 @@ ice_eswitch_add_tc_fltr(struct ice_vsi *vsi, struct ice_tc_flower_fltr *fltr)
        int ret;
        int i;
 
-       if (!flags || (flags & ICE_TC_FLWR_FIELD_ENC_SRC_L4_PORT)) {
+       if (flags & ICE_TC_FLWR_FIELD_ENC_SRC_L4_PORT) {
                NL_SET_ERR_MSG_MOD(fltr->extack, "Unsupported encap field(s)");
                return -EOPNOTSUPP;
        }
@@ -820,6 +827,7 @@ ice_eswitch_add_tc_fltr(struct ice_vsi *vsi, struct ice_tc_flower_fltr *fltr)
 
        /* specify the cookie as filter_rule_id */
        rule_info.fltr_rule_id = fltr->cookie;
+       rule_info.src_vsi = vsi->idx;
 
        ret = ice_add_adv_rule(hw, list, lkups_cnt, &rule_info, &rule_added);
        if (ret == -EEXIST) {
@@ -1481,7 +1489,10 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi,
                  (BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) |
                   BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) |
                   BIT_ULL(FLOW_DISSECTOR_KEY_ENC_KEYID) |
-                  BIT_ULL(FLOW_DISSECTOR_KEY_ENC_PORTS))) {
+                  BIT_ULL(FLOW_DISSECTOR_KEY_ENC_PORTS) |
+                  BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IP) |
+                  BIT_ULL(FLOW_DISSECTOR_KEY_ENC_OPTS) |
+                  BIT_ULL(FLOW_DISSECTOR_KEY_ENC_CONTROL))) {
                NL_SET_ERR_MSG_MOD(fltr->extack, "Tunnel key used, but device isn't a tunnel");
                return -EOPNOTSUPP;
        } else {
index 87bdb93cb066e9afba84e5a93556c1efa0d780d9..f4655a8c0705d70b3a4aff580ccb1e437069ca64 100644 (file)
@@ -689,6 +689,7 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
 
        if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
                struct flow_match_control match;
+               u32 val;
 
                flow_rule_match_control(rule, &match);
                if (match.mask->flags & FLOW_DIS_FIRST_FRAG) {
@@ -697,12 +698,14 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
                }
 
                if (match.mask->flags & FLOW_DIS_IS_FRAGMENT) {
+                       val = match.key->flags & FLOW_DIS_IS_FRAGMENT;
                        if (ntohs(flow_spec->etype) == ETH_P_IP) {
-                               flow_spec->ip_flag = IPV4_FLAG_MORE;
+                               flow_spec->ip_flag = val ? IPV4_FLAG_MORE : 0;
                                flow_mask->ip_flag = IPV4_FLAG_MORE;
                                req->features |= BIT_ULL(NPC_IPFRAG_IPV4);
                        } else if (ntohs(flow_spec->etype) == ETH_P_IPV6) {
-                               flow_spec->next_header = IPPROTO_FRAGMENT;
+                               flow_spec->next_header = val ?
+                                                        IPPROTO_FRAGMENT : 0;
                                flow_mask->next_header = 0xff;
                                req->features |= BIT_ULL(NPC_IPFRAG_IPV6);
                        } else {
index c895e265ae0ebcde930acf3785ba9ab1b63b65e5..61334a71058c7594a61ca768ce041f92ab238d24 100644 (file)
@@ -1074,13 +1074,13 @@ mtk_wed_dma_disable(struct mtk_wed_device *dev)
 static void
 mtk_wed_stop(struct mtk_wed_device *dev)
 {
+       mtk_wed_dma_disable(dev);
        mtk_wed_set_ext_int(dev, false);
 
        wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, 0);
        wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, 0);
        wdma_w32(dev, MTK_WDMA_INT_MASK, 0);
        wdma_w32(dev, MTK_WDMA_INT_GRP2, 0);
-       wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0);
 
        if (!mtk_wed_get_rx_capa(dev))
                return;
@@ -1093,7 +1093,6 @@ static void
 mtk_wed_deinit(struct mtk_wed_device *dev)
 {
        mtk_wed_stop(dev);
-       mtk_wed_dma_disable(dev);
 
        wed_clr(dev, MTK_WED_CTRL,
                MTK_WED_CTRL_WDMA_INT_AGENT_EN |
@@ -2605,9 +2604,6 @@ mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask)
 static void
 mtk_wed_irq_set_mask(struct mtk_wed_device *dev, u32 mask)
 {
-       if (!dev->running)
-               return;
-
        mtk_wed_set_ext_int(dev, !!mask);
        wed_w32(dev, MTK_WED_INT_MASK, mask);
 }
index 0ab9db319530258fab6c7e6ad5648e13550069f8..22918b2ef7f128849be838063819ed12509abb45 100644 (file)
@@ -108,7 +108,10 @@ static int mlx5e_tx_reporter_err_cqe_recover(void *ctx)
        mlx5e_reset_txqsq_cc_pc(sq);
        sq->stats->recover++;
        clear_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state);
+       rtnl_lock();
        mlx5e_activate_txqsq(sq);
+       rtnl_unlock();
+
        if (sq->channel)
                mlx5e_trigger_napi_icosq(sq->channel);
        else
@@ -179,12 +182,16 @@ static int mlx5e_tx_reporter_ptpsq_unhealthy_recover(void *ctx)
        carrier_ok = netif_carrier_ok(netdev);
        netif_carrier_off(netdev);
 
+       rtnl_lock();
        mlx5e_deactivate_priv_channels(priv);
+       rtnl_unlock();
 
        mlx5e_ptp_close(chs->ptp);
        err = mlx5e_ptp_open(priv, &chs->params, chs->c[0]->lag_port, &chs->ptp);
 
+       rtnl_lock();
        mlx5e_activate_priv_channels(priv);
+       rtnl_unlock();
 
        /* return carrier back if needed */
        if (carrier_ok)
index c7f542d0b8f08c635a6fad868a364a8f5f91ba8c..93cf23278d93c2629977f38ee7a39e7cd6c0aaa6 100644 (file)
@@ -46,6 +46,10 @@ struct arfs_table {
        struct hlist_head        rules_hash[ARFS_HASH_SIZE];
 };
 
+enum {
+       MLX5E_ARFS_STATE_ENABLED,
+};
+
 enum arfs_type {
        ARFS_IPV4_TCP,
        ARFS_IPV6_TCP,
@@ -60,6 +64,7 @@ struct mlx5e_arfs_tables {
        spinlock_t                     arfs_lock;
        int                            last_filter_id;
        struct workqueue_struct        *wq;
+       unsigned long                  state;
 };
 
 struct arfs_tuple {
@@ -170,6 +175,8 @@ int mlx5e_arfs_enable(struct mlx5e_flow_steering *fs)
                        return err;
                }
        }
+       set_bit(MLX5E_ARFS_STATE_ENABLED, &arfs->state);
+
        return 0;
 }
 
@@ -455,6 +462,8 @@ static void arfs_del_rules(struct mlx5e_flow_steering *fs)
        int i;
        int j;
 
+       clear_bit(MLX5E_ARFS_STATE_ENABLED, &arfs->state);
+
        spin_lock_bh(&arfs->arfs_lock);
        mlx5e_for_each_arfs_rule(rule, htmp, arfs->arfs_tables, i, j) {
                hlist_del_init(&rule->hlist);
@@ -627,17 +636,8 @@ static void arfs_handle_work(struct work_struct *work)
        struct mlx5_flow_handle *rule;
 
        arfs = mlx5e_fs_get_arfs(priv->fs);
-       mutex_lock(&priv->state_lock);
-       if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
-               spin_lock_bh(&arfs->arfs_lock);
-               hlist_del(&arfs_rule->hlist);
-               spin_unlock_bh(&arfs->arfs_lock);
-
-               mutex_unlock(&priv->state_lock);
-               kfree(arfs_rule);
-               goto out;
-       }
-       mutex_unlock(&priv->state_lock);
+       if (!test_bit(MLX5E_ARFS_STATE_ENABLED, &arfs->state))
+               return;
 
        if (!arfs_rule->rule) {
                rule = arfs_add_rule(priv, arfs_rule);
@@ -753,6 +753,11 @@ int mlx5e_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
                return -EPROTONOSUPPORT;
 
        spin_lock_bh(&arfs->arfs_lock);
+       if (!test_bit(MLX5E_ARFS_STATE_ENABLED, &arfs->state)) {
+               spin_unlock_bh(&arfs->arfs_lock);
+               return -EPERM;
+       }
+
        arfs_rule = arfs_find_rule(arfs_t, &fk);
        if (arfs_rule) {
                if (arfs_rule->rxq == rxq_index || work_busy(&arfs_rule->arfs_work)) {
index 8f101181648c6a294332b6229946b1afae4ee554..67a29826bb5702b8fd5e81e8673da5b6291bf7f3 100644 (file)
@@ -589,12 +589,12 @@ static int mlx5e_get_coalesce(struct net_device *netdev,
 static void
 mlx5e_set_priv_channels_tx_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesce *coal)
 {
-       struct mlx5_core_dev *mdev = priv->mdev;
        int tc;
        int i;
 
        for (i = 0; i < priv->channels.num; ++i) {
                struct mlx5e_channel *c = priv->channels.c[i];
+               struct mlx5_core_dev *mdev = c->mdev;
 
                for (tc = 0; tc < c->num_tc; tc++) {
                        mlx5_core_modify_cq_moderation(mdev,
@@ -608,11 +608,11 @@ mlx5e_set_priv_channels_tx_coalesce(struct mlx5e_priv *priv, struct ethtool_coal
 static void
 mlx5e_set_priv_channels_rx_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesce *coal)
 {
-       struct mlx5_core_dev *mdev = priv->mdev;
        int i;
 
        for (i = 0; i < priv->channels.num; ++i) {
                struct mlx5e_channel *c = priv->channels.c[i];
+               struct mlx5_core_dev *mdev = c->mdev;
 
                mlx5_core_modify_cq_moderation(mdev, &c->rq.cq.mcq,
                                               coal->rx_coalesce_usecs,
index b375ef268671ab01215e370149d1a3b9cb86b756..319930c04093ba2d15d498006ad9b3d060a883b7 100644 (file)
@@ -209,8 +209,8 @@ static int mlx5e_devcom_init_mpv(struct mlx5e_priv *priv, u64 *data)
                                                      *data,
                                                      mlx5e_devcom_event_mpv,
                                                      priv);
-       if (IS_ERR_OR_NULL(priv->devcom))
-               return -EOPNOTSUPP;
+       if (IS_ERR(priv->devcom))
+               return PTR_ERR(priv->devcom);
 
        if (mlx5_core_is_mp_master(priv->mdev)) {
                mlx5_devcom_send_event(priv->devcom, MPV_DEVCOM_MASTER_UP,
index 1f60954c12f7257cacf0c7e46539c949ac6eaf7b..844d3e3a65ddf04c6e326127b1b1c05ed351b3a7 100644 (file)
@@ -3060,7 +3060,7 @@ void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw, u64 key)
                                                     key,
                                                     mlx5_esw_offloads_devcom_event,
                                                     esw);
-       if (IS_ERR_OR_NULL(esw->devcom))
+       if (IS_ERR(esw->devcom))
                return;
 
        mlx5_devcom_send_event(esw->devcom,
index d14459e5c04fc515ad682e11ee322aa3891e382f..69d482f7c5a29916688ac0d79d324df5f2596586 100644 (file)
@@ -703,8 +703,10 @@ int mlx5_deactivate_lag(struct mlx5_lag *ldev)
                return err;
        }
 
-       if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &flags))
+       if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &flags)) {
                mlx5_lag_port_sel_destroy(ldev);
+               ldev->buckets = 1;
+       }
        if (mlx5_lag_has_drop_rule(ldev))
                mlx5_lag_drop_rule_cleanup(ldev);
 
index e7d59cfa8708e1617f78b28974977a9588026d1f..7b0766c89f4cf0aac5560e9eb041e564d6531e65 100644 (file)
@@ -220,7 +220,7 @@ mlx5_devcom_register_component(struct mlx5_devcom_dev *devc,
        struct mlx5_devcom_comp *comp;
 
        if (IS_ERR_OR_NULL(devc))
-               return NULL;
+               return ERR_PTR(-EINVAL);
 
        mutex_lock(&comp_list_lock);
        comp = devcom_component_get(devc, id, key, handler);
index 5b28084e8a03c77936e180a06246f9ef0a8dc4bd..dd5d186dc6148f065b986ee5d2363940314816db 100644 (file)
@@ -213,8 +213,8 @@ static int sd_register(struct mlx5_core_dev *dev)
        sd = mlx5_get_sd(dev);
        devcom = mlx5_devcom_register_component(dev->priv.devc, MLX5_DEVCOM_SD_GROUP,
                                                sd->group_id, NULL, dev);
-       if (!devcom)
-               return -ENOMEM;
+       if (IS_ERR(devcom))
+               return PTR_ERR(devcom);
 
        sd->devcom = devcom;
 
index 59806553889e907f7ff2938af2063b1e3b73ca1e..331ce47f51a17a386213d88db9aa7b3cb15d6b41 100644 (file)
@@ -956,7 +956,7 @@ static void mlx5_register_hca_devcom_comp(struct mlx5_core_dev *dev)
                mlx5_devcom_register_component(dev->priv.devc, MLX5_DEVCOM_HCA_PORTS,
                                               mlx5_query_nic_system_image_guid(dev),
                                               NULL, dev);
-       if (IS_ERR_OR_NULL(dev->priv.hca_devcom_comp))
+       if (IS_ERR(dev->priv.hca_devcom_comp))
                mlx5_core_err(dev, "Failed to register devcom HCA component\n");
 }
 
@@ -1699,12 +1699,15 @@ int mlx5_init_one_light(struct mlx5_core_dev *dev)
        err = mlx5_devlink_params_register(priv_to_devlink(dev));
        if (err) {
                mlx5_core_warn(dev, "mlx5_devlink_param_reg err = %d\n", err);
-               goto query_hca_caps_err;
+               goto params_reg_err;
        }
 
        devl_unlock(devlink);
        return 0;
 
+params_reg_err:
+       devl_unregister(devlink);
+       devl_unlock(devlink);
 query_hca_caps_err:
        devl_unregister(devlink);
        devl_unlock(devlink);
index e3bf8c7e4baa62e336415e495a8a385e1edb0654..7ebe712808275a7a1db290040d86c2cd5983c9d7 100644 (file)
@@ -75,7 +75,6 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia
                goto peer_devlink_set_err;
        }
 
-       devlink_register(devlink);
        return 0;
 
 peer_devlink_set_err:
index 523e0c470894f7fdcf8a995fb821ff146f08fcd9..55f255a3c9db69b92d5743bd42c34cbaba46a0a8 100644 (file)
@@ -36,6 +36,27 @@ struct sparx5_tc_flower_template {
        u16 l3_proto; /* protocol specified in the template */
 };
 
+/* SparX-5 VCAP fragment types:
+ * 0 = no fragment, 1 = initial fragment,
+ * 2 = suspicious fragment, 3 = valid follow-up fragment
+ */
+enum {                   /* key / mask */
+       FRAG_NOT   = 0x03, /* 0 / 3 */
+       FRAG_SOME  = 0x11, /* 1 / 1 */
+       FRAG_FIRST = 0x13, /* 1 / 3 */
+       FRAG_LATER = 0x33, /* 3 / 3 */
+       FRAG_INVAL = 0xff, /* invalid */
+};
+
+/* Flower fragment flag to VCAP fragment type mapping */
+static const u8 sparx5_vcap_frag_map[4][4] = {           /* is_frag */
+       { FRAG_INVAL, FRAG_INVAL, FRAG_INVAL, FRAG_FIRST }, /* 0/0 */
+       { FRAG_NOT,   FRAG_NOT,   FRAG_INVAL, FRAG_INVAL }, /* 0/1 */
+       { FRAG_INVAL, FRAG_INVAL, FRAG_INVAL, FRAG_INVAL }, /* 1/0 */
+       { FRAG_SOME,  FRAG_LATER, FRAG_INVAL, FRAG_FIRST }  /* 1/1 */
+       /* 0/0        0/1         1/0         1/1 <-- first_frag */
+};
+
 static int
 sparx5_tc_flower_es0_tpid(struct vcap_tc_flower_parse_usage *st)
 {
@@ -145,29 +166,27 @@ sparx5_tc_flower_handler_control_usage(struct vcap_tc_flower_parse_usage *st)
        flow_rule_match_control(st->frule, &mt);
 
        if (mt.mask->flags) {
-               if (mt.mask->flags & FLOW_DIS_FIRST_FRAG) {
-                       if (mt.key->flags & FLOW_DIS_FIRST_FRAG) {
-                               value = 1; /* initial fragment */
-                               mask = 0x3;
-                       } else {
-                               if (mt.mask->flags & FLOW_DIS_IS_FRAGMENT) {
-                                       value = 3; /* follow up fragment */
-                                       mask = 0x3;
-                               } else {
-                                       value = 0; /* no fragment */
-                                       mask = 0x3;
-                               }
-                       }
-               } else {
-                       if (mt.mask->flags & FLOW_DIS_IS_FRAGMENT) {
-                               value = 3; /* follow up fragment */
-                               mask = 0x3;
-                       } else {
-                               value = 0; /* no fragment */
-                               mask = 0x3;
-                       }
+               u8 is_frag_key = !!(mt.key->flags & FLOW_DIS_IS_FRAGMENT);
+               u8 is_frag_mask = !!(mt.mask->flags & FLOW_DIS_IS_FRAGMENT);
+               u8 is_frag_idx = (is_frag_key << 1) | is_frag_mask;
+
+               u8 first_frag_key = !!(mt.key->flags & FLOW_DIS_FIRST_FRAG);
+               u8 first_frag_mask = !!(mt.mask->flags & FLOW_DIS_FIRST_FRAG);
+               u8 first_frag_idx = (first_frag_key << 1) | first_frag_mask;
+
+               /* Lookup verdict based on the 2 + 2 input bits */
+               u8 vdt = sparx5_vcap_frag_map[is_frag_idx][first_frag_idx];
+
+               if (vdt == FRAG_INVAL) {
+                       NL_SET_ERR_MSG_MOD(st->fco->common.extack,
+                                          "Match on invalid fragment flag combination");
+                       return -EINVAL;
                }
 
+               /* Extract VCAP fragment key and mask from verdict */
+               value = (vdt >> 4) & 0x3;
+               mask = vdt & 0x3;
+
                err = vcap_rule_add_key_u32(st->vrule,
                                            VCAP_KF_L3_FRAGMENT_TYPE,
                                            value, mask);
index ba01c8cc3c906d5ea9a02029dc76fabc243b277c..fcb756d77681cbaf2a17d3e21ddffa5543bc9a84 100644 (file)
@@ -769,25 +769,28 @@ static bool ravb_rx_gbeth(struct net_device *ndev, int *quota, int q)
        dma_addr_t dma_addr;
        int rx_packets = 0;
        u8  desc_status;
-       u16 pkt_len;
+       u16 desc_len;
        u8  die_dt;
        int entry;
        int limit;
        int i;
 
-       entry = priv->cur_rx[q] % priv->num_rx_ring[q];
        limit = priv->dirty_rx[q] + priv->num_rx_ring[q] - priv->cur_rx[q];
        stats = &priv->stats[q];
 
-       desc = &priv->rx_ring[q].desc[entry];
-       for (i = 0; i < limit && rx_packets < *quota && desc->die_dt != DT_FEMPTY; i++) {
+       for (i = 0; i < limit; i++, priv->cur_rx[q]++) {
+               entry = priv->cur_rx[q] % priv->num_rx_ring[q];
+               desc = &priv->rx_ring[q].desc[entry];
+               if (rx_packets == *quota || desc->die_dt == DT_FEMPTY)
+                       break;
+
                /* Descriptor type must be checked before all other reads */
                dma_rmb();
                desc_status = desc->msc;
-               pkt_len = le16_to_cpu(desc->ds_cc) & RX_DS;
+               desc_len = le16_to_cpu(desc->ds_cc) & RX_DS;
 
                /* We use 0-byte descriptors to mark the DMA mapping errors */
-               if (!pkt_len)
+               if (!desc_len)
                        continue;
 
                if (desc_status & MSC_MC)
@@ -808,25 +811,25 @@ static bool ravb_rx_gbeth(struct net_device *ndev, int *quota, int q)
                        switch (die_dt) {
                        case DT_FSINGLE:
                                skb = ravb_get_skb_gbeth(ndev, entry, desc);
-                               skb_put(skb, pkt_len);
+                               skb_put(skb, desc_len);
                                skb->protocol = eth_type_trans(skb, ndev);
                                if (ndev->features & NETIF_F_RXCSUM)
                                        ravb_rx_csum_gbeth(skb);
                                napi_gro_receive(&priv->napi[q], skb);
                                rx_packets++;
-                               stats->rx_bytes += pkt_len;
+                               stats->rx_bytes += desc_len;
                                break;
                        case DT_FSTART:
                                priv->rx_1st_skb = ravb_get_skb_gbeth(ndev, entry, desc);
-                               skb_put(priv->rx_1st_skb, pkt_len);
+                               skb_put(priv->rx_1st_skb, desc_len);
                                break;
                        case DT_FMID:
                                skb = ravb_get_skb_gbeth(ndev, entry, desc);
                                skb_copy_to_linear_data_offset(priv->rx_1st_skb,
                                                               priv->rx_1st_skb->len,
                                                               skb->data,
-                                                              pkt_len);
-                               skb_put(priv->rx_1st_skb, pkt_len);
+                                                              desc_len);
+                               skb_put(priv->rx_1st_skb, desc_len);
                                dev_kfree_skb(skb);
                                break;
                        case DT_FEND:
@@ -834,23 +837,20 @@ static bool ravb_rx_gbeth(struct net_device *ndev, int *quota, int q)
                                skb_copy_to_linear_data_offset(priv->rx_1st_skb,
                                                               priv->rx_1st_skb->len,
                                                               skb->data,
-                                                              pkt_len);
-                               skb_put(priv->rx_1st_skb, pkt_len);
+                                                              desc_len);
+                               skb_put(priv->rx_1st_skb, desc_len);
                                dev_kfree_skb(skb);
                                priv->rx_1st_skb->protocol =
                                        eth_type_trans(priv->rx_1st_skb, ndev);
                                if (ndev->features & NETIF_F_RXCSUM)
-                                       ravb_rx_csum_gbeth(skb);
+                                       ravb_rx_csum_gbeth(priv->rx_1st_skb);
+                               stats->rx_bytes += priv->rx_1st_skb->len;
                                napi_gro_receive(&priv->napi[q],
                                                 priv->rx_1st_skb);
                                rx_packets++;
-                               stats->rx_bytes += pkt_len;
                                break;
                        }
                }
-
-               entry = (++priv->cur_rx[q]) % priv->num_rx_ring[q];
-               desc = &priv->rx_ring[q].desc[entry];
        }
 
        /* Refill the RX ring buffers. */
@@ -891,30 +891,29 @@ static bool ravb_rx_rcar(struct net_device *ndev, int *quota, int q)
 {
        struct ravb_private *priv = netdev_priv(ndev);
        const struct ravb_hw_info *info = priv->info;
-       int entry = priv->cur_rx[q] % priv->num_rx_ring[q];
-       int boguscnt = (priv->dirty_rx[q] + priv->num_rx_ring[q]) -
-                       priv->cur_rx[q];
        struct net_device_stats *stats = &priv->stats[q];
        struct ravb_ex_rx_desc *desc;
+       unsigned int limit, i;
        struct sk_buff *skb;
        dma_addr_t dma_addr;
        struct timespec64 ts;
+       int rx_packets = 0;
        u8  desc_status;
        u16 pkt_len;
-       int limit;
+       int entry;
+
+       limit = priv->dirty_rx[q] + priv->num_rx_ring[q] - priv->cur_rx[q];
+       for (i = 0; i < limit; i++, priv->cur_rx[q]++) {
+               entry = priv->cur_rx[q] % priv->num_rx_ring[q];
+               desc = &priv->rx_ring[q].ex_desc[entry];
+               if (rx_packets == *quota || desc->die_dt == DT_FEMPTY)
+                       break;
 
-       boguscnt = min(boguscnt, *quota);
-       limit = boguscnt;
-       desc = &priv->rx_ring[q].ex_desc[entry];
-       while (desc->die_dt != DT_FEMPTY) {
                /* Descriptor type must be checked before all other reads */
                dma_rmb();
                desc_status = desc->msc;
                pkt_len = le16_to_cpu(desc->ds_cc) & RX_DS;
 
-               if (--boguscnt < 0)
-                       break;
-
                /* We use 0-byte descriptors to mark the DMA mapping errors */
                if (!pkt_len)
                        continue;
@@ -960,12 +959,9 @@ static bool ravb_rx_rcar(struct net_device *ndev, int *quota, int q)
                        if (ndev->features & NETIF_F_RXCSUM)
                                ravb_rx_csum(skb);
                        napi_gro_receive(&priv->napi[q], skb);
-                       stats->rx_packets++;
+                       rx_packets++;
                        stats->rx_bytes += pkt_len;
                }
-
-               entry = (++priv->cur_rx[q]) % priv->num_rx_ring[q];
-               desc = &priv->rx_ring[q].ex_desc[entry];
        }
 
        /* Refill the RX ring buffers. */
@@ -995,9 +991,9 @@ static bool ravb_rx_rcar(struct net_device *ndev, int *quota, int q)
                desc->die_dt = DT_FEMPTY;
        }
 
-       *quota -= limit - (++boguscnt);
-
-       return boguscnt <= 0;
+       stats->rx_packets += rx_packets;
+       *quota -= rx_packets;
+       return *quota == 0;
 }
 
 /* Packet receive function for Ethernet AVB */
index a6fefe675ef1520566ccdcafaac705f0ee159e42..3b7d4ac1e7be07cb2a0fc796f73b671ed535f01d 100644 (file)
@@ -553,6 +553,7 @@ extern const struct stmmac_hwtimestamp stmmac_ptp;
 extern const struct stmmac_mode_ops dwmac4_ring_mode_ops;
 
 struct mac_link {
+       u32 caps;
        u32 speed_mask;
        u32 speed10;
        u32 speed100;
index b21d99faa2d04c985427af61724dd073e3a2fe79..e1b761dcfa1dd56f2e5218312933eb1ea6bc06b1 100644 (file)
@@ -1096,6 +1096,8 @@ static struct mac_device_info *sun8i_dwmac_setup(void *ppriv)
 
        priv->dev->priv_flags |= IFF_UNICAST_FLT;
 
+       mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+                        MAC_10 | MAC_100 | MAC_1000;
        /* The loopback bit seems to be re-set when link change
         * Simply mask it each time
         * Speed 10/100/1000 are set in BIT(2)/BIT(3)
index 3927609abc44110be97903aee12e25084473b80c..8555299443f4edf2475b95c1785544a1c3b73251 100644 (file)
@@ -539,6 +539,8 @@ int dwmac1000_setup(struct stmmac_priv *priv)
        if (mac->multicast_filter_bins)
                mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
 
+       mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+                        MAC_10 | MAC_100 | MAC_1000;
        mac->link.duplex = GMAC_CONTROL_DM;
        mac->link.speed10 = GMAC_CONTROL_PS;
        mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
index a6e8d7bd95886fc277c7e22c896ddf618e0fca97..7667d103cd0ebd9670a42360a095cfd322c8ebac 100644 (file)
@@ -175,6 +175,8 @@ int dwmac100_setup(struct stmmac_priv *priv)
        dev_info(priv->device, "\tDWMAC100\n");
 
        mac->pcsr = priv->ioaddr;
+       mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+                        MAC_10 | MAC_100;
        mac->link.duplex = MAC_CONTROL_F;
        mac->link.speed10 = 0;
        mac->link.speed100 = 0;
index cef25efbdff99fdc07a313ab678869e83c85f79e..a38226d7cc6a99e45c39f62c81c56d8dc87a921a 100644 (file)
@@ -70,7 +70,10 @@ static void dwmac4_core_init(struct mac_device_info *hw,
 
 static void dwmac4_phylink_get_caps(struct stmmac_priv *priv)
 {
-       priv->phylink_config.mac_capabilities |= MAC_2500FD;
+       if (priv->plat->tx_queues_to_use > 1)
+               priv->hw->link.caps &= ~(MAC_10HD | MAC_100HD | MAC_1000HD);
+       else
+               priv->hw->link.caps |= (MAC_10HD | MAC_100HD | MAC_1000HD);
 }
 
 static void dwmac4_rx_queue_enable(struct mac_device_info *hw,
@@ -1378,6 +1381,8 @@ int dwmac4_setup(struct stmmac_priv *priv)
        if (mac->multicast_filter_bins)
                mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
 
+       mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+                        MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD;
        mac->link.duplex = GMAC_CONFIG_DM;
        mac->link.speed10 = GMAC_CONFIG_PS;
        mac->link.speed100 = GMAC_CONFIG_FES | GMAC_CONFIG_PS;
index e841e312077ef0604c5b17a5473069cc4affadff..f8e7775bb63364c589da99cb4c954a38f4411567 100644 (file)
@@ -47,14 +47,6 @@ static void dwxgmac2_core_init(struct mac_device_info *hw,
        writel(XGMAC_INT_DEFAULT_EN, ioaddr + XGMAC_INT_EN);
 }
 
-static void xgmac_phylink_get_caps(struct stmmac_priv *priv)
-{
-       priv->phylink_config.mac_capabilities |= MAC_2500FD | MAC_5000FD |
-                                                MAC_10000FD | MAC_25000FD |
-                                                MAC_40000FD | MAC_50000FD |
-                                                MAC_100000FD;
-}
-
 static void dwxgmac2_set_mac(void __iomem *ioaddr, bool enable)
 {
        u32 tx = readl(ioaddr + XGMAC_TX_CONFIG);
@@ -1540,7 +1532,6 @@ static void dwxgmac3_fpe_configure(void __iomem *ioaddr, struct stmmac_fpe_cfg *
 
 const struct stmmac_ops dwxgmac210_ops = {
        .core_init = dwxgmac2_core_init,
-       .phylink_get_caps = xgmac_phylink_get_caps,
        .set_mac = dwxgmac2_set_mac,
        .rx_ipc = dwxgmac2_rx_ipc,
        .rx_queue_enable = dwxgmac2_rx_queue_enable,
@@ -1601,7 +1592,6 @@ static void dwxlgmac2_rx_queue_enable(struct mac_device_info *hw, u8 mode,
 
 const struct stmmac_ops dwxlgmac2_ops = {
        .core_init = dwxgmac2_core_init,
-       .phylink_get_caps = xgmac_phylink_get_caps,
        .set_mac = dwxgmac2_set_mac,
        .rx_ipc = dwxgmac2_rx_ipc,
        .rx_queue_enable = dwxlgmac2_rx_queue_enable,
@@ -1661,6 +1651,9 @@ int dwxgmac2_setup(struct stmmac_priv *priv)
        if (mac->multicast_filter_bins)
                mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
 
+       mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+                        MAC_1000FD | MAC_2500FD | MAC_5000FD |
+                        MAC_10000FD;
        mac->link.duplex = 0;
        mac->link.speed10 = XGMAC_CONFIG_SS_10_MII;
        mac->link.speed100 = XGMAC_CONFIG_SS_100_MII;
@@ -1698,6 +1691,11 @@ int dwxlgmac2_setup(struct stmmac_priv *priv)
        if (mac->multicast_filter_bins)
                mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
 
+       mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+                        MAC_1000FD | MAC_2500FD | MAC_5000FD |
+                        MAC_10000FD | MAC_25000FD |
+                        MAC_40000FD | MAC_50000FD |
+                        MAC_100000FD;
        mac->link.duplex = 0;
        mac->link.speed1000 = XLGMAC_CONFIG_SS_1000;
        mac->link.speed2500 = XLGMAC_CONFIG_SS_2500;
index 24cd80490d19cf86c2cd566b81f13b137109d784..7c6fb14b555508e4461980f99843ac461b323239 100644 (file)
@@ -1198,17 +1198,6 @@ static int stmmac_init_phy(struct net_device *dev)
        return ret;
 }
 
-static void stmmac_set_half_duplex(struct stmmac_priv *priv)
-{
-       /* Half-Duplex can only work with single tx queue */
-       if (priv->plat->tx_queues_to_use > 1)
-               priv->phylink_config.mac_capabilities &=
-                       ~(MAC_10HD | MAC_100HD | MAC_1000HD);
-       else
-               priv->phylink_config.mac_capabilities |=
-                       (MAC_10HD | MAC_100HD | MAC_1000HD);
-}
-
 static int stmmac_phy_setup(struct stmmac_priv *priv)
 {
        struct stmmac_mdio_bus_data *mdio_bus_data;
@@ -1236,15 +1225,11 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
                xpcs_get_interfaces(priv->hw->xpcs,
                                    priv->phylink_config.supported_interfaces);
 
-       priv->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
-                                               MAC_10FD | MAC_100FD |
-                                               MAC_1000FD;
-
-       stmmac_set_half_duplex(priv);
-
        /* Get the MAC specific capabilities */
        stmmac_mac_phylink_get_caps(priv);
 
+       priv->phylink_config.mac_capabilities = priv->hw->link.caps;
+
        max_speed = priv->plat->max_speed;
        if (max_speed)
                phylink_limit_mac_speed(&priv->phylink_config, max_speed);
@@ -7342,6 +7327,7 @@ int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
        int ret = 0, i;
+       int max_speed;
 
        if (netif_running(dev))
                stmmac_release(dev);
@@ -7355,7 +7341,14 @@ int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt)
                        priv->rss.table[i] = ethtool_rxfh_indir_default(i,
                                                                        rx_cnt);
 
-       stmmac_set_half_duplex(priv);
+       stmmac_mac_phylink_get_caps(priv);
+
+       priv->phylink_config.mac_capabilities = priv->hw->link.caps;
+
+       max_speed = priv->plat->max_speed;
+       if (max_speed)
+               phylink_limit_mac_speed(&priv->phylink_config, max_speed);
+
        stmmac_napi_add(dev);
 
        if (netif_running(dev))
index 2939a21ca74f3cf0f627981df74a949e9c61011e..1d00e21808c1c36dde2fcd4e6a864ca1ecf72a0b 100644 (file)
@@ -2793,6 +2793,8 @@ static void am65_cpsw_unregister_devlink(struct am65_cpsw_common *common)
 
 static int am65_cpsw_nuss_register_ndevs(struct am65_cpsw_common *common)
 {
+       struct am65_cpsw_rx_chn *rx_chan = &common->rx_chns;
+       struct am65_cpsw_tx_chn *tx_chan = common->tx_chns;
        struct device *dev = common->dev;
        struct am65_cpsw_port *port;
        int ret = 0, i;
@@ -2805,6 +2807,22 @@ static int am65_cpsw_nuss_register_ndevs(struct am65_cpsw_common *common)
        if (ret)
                return ret;
 
+       /* The DMA Channels are not guaranteed to be in a clean state.
+        * Reset and disable them to ensure that they are back to the
+        * clean state and ready to be used.
+        */
+       for (i = 0; i < common->tx_ch_num; i++) {
+               k3_udma_glue_reset_tx_chn(tx_chan[i].tx_chn, &tx_chan[i],
+                                         am65_cpsw_nuss_tx_cleanup);
+               k3_udma_glue_disable_tx_chn(tx_chan[i].tx_chn);
+       }
+
+       for (i = 0; i < AM65_CPSW_MAX_RX_FLOWS; i++)
+               k3_udma_glue_reset_rx_chn(rx_chan->rx_chn, i, rx_chan,
+                                         am65_cpsw_nuss_rx_cleanup, !!i);
+
+       k3_udma_glue_disable_rx_chn(rx_chan->rx_chn);
+
        ret = am65_cpsw_nuss_register_devlink(common);
        if (ret)
                return ret;
index 0b3f21cba552f27221a2c7fbe8147feb34e69724..92da8c03d960c9beca5b425a1e3d366f37fa21fc 100644 (file)
@@ -2125,14 +2125,16 @@ static ssize_t tun_put_user(struct tun_struct *tun,
                                            tun_is_little_endian(tun), true,
                                            vlan_hlen)) {
                        struct skb_shared_info *sinfo = skb_shinfo(skb);
-                       pr_err("unexpected GSO type: "
-                              "0x%x, gso_size %d, hdr_len %d\n",
-                              sinfo->gso_type, tun16_to_cpu(tun, gso.gso_size),
-                              tun16_to_cpu(tun, gso.hdr_len));
-                       print_hex_dump(KERN_ERR, "tun: ",
-                                      DUMP_PREFIX_NONE,
-                                      16, 1, skb->head,
-                                      min((int)tun16_to_cpu(tun, gso.hdr_len), 64), true);
+
+                       if (net_ratelimit()) {
+                               netdev_err(tun->dev, "unexpected GSO type: 0x%x, gso_size %d, hdr_len %d\n",
+                                          sinfo->gso_type, tun16_to_cpu(tun, gso.gso_size),
+                                          tun16_to_cpu(tun, gso.hdr_len));
+                               print_hex_dump(KERN_ERR, "tun: ",
+                                              DUMP_PREFIX_NONE,
+                                              16, 1, skb->head,
+                                              min((int)tun16_to_cpu(tun, gso.hdr_len), 64), true);
+                       }
                        WARN_ON_ONCE(1);
                        return -EINVAL;
                }
index a9c418890a1cacc584c9265f4716fa2e18fe0e4b..752f821a19901f313a1aca51fe332539ce82385b 100644 (file)
@@ -1317,6 +1317,8 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf)
 
        netif_set_tso_max_size(dev->net, 16384);
 
+       ax88179_reset(dev);
+
        return 0;
 }
 
@@ -1695,7 +1697,6 @@ static const struct driver_info ax88179_info = {
        .unbind = ax88179_unbind,
        .status = ax88179_status,
        .link_reset = ax88179_link_reset,
-       .reset = ax88179_reset,
        .stop = ax88179_stop,
        .flags = FLAG_ETHER | FLAG_FRAMING_AX,
        .rx_fixup = ax88179_rx_fixup,
@@ -1708,7 +1709,6 @@ static const struct driver_info ax88178a_info = {
        .unbind = ax88179_unbind,
        .status = ax88179_status,
        .link_reset = ax88179_link_reset,
-       .reset = ax88179_reset,
        .stop = ax88179_stop,
        .flags = FLAG_ETHER | FLAG_FRAMING_AX,
        .rx_fixup = ax88179_rx_fixup,
index e2e181378f4124c64b1d02bbe910f6209b57a356..edc34402e787f9ff84a345ecb892cc7b720ef312 100644 (file)
@@ -1431,6 +1431,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x2692, 0x9025, 4)},    /* Cellient MPL200 (rebranded Qualcomm 05c6:9025) */
        {QMI_QUIRK_SET_DTR(0x1546, 0x1312, 4)}, /* u-blox LARA-R6 01B */
        {QMI_QUIRK_SET_DTR(0x1546, 0x1342, 4)}, /* u-blox LARA-L6 */
+       {QMI_QUIRK_SET_DTR(0x33f8, 0x0104, 4)}, /* Rolling RW101 RMNET */
 
        /* 4. Gobi 1000 devices */
        {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)},    /* Acer Gobi Modem Device */
index b456370166b6bb2158ca0916e0eb9e106f9fd9d7..b4f49720c87f62aa6e8349af12797382f740c2b7 100644 (file)
@@ -208,6 +208,15 @@ static const struct dmi_system_id fwbug_list[] = {
                        DMI_MATCH(DMI_BIOS_VERSION, "03.03"),
                }
        },
+       {
+               .ident = "Framework Laptop 13 (Phoenix)",
+               .driver_data = &quirk_spurious_8042,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Framework"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Laptop 13 (AMD Ryzen 7040Series)"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "03.05"),
+               }
+       },
        {}
 };
 
index 6b26e48ce8ad2a5f4de6e78751ffec8941610336..7d6079b02589cbacbb203bdc42cfac4e42dd601c 100644 (file)
@@ -7,4 +7,4 @@
 obj-$(CONFIG_AMD_PMF) += amd-pmf.o
 amd-pmf-objs := core.o acpi.o sps.o \
                auto-mode.o cnqf.o \
-               tee-if.o spc.o
+               tee-if.o spc.o pmf-quirks.o
index d0cf46e2fc8e8a073149c61c52b27e9cc9051da6..1157ec148880b54ec145a7ed9353a656e36f0b33 100644 (file)
@@ -343,7 +343,10 @@ static int apmf_if_verify_interface(struct amd_pmf_dev *pdev)
        if (err)
                return err;
 
-       pdev->supported_func = output.supported_functions;
+       /* only set if not already set by a quirk */
+       if (!pdev->supported_func)
+               pdev->supported_func = output.supported_functions;
+
        dev_dbg(pdev->dev, "supported functions:0x%x notifications:0x%x version:%u\n",
                output.supported_functions, output.notification_mask, output.version);
 
@@ -437,7 +440,7 @@ int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev)
 
        status = acpi_walk_resources(ahandle, METHOD_NAME__CRS, apmf_walk_resources, pmf_dev);
        if (ACPI_FAILURE(status)) {
-               dev_err(pmf_dev->dev, "acpi_walk_resources failed :%d\n", status);
+               dev_dbg(pmf_dev->dev, "acpi_walk_resources failed :%d\n", status);
                return -EINVAL;
        }
 
index 5d4f80698a8b8824bdb59b4e5632ca5f05982c48..64e6e34a2a9acd954f4ce9a916f77673193aba06 100644 (file)
@@ -445,6 +445,7 @@ static int amd_pmf_probe(struct platform_device *pdev)
        mutex_init(&dev->lock);
        mutex_init(&dev->update_mutex);
 
+       amd_pmf_quirks_init(dev);
        apmf_acpi_init(dev);
        platform_set_drvdata(pdev, dev);
        amd_pmf_dbgfs_register(dev);
diff --git a/drivers/platform/x86/amd/pmf/pmf-quirks.c b/drivers/platform/x86/amd/pmf/pmf-quirks.c
new file mode 100644 (file)
index 0000000..0b2eb0a
--- /dev/null
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * AMD Platform Management Framework Driver Quirks
+ *
+ * Copyright (c) 2024, Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Author: Mario Limonciello <mario.limonciello@amd.com>
+ */
+
+#include <linux/dmi.h>
+
+#include "pmf.h"
+
+struct quirk_entry {
+       u32 supported_func;
+};
+
+static struct quirk_entry quirk_no_sps_bug = {
+       .supported_func = 0x4003,
+};
+
+static const struct dmi_system_id fwbug_list[] = {
+       {
+               .ident = "ROG Zephyrus G14",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "GA403UV"),
+               },
+               .driver_data = &quirk_no_sps_bug,
+       },
+       {}
+};
+
+void amd_pmf_quirks_init(struct amd_pmf_dev *dev)
+{
+       const struct dmi_system_id *dmi_id;
+       struct quirk_entry *quirks;
+
+       dmi_id = dmi_first_match(fwbug_list);
+       if (!dmi_id)
+               return;
+
+       quirks = dmi_id->driver_data;
+       if (quirks->supported_func) {
+               dev->supported_func = quirks->supported_func;
+               pr_info("Using supported funcs quirk to avoid %s platform firmware bug\n",
+                       dmi_id->ident);
+       }
+}
+
index 8c4df5753f40d48fefc05c6373a64d0a00469149..eeedd0c0395a89704ce360a6aff9f827566b17b2 100644 (file)
@@ -720,4 +720,7 @@ int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev);
 void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in);
 void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in);
 
+/* Quirk infrastructure */
+void amd_pmf_quirks_init(struct amd_pmf_dev *dev);
+
 #endif /* PMF_H */
index 08df9494603c5e2acf152aacfe13fce81a18dc2c..30951f7131cd98bfdaffb70b2aa30ee3ceb7dbdd 100644 (file)
@@ -719,6 +719,7 @@ static struct miscdevice isst_if_char_driver = {
 };
 
 static const struct x86_cpu_id hpm_cpu_ids[] = {
+       X86_MATCH_INTEL_FAM6_MODEL(GRANITERAPIDS_D,     NULL),
        X86_MATCH_INTEL_FAM6_MODEL(GRANITERAPIDS_X,     NULL),
        X86_MATCH_INTEL_FAM6_MODEL(ATOM_CRESTMONT_X,    NULL),
        {}
index bd75d61ff8a66196d620b5ca2824d8bb16332237..ef730200a04bd94682c781be092a43f15f88190e 100644 (file)
@@ -29,7 +29,7 @@
 #include "uncore-frequency-common.h"
 
 #define        UNCORE_MAJOR_VERSION            0
-#define        UNCORE_MINOR_VERSION            1
+#define        UNCORE_MINOR_VERSION            2
 #define UNCORE_HEADER_INDEX            0
 #define UNCORE_FABRIC_CLUSTER_OFFSET   8
 
@@ -329,7 +329,7 @@ static int uncore_probe(struct auxiliary_device *auxdev, const struct auxiliary_
                        goto remove_clusters;
                }
 
-               if (TPMI_MINOR_VERSION(pd_info->ufs_header_ver) != UNCORE_MINOR_VERSION)
+               if (TPMI_MINOR_VERSION(pd_info->ufs_header_ver) > UNCORE_MINOR_VERSION)
                        dev_info(&auxdev->dev, "Uncore: Ignore: Unsupported minor version:%lx\n",
                                 TPMI_MINOR_VERSION(pd_info->ufs_header_ver));
 
index 043736972cb9216c59a7cb3bc6682e056cdb2373..c8425493b95d855a7562406501b7c803ef481b22 100644 (file)
@@ -172,7 +172,6 @@ struct pwm_chip *dwc_pwm_alloc(struct device *dev)
        dwc->clk_ns = 10;
        chip->ops = &dwc_pwm_ops;
 
-       dev_set_drvdata(dev, chip);
        return chip;
 }
 EXPORT_SYMBOL_GPL(dwc_pwm_alloc);
index 676eaf8d7a53f76672527c1871a306cbcdb9b7ba..fb3eadf6fbc464773b17c30235c51f5a4ff6917f 100644 (file)
@@ -31,26 +31,34 @@ static const struct dwc_pwm_info ehl_pwm_info = {
        .size = 0x1000,
 };
 
-static int dwc_pwm_init_one(struct device *dev, void __iomem *base, unsigned int offset)
+static int dwc_pwm_init_one(struct device *dev, struct dwc_pwm_drvdata *ddata, unsigned int idx)
 {
        struct pwm_chip *chip;
        struct dwc_pwm *dwc;
+       int ret;
 
        chip = dwc_pwm_alloc(dev);
        if (IS_ERR(chip))
                return PTR_ERR(chip);
 
        dwc = to_dwc_pwm(chip);
-       dwc->base = base + offset;
+       dwc->base = ddata->io_base + (ddata->info->size * idx);
 
-       return devm_pwmchip_add(dev, chip);
+       ret = devm_pwmchip_add(dev, chip);
+       if (ret)
+               return ret;
+
+       ddata->chips[idx] = chip;
+       return 0;
 }
 
 static int dwc_pwm_probe(struct pci_dev *pci, const struct pci_device_id *id)
 {
        const struct dwc_pwm_info *info;
        struct device *dev = &pci->dev;
-       int i, ret;
+       struct dwc_pwm_drvdata *ddata;
+       unsigned int idx;
+       int ret;
 
        ret = pcim_enable_device(pci);
        if (ret)
@@ -63,17 +71,25 @@ static int dwc_pwm_probe(struct pci_dev *pci, const struct pci_device_id *id)
                return dev_err_probe(dev, ret, "Failed to iomap PCI BAR\n");
 
        info = (const struct dwc_pwm_info *)id->driver_data;
-
-       for (i = 0; i < info->nr; i++) {
-               /*
-                * No need to check for pcim_iomap_table() failure,
-                * pcim_iomap_regions() already does it for us.
-                */
-               ret = dwc_pwm_init_one(dev, pcim_iomap_table(pci)[0], i * info->size);
+       ddata = devm_kzalloc(dev, struct_size(ddata, chips, info->nr), GFP_KERNEL);
+       if (!ddata)
+               return -ENOMEM;
+
+       /*
+        * No need to check for pcim_iomap_table() failure,
+        * pcim_iomap_regions() already does it for us.
+        */
+       ddata->io_base = pcim_iomap_table(pci)[0];
+       ddata->info = info;
+
+       for (idx = 0; idx < ddata->info->nr; idx++) {
+               ret = dwc_pwm_init_one(dev, ddata, idx);
                if (ret)
                        return ret;
        }
 
+       dev_set_drvdata(dev, ddata);
+
        pm_runtime_put(dev);
        pm_runtime_allow(dev);
 
@@ -88,19 +104,24 @@ static void dwc_pwm_remove(struct pci_dev *pci)
 
 static int dwc_pwm_suspend(struct device *dev)
 {
-       struct pwm_chip *chip = dev_get_drvdata(dev);
-       struct dwc_pwm *dwc = to_dwc_pwm(chip);
-       int i;
-
-       for (i = 0; i < DWC_TIMERS_TOTAL; i++) {
-               if (chip->pwms[i].state.enabled) {
-                       dev_err(dev, "PWM %u in use by consumer (%s)\n",
-                               i, chip->pwms[i].label);
-                       return -EBUSY;
+       struct dwc_pwm_drvdata *ddata = dev_get_drvdata(dev);
+       unsigned int idx;
+
+       for (idx = 0; idx < ddata->info->nr; idx++) {
+               struct pwm_chip *chip = ddata->chips[idx];
+               struct dwc_pwm *dwc = to_dwc_pwm(chip);
+               unsigned int i;
+
+               for (i = 0; i < DWC_TIMERS_TOTAL; i++) {
+                       if (chip->pwms[i].state.enabled) {
+                               dev_err(dev, "PWM %u in use by consumer (%s)\n",
+                                       i, chip->pwms[i].label);
+                               return -EBUSY;
+                       }
+                       dwc->ctx[i].cnt = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT(i));
+                       dwc->ctx[i].cnt2 = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT2(i));
+                       dwc->ctx[i].ctrl = dwc_pwm_readl(dwc, DWC_TIM_CTRL(i));
                }
-               dwc->ctx[i].cnt = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT(i));
-               dwc->ctx[i].cnt2 = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT2(i));
-               dwc->ctx[i].ctrl = dwc_pwm_readl(dwc, DWC_TIM_CTRL(i));
        }
 
        return 0;
@@ -108,14 +129,19 @@ static int dwc_pwm_suspend(struct device *dev)
 
 static int dwc_pwm_resume(struct device *dev)
 {
-       struct pwm_chip *chip = dev_get_drvdata(dev);
-       struct dwc_pwm *dwc = to_dwc_pwm(chip);
-       int i;
-
-       for (i = 0; i < DWC_TIMERS_TOTAL; i++) {
-               dwc_pwm_writel(dwc, dwc->ctx[i].cnt, DWC_TIM_LD_CNT(i));
-               dwc_pwm_writel(dwc, dwc->ctx[i].cnt2, DWC_TIM_LD_CNT2(i));
-               dwc_pwm_writel(dwc, dwc->ctx[i].ctrl, DWC_TIM_CTRL(i));
+       struct dwc_pwm_drvdata *ddata = dev_get_drvdata(dev);
+       unsigned int idx;
+
+       for (idx = 0; idx < ddata->info->nr; idx++) {
+               struct pwm_chip *chip = ddata->chips[idx];
+               struct dwc_pwm *dwc = to_dwc_pwm(chip);
+               unsigned int i;
+
+               for (i = 0; i < DWC_TIMERS_TOTAL; i++) {
+                       dwc_pwm_writel(dwc, dwc->ctx[i].cnt, DWC_TIM_LD_CNT(i));
+                       dwc_pwm_writel(dwc, dwc->ctx[i].cnt2, DWC_TIM_LD_CNT2(i));
+                       dwc_pwm_writel(dwc, dwc->ctx[i].ctrl, DWC_TIM_CTRL(i));
+               }
        }
 
        return 0;
index a8b074841ae8054a5a3737127442a1d0e9979e02..c6e2df5a61227131c50fc3c6351326217371c3a3 100644 (file)
@@ -38,6 +38,12 @@ struct dwc_pwm_info {
        unsigned int size;
 };
 
+struct dwc_pwm_drvdata {
+       const struct dwc_pwm_info *info;
+       void __iomem *io_base;
+       struct pwm_chip *chips[];
+};
+
 struct dwc_pwm_ctx {
        u32 cnt;
        u32 cnt2;
index f95d12345d98a6dbfd1efa850829586852d409ab..920f550bc313bf6c036ed11c539d4319852cb2dd 100644 (file)
@@ -363,10 +363,8 @@ int ccw_device_set_online(struct ccw_device *cdev)
 
        spin_lock_irq(cdev->ccwlock);
        ret = ccw_device_online(cdev);
-       spin_unlock_irq(cdev->ccwlock);
-       if (ret == 0)
-               wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
-       else {
+       if (ret) {
+               spin_unlock_irq(cdev->ccwlock);
                CIO_MSG_EVENT(0, "ccw_device_online returned %d, "
                              "device 0.%x.%04x\n",
                              ret, cdev->private->dev_id.ssid,
@@ -375,7 +373,12 @@ int ccw_device_set_online(struct ccw_device *cdev)
                put_device(&cdev->dev);
                return ret;
        }
-       spin_lock_irq(cdev->ccwlock);
+       /* Wait until a final state is reached */
+       while (!dev_fsm_final_state(cdev)) {
+               spin_unlock_irq(cdev->ccwlock);
+               wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
+               spin_lock_irq(cdev->ccwlock);
+       }
        /* Check if online processing was successful */
        if ((cdev->private->state != DEV_STATE_ONLINE) &&
            (cdev->private->state != DEV_STATE_W4SENSE)) {
index 65d8b2cfd6262d53a03bf10295d5d6c59f518c5d..42791fa0b80e26d4246dabc18e82f2130edb9bb9 100644 (file)
@@ -504,6 +504,11 @@ callback:
                ccw_device_done(cdev, DEV_STATE_ONLINE);
                /* Deliver fake irb to device driver, if needed. */
                if (cdev->private->flags.fake_irb) {
+                       CIO_MSG_EVENT(2, "fakeirb: deliver device 0.%x.%04x intparm %lx type=%d\n",
+                                     cdev->private->dev_id.ssid,
+                                     cdev->private->dev_id.devno,
+                                     cdev->private->intparm,
+                                     cdev->private->flags.fake_irb);
                        create_fake_irb(&cdev->private->dma_area->irb,
                                        cdev->private->flags.fake_irb);
                        cdev->private->flags.fake_irb = 0;
index 40c97f8730751f2afa862ace30b16f1ade38ea80..acd6790dba4dd1311d78e05afa0f41ad5b38aa3a 100644 (file)
@@ -208,6 +208,10 @@ int ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa,
                if (!cdev->private->flags.fake_irb) {
                        cdev->private->flags.fake_irb = FAKE_CMD_IRB;
                        cdev->private->intparm = intparm;
+                       CIO_MSG_EVENT(2, "fakeirb: queue device 0.%x.%04x intparm %lx type=%d\n",
+                                     cdev->private->dev_id.ssid,
+                                     cdev->private->dev_id.devno, intparm,
+                                     cdev->private->flags.fake_irb);
                        return 0;
                } else
                        /* There's already a fake I/O around. */
@@ -551,6 +555,10 @@ int ccw_device_tm_start_timeout_key(struct ccw_device *cdev, struct tcw *tcw,
                if (!cdev->private->flags.fake_irb) {
                        cdev->private->flags.fake_irb = FAKE_TM_IRB;
                        cdev->private->intparm = intparm;
+                       CIO_MSG_EVENT(2, "fakeirb: queue device 0.%x.%04x intparm %lx type=%d\n",
+                                     cdev->private->dev_id.ssid,
+                                     cdev->private->dev_id.devno, intparm,
+                                     cdev->private->flags.fake_irb);
                        return 0;
                } else
                        /* There's already a fake I/O around. */
index 3d9f0834c78bf1e6a55c17a21218b29bacbd1dce..a1cb39f4b7a27939dcf8ac247a30ed965957bd5e 100644 (file)
@@ -722,8 +722,8 @@ static void qdio_handle_activate_check(struct qdio_irq *irq_ptr,
        lgr_info_log();
 }
 
-static void qdio_establish_handle_irq(struct qdio_irq *irq_ptr, int cstat,
-                                     int dstat)
+static int qdio_establish_handle_irq(struct qdio_irq *irq_ptr, int cstat,
+                                    int dstat, int dcc)
 {
        DBF_DEV_EVENT(DBF_INFO, irq_ptr, "qest irq");
 
@@ -731,15 +731,18 @@ static void qdio_establish_handle_irq(struct qdio_irq *irq_ptr, int cstat,
                goto error;
        if (dstat & ~(DEV_STAT_DEV_END | DEV_STAT_CHN_END))
                goto error;
+       if (dcc == 1)
+               return -EAGAIN;
        if (!(dstat & DEV_STAT_DEV_END))
                goto error;
        qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ESTABLISHED);
-       return;
+       return 0;
 
 error:
        DBF_ERROR("%4x EQ:error", irq_ptr->schid.sch_no);
        DBF_ERROR("ds: %2x cs:%2x", dstat, cstat);
        qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
+       return -EIO;
 }
 
 /* qdio interrupt handler */
@@ -748,7 +751,7 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
 {
        struct qdio_irq *irq_ptr = cdev->private->qdio_data;
        struct subchannel_id schid;
-       int cstat, dstat;
+       int cstat, dstat, rc, dcc;
 
        if (!intparm || !irq_ptr) {
                ccw_device_get_schid(cdev, &schid);
@@ -768,10 +771,12 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
        qdio_irq_check_sense(irq_ptr, irb);
        cstat = irb->scsw.cmd.cstat;
        dstat = irb->scsw.cmd.dstat;
+       dcc   = scsw_cmd_is_valid_cc(&irb->scsw) ? irb->scsw.cmd.cc : 0;
+       rc    = 0;
 
        switch (irq_ptr->state) {
        case QDIO_IRQ_STATE_INACTIVE:
-               qdio_establish_handle_irq(irq_ptr, cstat, dstat);
+               rc = qdio_establish_handle_irq(irq_ptr, cstat, dstat, dcc);
                break;
        case QDIO_IRQ_STATE_CLEANUP:
                qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE);
@@ -785,12 +790,25 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
                if (cstat || dstat)
                        qdio_handle_activate_check(irq_ptr, intparm, cstat,
                                                   dstat);
+               else if (dcc == 1)
+                       rc = -EAGAIN;
                break;
        case QDIO_IRQ_STATE_STOPPED:
                break;
        default:
                WARN_ON_ONCE(1);
        }
+
+       if (rc == -EAGAIN) {
+               DBF_DEV_EVENT(DBF_INFO, irq_ptr, "qint retry");
+               rc = ccw_device_start(cdev, irq_ptr->ccw, intparm, 0, 0);
+               if (!rc)
+                       return;
+               DBF_ERROR("%4x RETRY ERR", irq_ptr->schid.sch_no);
+               DBF_ERROR("rc:%4x", rc);
+               qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
+       }
+
        wake_up(&cdev->private->wait_q);
 }
 
index 2c8e964425dc38ca80fa5009b17b4e9dc29bbf10..43778b088ffac54c4a8911f3e41e187f0ae3f364 100644 (file)
@@ -292,13 +292,16 @@ out:
 static void ism_free_dmb(struct ism_dev *ism, struct ism_dmb *dmb)
 {
        clear_bit(dmb->sba_idx, ism->sba_bitmap);
-       dma_free_coherent(&ism->pdev->dev, dmb->dmb_len,
-                         dmb->cpu_addr, dmb->dma_addr);
+       dma_unmap_page(&ism->pdev->dev, dmb->dma_addr, dmb->dmb_len,
+                      DMA_FROM_DEVICE);
+       folio_put(virt_to_folio(dmb->cpu_addr));
 }
 
 static int ism_alloc_dmb(struct ism_dev *ism, struct ism_dmb *dmb)
 {
+       struct folio *folio;
        unsigned long bit;
+       int rc;
 
        if (PAGE_ALIGN(dmb->dmb_len) > dma_get_max_seg_size(&ism->pdev->dev))
                return -EINVAL;
@@ -315,14 +318,30 @@ static int ism_alloc_dmb(struct ism_dev *ism, struct ism_dmb *dmb)
            test_and_set_bit(dmb->sba_idx, ism->sba_bitmap))
                return -EINVAL;
 
-       dmb->cpu_addr = dma_alloc_coherent(&ism->pdev->dev, dmb->dmb_len,
-                                          &dmb->dma_addr,
-                                          GFP_KERNEL | __GFP_NOWARN |
-                                          __GFP_NOMEMALLOC | __GFP_NORETRY);
-       if (!dmb->cpu_addr)
-               clear_bit(dmb->sba_idx, ism->sba_bitmap);
+       folio = folio_alloc(GFP_KERNEL | __GFP_NOWARN | __GFP_NOMEMALLOC |
+                           __GFP_NORETRY, get_order(dmb->dmb_len));
 
-       return dmb->cpu_addr ? 0 : -ENOMEM;
+       if (!folio) {
+               rc = -ENOMEM;
+               goto out_bit;
+       }
+
+       dmb->cpu_addr = folio_address(folio);
+       dmb->dma_addr = dma_map_page(&ism->pdev->dev,
+                                    virt_to_page(dmb->cpu_addr), 0,
+                                    dmb->dmb_len, DMA_FROM_DEVICE);
+       if (dma_mapping_error(&ism->pdev->dev, dmb->dma_addr)) {
+               rc = -ENOMEM;
+               goto out_free;
+       }
+
+       return 0;
+
+out_free:
+       kfree(dmb->cpu_addr);
+out_bit:
+       clear_bit(dmb->sba_idx, ism->sba_bitmap);
+       return rc;
 }
 
 int ism_register_dmb(struct ism_dev *ism, struct ism_dmb *dmb,
index 2e28e2360c85740d0b3ebb391785ee111c78d47b..5b3230ef51fe61bce58ba1cc83bff7cb0a6ddbc1 100644 (file)
@@ -635,10 +635,9 @@ static bool scsi_end_request(struct request *req, blk_status_t error,
        if (blk_queue_add_random(q))
                add_disk_randomness(req->q->disk);
 
-       if (!blk_rq_is_passthrough(req)) {
-               WARN_ON_ONCE(!(cmd->flags & SCMD_INITIALIZED));
-               cmd->flags &= ~SCMD_INITIALIZED;
-       }
+       WARN_ON_ONCE(!blk_rq_is_passthrough(req) &&
+                    !(cmd->flags & SCMD_INITIALIZED));
+       cmd->flags = 0;
 
        /*
         * Calling rcu_barrier() is not necessary here because the
index c617e8b9f0ddfe18bcb34155e156af47e4006837..d78d54ae2605e8ab3050dd7a1e68fb13688a78c5 100644 (file)
@@ -616,6 +616,7 @@ void thermal_debug_tz_trip_up(struct thermal_zone_device *tz,
        tze->trip_stats[trip_id].timestamp = now;
        tze->trip_stats[trip_id].max = max(tze->trip_stats[trip_id].max, temperature);
        tze->trip_stats[trip_id].min = min(tze->trip_stats[trip_id].min, temperature);
+       tze->trip_stats[trip_id].count++;
        tze->trip_stats[trip_id].avg = tze->trip_stats[trip_id].avg +
                (temperature - tze->trip_stats[trip_id].avg) /
                tze->trip_stats[trip_id].count;
index 06859e17b67b7777a08d7e5e33b1bfb972cdd6c3..7a00004bfd0361799f1a43be4cb8e9c35e414d9e 100644 (file)
@@ -47,7 +47,7 @@ enum {
        TSTBUS_MAX,
 };
 
-#define QCOM_UFS_MAX_GEAR 4
+#define QCOM_UFS_MAX_GEAR 5
 #define QCOM_UFS_MAX_LANE 2
 
 enum {
@@ -67,26 +67,32 @@ static const struct __ufs_qcom_bw_table {
        [MODE_PWM][UFS_PWM_G2][UFS_LANE_1] = { 1844,            1000 },
        [MODE_PWM][UFS_PWM_G3][UFS_LANE_1] = { 3688,            1000 },
        [MODE_PWM][UFS_PWM_G4][UFS_LANE_1] = { 7376,            1000 },
+       [MODE_PWM][UFS_PWM_G5][UFS_LANE_1] = { 14752,           1000 },
        [MODE_PWM][UFS_PWM_G1][UFS_LANE_2] = { 1844,            1000 },
        [MODE_PWM][UFS_PWM_G2][UFS_LANE_2] = { 3688,            1000 },
        [MODE_PWM][UFS_PWM_G3][UFS_LANE_2] = { 7376,            1000 },
        [MODE_PWM][UFS_PWM_G4][UFS_LANE_2] = { 14752,           1000 },
+       [MODE_PWM][UFS_PWM_G5][UFS_LANE_2] = { 29504,           1000 },
        [MODE_HS_RA][UFS_HS_G1][UFS_LANE_1] = { 127796,         1000 },
        [MODE_HS_RA][UFS_HS_G2][UFS_LANE_1] = { 255591,         1000 },
        [MODE_HS_RA][UFS_HS_G3][UFS_LANE_1] = { 1492582,        102400 },
        [MODE_HS_RA][UFS_HS_G4][UFS_LANE_1] = { 2915200,        204800 },
+       [MODE_HS_RA][UFS_HS_G5][UFS_LANE_1] = { 5836800,        409600 },
        [MODE_HS_RA][UFS_HS_G1][UFS_LANE_2] = { 255591,         1000 },
        [MODE_HS_RA][UFS_HS_G2][UFS_LANE_2] = { 511181,         1000 },
        [MODE_HS_RA][UFS_HS_G3][UFS_LANE_2] = { 1492582,        204800 },
        [MODE_HS_RA][UFS_HS_G4][UFS_LANE_2] = { 2915200,        409600 },
+       [MODE_HS_RA][UFS_HS_G5][UFS_LANE_2] = { 5836800,        819200 },
        [MODE_HS_RB][UFS_HS_G1][UFS_LANE_1] = { 149422,         1000 },
        [MODE_HS_RB][UFS_HS_G2][UFS_LANE_1] = { 298189,         1000 },
        [MODE_HS_RB][UFS_HS_G3][UFS_LANE_1] = { 1492582,        102400 },
        [MODE_HS_RB][UFS_HS_G4][UFS_LANE_1] = { 2915200,        204800 },
+       [MODE_HS_RB][UFS_HS_G5][UFS_LANE_1] = { 5836800,        409600 },
        [MODE_HS_RB][UFS_HS_G1][UFS_LANE_2] = { 298189,         1000 },
        [MODE_HS_RB][UFS_HS_G2][UFS_LANE_2] = { 596378,         1000 },
        [MODE_HS_RB][UFS_HS_G3][UFS_LANE_2] = { 1492582,        204800 },
        [MODE_HS_RB][UFS_HS_G4][UFS_LANE_2] = { 2915200,        409600 },
+       [MODE_HS_RB][UFS_HS_G5][UFS_LANE_2] = { 5836800,        819200 },
        [MODE_MAX][0][0]                    = { 7643136,        307200 },
 };
 
index b67a28da47026d0299b8a1f8c22a40fc36b1c4a2..a1c467a0e9f719665fc02fa559d5c94545e5725f 100644 (file)
@@ -68,7 +68,6 @@ out:
 static void vmgenid_notify(struct acpi_device *device, u32 event)
 {
        struct vmgenid_state *state = acpi_driver_data(device);
-       char *envp[] = { "NEW_VMGENID=1", NULL };
        u8 old_id[VMGENID_SIZE];
 
        memcpy(old_id, state->this_id, sizeof(old_id));
@@ -76,7 +75,6 @@ static void vmgenid_notify(struct acpi_device *device, u32 event)
        if (!memcmp(old_id, state->this_id, sizeof(old_id)))
                return;
        add_vmfork_randomness(state->this_id, sizeof(state->this_id));
-       kobject_uevent_env(&device->dev.kobj, KOBJ_CHANGE, envp);
 }
 
 static const struct acpi_device_id vmgenid_ids[] = {
index 29281b7c388703d6a6b809823198f37a9405241c..0d6138bee2a3d1ab565ab2d210c0a3f3bf97e4e3 100644 (file)
@@ -49,9 +49,6 @@ static inline struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
 static inline void v9fs_fid_add_modes(struct p9_fid *fid, unsigned int s_flags,
        unsigned int s_cache, unsigned int f_flags)
 {
-       if (fid->qid.type != P9_QTFILE)
-               return;
-
        if ((!s_cache) ||
           ((fid->qid.version == 0) && !(s_flags & V9FS_IGNORE_QV)) ||
           (s_flags & V9FS_DIRECT_IO) || (f_flags & O_DIRECT)) {
index abdbbaee51846218d807033a30c98394a0c213b6..348cc90bf9c56b7184dbac73faffe8d5f3d2762e 100644 (file)
@@ -520,6 +520,7 @@ const struct file_operations v9fs_file_operations = {
        .splice_read = v9fs_file_splice_read,
        .splice_write = iter_file_splice_write,
        .fsync = v9fs_file_fsync,
+       .setlease = simple_nosetlease,
 };
 
 const struct file_operations v9fs_file_operations_dotl = {
@@ -534,4 +535,5 @@ const struct file_operations v9fs_file_operations_dotl = {
        .splice_read = v9fs_file_splice_read,
        .splice_write = iter_file_splice_write,
        .fsync = v9fs_file_fsync_dotl,
+       .setlease = simple_nosetlease,
 };
index b01b1bbf24937168f6fdabe920ddbad0bae3e5d9..47bd77199e20c83a3c7554d5dc592697080b7885 100644 (file)
@@ -83,7 +83,7 @@ static int p9mode2perm(struct v9fs_session_info *v9ses,
        int res;
        int mode = stat->mode;
 
-       res = mode & S_IALLUGO;
+       res = mode & 0777; /* S_IRWXUGO */
        if (v9fs_proto_dotu(v9ses)) {
                if ((mode & P9_DMSETUID) == P9_DMSETUID)
                        res |= S_ISUID;
@@ -178,6 +178,9 @@ int v9fs_uflags2omode(int uflags, int extended)
                break;
        }
 
+       if (uflags & O_TRUNC)
+               ret |= P9_OTRUNC;
+
        if (extended) {
                if (uflags & O_EXCL)
                        ret |= P9_OEXCL;
@@ -1061,8 +1064,6 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
        struct v9fs_session_info *v9ses = sb->s_fs_info;
        struct v9fs_inode *v9inode = V9FS_I(inode);
 
-       set_nlink(inode, 1);
-
        inode_set_atime(inode, stat->atime, 0);
        inode_set_mtime(inode, stat->mtime, 0);
        inode_set_ctime(inode, stat->mtime, 0);
index 4236058c7bbd18b726925e808e73bcb6c08edfeb..55e67e36ae682bcf33a66c2f5e7d936e975e8f6f 100644 (file)
@@ -244,6 +244,21 @@ done:
        return res;
 }
 
+static int v9fs_drop_inode(struct inode *inode)
+{
+       struct v9fs_session_info *v9ses;
+
+       v9ses = v9fs_inode2v9ses(inode);
+       if (v9ses->cache & (CACHE_META|CACHE_LOOSE))
+               return generic_drop_inode(inode);
+       /*
+        * in case of non cached mode always drop the
+        * inode because we want the inode attribute
+        * to always match that on the server.
+        */
+       return 1;
+}
+
 static int v9fs_write_inode(struct inode *inode,
                            struct writeback_control *wbc)
 {
@@ -268,6 +283,7 @@ static const struct super_operations v9fs_super_ops = {
        .alloc_inode = v9fs_alloc_inode,
        .free_inode = v9fs_free_inode,
        .statfs = simple_statfs,
+       .drop_inode = v9fs_drop_inode,
        .evict_inode = v9fs_evict_inode,
        .show_options = v9fs_show_options,
        .umount_begin = v9fs_umount_begin,
@@ -278,6 +294,7 @@ static const struct super_operations v9fs_super_ops_dotl = {
        .alloc_inode = v9fs_alloc_inode,
        .free_inode = v9fs_free_inode,
        .statfs = v9fs_statfs,
+       .drop_inode = v9fs_drop_inode,
        .evict_inode = v9fs_evict_inode,
        .show_options = v9fs_show_options,
        .umount_begin = v9fs_umount_begin,
index 114328acde7202ed201fc8e776ed9cd73176d765..fadb1078903d291ce6ce3c7928d79c71c1eb18f8 100644 (file)
@@ -49,13 +49,15 @@ int bch2_backpointer_invalid(struct bch_fs *c, struct bkey_s_c k,
        if (!bch2_dev_exists2(c, bp.k->p.inode))
                return 0;
 
+       struct bch_dev *ca = bch_dev_bkey_exists(c, bp.k->p.inode);
        struct bpos bucket = bp_pos_to_bucket(c, bp.k->p);
        int ret = 0;
 
-       bkey_fsck_err_on(!bpos_eq(bp.k->p, bucket_pos_to_bp(c, bucket, bp.v->bucket_offset)),
+       bkey_fsck_err_on((bp.v->bucket_offset >> MAX_EXTENT_COMPRESS_RATIO_SHIFT) >= ca->mi.bucket_size ||
+                        !bpos_eq(bp.k->p, bucket_pos_to_bp(c, bucket, bp.v->bucket_offset)),
                         c, err,
-                        backpointer_pos_wrong,
-                        "backpointer at wrong pos");
+                        backpointer_bucket_offset_wrong,
+                        "backpointer bucket_offset wrong");
 fsck_err:
        return ret;
 }
index da012ca7daee5501fe04be48bc875c918abbb33a..85949b9fd880ce2fcce508ba4018350a5dfac9ca 100644 (file)
@@ -53,14 +53,11 @@ static inline struct bpos bucket_pos_to_bp(const struct bch_fs *c,
                                           u64 bucket_offset)
 {
        struct bch_dev *ca = bch_dev_bkey_exists(c, bucket.inode);
-       struct bpos ret;
-
-       ret = POS(bucket.inode,
-                 (bucket_to_sector(ca, bucket.offset) <<
-                  MAX_EXTENT_COMPRESS_RATIO_SHIFT) + bucket_offset);
+       struct bpos ret = POS(bucket.inode,
+                             (bucket_to_sector(ca, bucket.offset) <<
+                              MAX_EXTENT_COMPRESS_RATIO_SHIFT) + bucket_offset);
 
        EBUG_ON(!bkey_eq(bucket, bp_pos_to_bucket(c, ret)));
-
        return ret;
 }
 
index a31a5f706929eb2006e4867a38123b9526639cee..91c3c1fef233d118fb083dae3a60a5e779e3cdaf 100644 (file)
@@ -709,6 +709,8 @@ struct btree_trans_buf {
        x(stripe_delete)                                                \
        x(reflink)                                                      \
        x(fallocate)                                                    \
+       x(fsync)                                                        \
+       x(dio_write)                                                    \
        x(discard)                                                      \
        x(discard_fast)                                                 \
        x(invalidate)                                                   \
index 364ae42022af1750f9887d3f16c566a676b30776..085987435a5ea3cfc7354db7ee5392ce62241f05 100644 (file)
@@ -578,7 +578,8 @@ struct bch_member {
        __le64                  nbuckets;       /* device size */
        __le16                  first_bucket;   /* index of first bucket used */
        __le16                  bucket_size;    /* sectors */
-       __le32                  pad;
+       __u8                    btree_bitmap_shift;
+       __u8                    pad[3];
        __le64                  last_mount;     /* time_t */
 
        __le64                  flags;
@@ -587,6 +588,7 @@ struct bch_member {
        __le64                  errors_at_reset[BCH_MEMBER_ERROR_NR];
        __le64                  errors_reset_time;
        __le64                  seq;
+       __le64                  btree_allocated_bitmap;
 };
 
 #define BCH_MEMBER_V1_BYTES    56
@@ -876,7 +878,8 @@ struct bch_sb_field_downgrade {
        x(rebalance_work,               BCH_VERSION(1,  3))             \
        x(member_seq,                   BCH_VERSION(1,  4))             \
        x(subvolume_fs_parent,          BCH_VERSION(1,  5))             \
-       x(btree_subvolume_children,     BCH_VERSION(1,  6))
+       x(btree_subvolume_children,     BCH_VERSION(1,  6))             \
+       x(mi_btree_bitmap,              BCH_VERSION(1,  7))
 
 enum bcachefs_metadata_version {
        bcachefs_metadata_version_min = 9,
@@ -1314,7 +1317,7 @@ static inline __u64 __bset_magic(struct bch_sb *sb)
        x(write_buffer_keys,    11)             \
        x(datetime,             12)
 
-enum {
+enum bch_jset_entry_type {
 #define x(f, nr)       BCH_JSET_ENTRY_##f      = nr,
        BCH_JSET_ENTRY_TYPES()
 #undef x
@@ -1360,7 +1363,7 @@ struct jset_entry_blacklist_v2 {
        x(inodes,               1)              \
        x(key_version,          2)
 
-enum {
+enum bch_fs_usage_type {
 #define x(f, nr)       BCH_FS_USAGE_##f        = nr,
        BCH_FS_USAGE_TYPES()
 #undef x
index cf23ff47bed8be588593a7fb193ee21ca8298c65..3a45d128f608db86d060d43573219d60762e3038 100644 (file)
@@ -314,6 +314,12 @@ static inline unsigned bkeyp_key_u64s(const struct bkey_format *format,
        return bkey_packed(k) ? format->key_u64s : BKEY_U64s;
 }
 
+static inline bool bkeyp_u64s_valid(const struct bkey_format *f,
+                                   const struct bkey_packed *k)
+{
+       return ((unsigned) k->u64s - bkeyp_key_u64s(f, k) <= U8_MAX - BKEY_U64s);
+}
+
 static inline unsigned bkeyp_key_bytes(const struct bkey_format *format,
                                       const struct bkey_packed *k)
 {
index 5e52684764eb14de4d8433abd5954a829648440b..db336a43fc083a79615e81ce9da37ff4877005f9 100644 (file)
@@ -171,11 +171,15 @@ int __bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k,
        if (type >= BKEY_TYPE_NR)
                return 0;
 
-       bkey_fsck_err_on((flags & BKEY_INVALID_COMMIT) &&
+       bkey_fsck_err_on((type == BKEY_TYPE_btree ||
+                         (flags & BKEY_INVALID_COMMIT)) &&
                         !(bch2_key_types_allowed[type] & BIT_ULL(k.k->type)), c, err,
                         bkey_invalid_type_for_btree,
                         "invalid key type for btree %s (%s)",
-                        bch2_btree_node_type_str(type), bch2_bkey_types[k.k->type]);
+                        bch2_btree_node_type_str(type),
+                        k.k->type < KEY_TYPE_MAX
+                        ? bch2_bkey_types[k.k->type]
+                        : "(unknown)");
 
        if (btree_node_type_is_extents(type) && !bkey_whiteout(k.k)) {
                bkey_fsck_err_on(k.k->size == 0, c, err,
index 84474324dba9b508141f0e886bafbd8a95d47537..02c70e813face0ce975f1f700e55a34743d286ea 100644 (file)
@@ -709,9 +709,31 @@ static noinline struct btree *bch2_btree_node_fill(struct btree_trans *trans,
        struct bch_fs *c = trans->c;
        struct btree_cache *bc = &c->btree_cache;
        struct btree *b;
-       u32 seq;
 
-       BUG_ON(level + 1 >= BTREE_MAX_DEPTH);
+       if (unlikely(level >= BTREE_MAX_DEPTH)) {
+               int ret = bch2_fs_topology_error(c, "attempting to get btree node at level %u, >= max depth %u",
+                                                level, BTREE_MAX_DEPTH);
+               return ERR_PTR(ret);
+       }
+
+       if (unlikely(!bkey_is_btree_ptr(&k->k))) {
+               struct printbuf buf = PRINTBUF;
+               bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(k));
+
+               int ret = bch2_fs_topology_error(c, "attempting to get btree node with non-btree key %s", buf.buf);
+               printbuf_exit(&buf);
+               return ERR_PTR(ret);
+       }
+
+       if (unlikely(k->k.u64s > BKEY_BTREE_PTR_U64s_MAX)) {
+               struct printbuf buf = PRINTBUF;
+               bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(k));
+
+               int ret = bch2_fs_topology_error(c, "attempting to get btree node with too big key %s", buf.buf);
+               printbuf_exit(&buf);
+               return ERR_PTR(ret);
+       }
+
        /*
         * Parent node must be locked, else we could read in a btree node that's
         * been freed:
@@ -752,34 +774,26 @@ static noinline struct btree *bch2_btree_node_fill(struct btree_trans *trans,
        }
 
        set_btree_node_read_in_flight(b);
-
        six_unlock_write(&b->c.lock);
-       seq = six_lock_seq(&b->c.lock);
-       six_unlock_intent(&b->c.lock);
 
-       /* Unlock before doing IO: */
-       if (path && sync)
-               bch2_trans_unlock_noassert(trans);
-
-       bch2_btree_node_read(trans, b, sync);
+       if (path) {
+               u32 seq = six_lock_seq(&b->c.lock);
 
-       if (!sync)
-               return NULL;
+               /* Unlock before doing IO: */
+               six_unlock_intent(&b->c.lock);
+               bch2_trans_unlock_noassert(trans);
 
-       if (path) {
-               int ret = bch2_trans_relock(trans) ?:
-                       bch2_btree_path_relock_intent(trans, path);
-               if (ret) {
-                       BUG_ON(!trans->restarted);
-                       return ERR_PTR(ret);
-               }
-       }
+               bch2_btree_node_read(trans, b, sync);
 
-       if (!six_relock_type(&b->c.lock, lock_type, seq)) {
-               BUG_ON(!path);
+               if (!sync)
+                       return NULL;
 
-               trace_and_count(c, trans_restart_relock_after_fill, trans, _THIS_IP_, path);
-               return ERR_PTR(btree_trans_restart(trans, BCH_ERR_transaction_restart_relock_after_fill));
+               if (!six_relock_type(&b->c.lock, lock_type, seq))
+                       b = NULL;
+       } else {
+               bch2_btree_node_read(trans, b, sync);
+               if (lock_type == SIX_LOCK_read)
+                       six_lock_downgrade(&b->c.lock);
        }
 
        return b;
@@ -1112,18 +1126,19 @@ int bch2_btree_node_prefetch(struct btree_trans *trans,
 {
        struct bch_fs *c = trans->c;
        struct btree_cache *bc = &c->btree_cache;
-       struct btree *b;
 
        BUG_ON(path && !btree_node_locked(path, level + 1));
        BUG_ON(level >= BTREE_MAX_DEPTH);
 
-       b = btree_cache_find(bc, k);
+       struct btree *b = btree_cache_find(bc, k);
        if (b)
                return 0;
 
        b = bch2_btree_node_fill(trans, path, k, btree_id,
                                 level, SIX_LOCK_read, false);
-       return PTR_ERR_OR_ZERO(b);
+       if (!IS_ERR_OR_NULL(b))
+               six_unlock_read(&b->c.lock);
+       return bch2_trans_relock(trans) ?: PTR_ERR_OR_ZERO(b);
 }
 
 void bch2_btree_node_evict(struct btree_trans *trans, const struct bkey_i *k)
@@ -1148,6 +1163,8 @@ wait_on_io:
 
        btree_node_lock_nopath_nofail(trans, &b->c, SIX_LOCK_intent);
        btree_node_lock_nopath_nofail(trans, &b->c, SIX_LOCK_write);
+       if (unlikely(b->hash_val != btree_ptr_hash_val(k)))
+               goto out;
 
        if (btree_node_dirty(b)) {
                __bch2_btree_node_write(c, b, BTREE_WRITE_cache_reclaim);
@@ -1162,7 +1179,7 @@ wait_on_io:
        btree_node_data_free(c, b);
        bch2_btree_node_hash_remove(bc, b);
        mutex_unlock(&bc->lock);
-
+out:
        six_unlock_write(&b->c.lock);
        six_unlock_intent(&b->c.lock);
 }
index d2555da55c6da3750af9fab2538e3653118a48d9..ecbd9598f69fd00e86efbe7537a134d6d4c4db06 100644 (file)
@@ -828,6 +828,7 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id,
        struct bch_fs *c = trans->c;
        struct bkey deleted = KEY(0, 0, 0);
        struct bkey_s_c old = (struct bkey_s_c) { &deleted, NULL };
+       struct printbuf buf = PRINTBUF;
        int ret = 0;
 
        deleted.p = k->k->p;
@@ -848,11 +849,23 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id,
        if (ret)
                goto err;
 
+       if (mustfix_fsck_err_on(level && !bch2_dev_btree_bitmap_marked(c, *k),
+                               c, btree_bitmap_not_marked,
+                               "btree ptr not marked in member info btree allocated bitmap\n  %s",
+                               (bch2_bkey_val_to_text(&buf, c, *k),
+                                buf.buf))) {
+               mutex_lock(&c->sb_lock);
+               bch2_dev_btree_bitmap_mark(c, *k);
+               bch2_write_super(c);
+               mutex_unlock(&c->sb_lock);
+       }
+
        ret = commit_do(trans, NULL, NULL, 0,
                        bch2_key_trigger(trans, btree_id, level, old,
                                         unsafe_bkey_s_c_to_s(*k), BTREE_TRIGGER_GC));
 fsck_err:
 err:
+       printbuf_exit(&buf);
        bch_err_fn(c, ret);
        return ret;
 }
index d7de82ac389354f9a0d5eef0a66c8694f1752b94..9678b2375bedde868e7a168435c9a17fc74eb26a 100644 (file)
@@ -831,7 +831,7 @@ static int bset_key_invalid(struct bch_fs *c, struct btree *b,
                (rw == WRITE ? bch2_bkey_val_invalid(c, k, READ, err) : 0);
 }
 
-static bool __bkey_valid(struct bch_fs *c, struct btree *b,
+static bool bkey_packed_valid(struct bch_fs *c, struct btree *b,
                         struct bset *i, struct bkey_packed *k)
 {
        if (bkey_p_next(k) > vstruct_last(i))
@@ -840,7 +840,7 @@ static bool __bkey_valid(struct bch_fs *c, struct btree *b,
        if (k->format > KEY_FORMAT_CURRENT)
                return false;
 
-       if (k->u64s < bkeyp_key_u64s(&b->format, k))
+       if (!bkeyp_u64s_valid(&b->format, k))
                return false;
 
        struct printbuf buf = PRINTBUF;
@@ -884,11 +884,13 @@ static int validate_bset_keys(struct bch_fs *c, struct btree *b,
                                 "invalid bkey format %u", k->format))
                        goto drop_this_key;
 
-               if (btree_err_on(k->u64s < bkeyp_key_u64s(&b->format, k),
+               if (btree_err_on(!bkeyp_u64s_valid(&b->format, k),
                                 -BCH_ERR_btree_node_read_err_fixable,
                                 c, NULL, b, i,
                                 btree_node_bkey_bad_u64s,
-                                "k->u64s too small (%u < %u)", k->u64s, bkeyp_key_u64s(&b->format, k)))
+                                "bad k->u64s %u (min %u max %lu)", k->u64s,
+                                bkeyp_key_u64s(&b->format, k),
+                                U8_MAX - BKEY_U64s + bkeyp_key_u64s(&b->format, k)))
                        goto drop_this_key;
 
                if (!write)
@@ -947,13 +949,12 @@ drop_this_key:
                         * do
                         */
 
-                       if (!__bkey_valid(c, b, i, (void *) ((u64 *) k + next_good_key))) {
+                       if (!bkey_packed_valid(c, b, i, (void *) ((u64 *) k + next_good_key))) {
                                for (next_good_key = 1;
                                     next_good_key < (u64 *) vstruct_last(i) - (u64 *) k;
                                     next_good_key++)
-                                       if (__bkey_valid(c, b, i, (void *) ((u64 *) k + next_good_key)))
+                                       if (bkey_packed_valid(c, b, i, (void *) ((u64 *) k + next_good_key)))
                                                goto got_good_key;
-
                        }
 
                        /*
@@ -1339,7 +1340,9 @@ start:
                               rb->start_time);
        bio_put(&rb->bio);
 
-       if (saw_error && !btree_node_read_error(b)) {
+       if (saw_error &&
+           !btree_node_read_error(b) &&
+           c->curr_recovery_pass != BCH_RECOVERY_PASS_scan_for_btree_nodes) {
                printbuf_reset(&buf);
                bch2_bpos_to_text(&buf, b->key.k.p);
                bch_err_ratelimited(c, "%s: rewriting btree node at btree=%s level=%u %s due to error",
index 1d58d447b386cdf74ecce2609f8aa23851ae4057..1c70836dd7cce4988ef8cf166ee0797fd8f8269e 100644 (file)
@@ -498,8 +498,13 @@ static inline void set_btree_iter_dontneed(struct btree_iter *iter)
 {
        struct btree_trans *trans = iter->trans;
 
-       if (!trans->restarted)
-               btree_iter_path(trans, iter)->preserve = false;
+       if (!iter->path || trans->restarted)
+               return;
+
+       struct btree_path *path = btree_iter_path(trans, iter);
+       path->preserve          = false;
+       if (path->ref == 1)
+               path->should_be_locked  = false;
 }
 
 void *__bch2_trans_kmalloc(struct btree_trans *, size_t);
index 556f76f5c84e1613c332e7443e6bb8b1602dd359..866bd278439f8bb72a0b1e31e672953ff9b3f839 100644 (file)
@@ -133,9 +133,19 @@ static void try_read_btree_node(struct find_btree_nodes *f, struct bch_dev *ca,
        if (le64_to_cpu(bn->magic) != bset_magic(c))
                return;
 
+       if (bch2_csum_type_is_encryption(BSET_CSUM_TYPE(&bn->keys))) {
+               struct nonce nonce = btree_nonce(&bn->keys, 0);
+               unsigned bytes = (void *) &bn->keys - (void *) &bn->flags;
+
+               bch2_encrypt(c, BSET_CSUM_TYPE(&bn->keys), nonce, &bn->flags, bytes);
+       }
+
        if (btree_id_is_alloc(BTREE_NODE_ID(bn)))
                return;
 
+       if (BTREE_NODE_LEVEL(bn) >= BTREE_MAX_DEPTH)
+               return;
+
        rcu_read_lock();
        struct found_btree_node n = {
                .btree_id       = BTREE_NODE_ID(bn),
@@ -195,8 +205,13 @@ static int read_btree_nodes_worker(void *p)
                                last_print = jiffies;
                        }
 
-                       try_read_btree_node(w->f, ca, bio, buf,
-                                           bucket * ca->mi.bucket_size + bucket_offset);
+                       u64 sector = bucket * ca->mi.bucket_size + bucket_offset;
+
+                       if (c->sb.version_upgrade_complete >= bcachefs_metadata_version_mi_btree_bitmap &&
+                           !bch2_dev_btree_bitmap_marked_sectors(ca, sector, btree_sectors(c)))
+                               continue;
+
+                       try_read_btree_node(w->f, ca, bio, buf, sector);
                }
 err:
        bio_put(bio);
index aa9da49707404015a558c9c6e9339b733d0c98c3..bbec91e8e6506fa32611b340dc1a3a4a104aeed6 100644 (file)
@@ -397,12 +397,13 @@ static int btree_key_can_insert_cached(struct btree_trans *trans, unsigned flags
        struct bkey_cached *ck = (void *) path->l[0].b;
        unsigned new_u64s;
        struct bkey_i *new_k;
+       unsigned watermark = flags & BCH_WATERMARK_MASK;
 
        EBUG_ON(path->level);
 
-       if (!test_bit(BKEY_CACHED_DIRTY, &ck->flags) &&
-           bch2_btree_key_cache_must_wait(c) &&
-           !(flags & BCH_TRANS_COMMIT_journal_reclaim))
+       if (watermark < BCH_WATERMARK_reclaim &&
+           !test_bit(BKEY_CACHED_DIRTY, &ck->flags) &&
+           bch2_btree_key_cache_must_wait(c))
                return -BCH_ERR_btree_insert_need_journal_reclaim;
 
        /*
@@ -499,9 +500,8 @@ static int run_one_trans_trigger(struct btree_trans *trans, struct btree_insert_
 }
 
 static int run_btree_triggers(struct btree_trans *trans, enum btree_id btree_id,
-                             struct btree_insert_entry *btree_id_start)
+                             unsigned btree_id_start)
 {
-       struct btree_insert_entry *i;
        bool trans_trigger_run;
        int ret, overwrite;
 
@@ -514,13 +514,13 @@ static int run_btree_triggers(struct btree_trans *trans, enum btree_id btree_id,
                do {
                        trans_trigger_run = false;
 
-                       for (i = btree_id_start;
-                            i < trans->updates + trans->nr_updates && i->btree_id <= btree_id;
+                       for (unsigned i = btree_id_start;
+                            i < trans->nr_updates && trans->updates[i].btree_id <= btree_id;
                             i++) {
-                               if (i->btree_id != btree_id)
+                               if (trans->updates[i].btree_id != btree_id)
                                        continue;
 
-                               ret = run_one_trans_trigger(trans, i, overwrite);
+                               ret = run_one_trans_trigger(trans, trans->updates + i, overwrite);
                                if (ret < 0)
                                        return ret;
                                if (ret)
@@ -534,8 +534,7 @@ static int run_btree_triggers(struct btree_trans *trans, enum btree_id btree_id,
 
 static int bch2_trans_commit_run_triggers(struct btree_trans *trans)
 {
-       struct btree_insert_entry *btree_id_start = trans->updates;
-       unsigned btree_id = 0;
+       unsigned btree_id = 0, btree_id_start = 0;
        int ret = 0;
 
        /*
@@ -549,8 +548,8 @@ static int bch2_trans_commit_run_triggers(struct btree_trans *trans)
                if (btree_id == BTREE_ID_alloc)
                        continue;
 
-               while (btree_id_start < trans->updates + trans->nr_updates &&
-                      btree_id_start->btree_id < btree_id)
+               while (btree_id_start < trans->nr_updates &&
+                      trans->updates[btree_id_start].btree_id < btree_id)
                        btree_id_start++;
 
                ret = run_btree_triggers(trans, btree_id, btree_id_start);
@@ -558,11 +557,13 @@ static int bch2_trans_commit_run_triggers(struct btree_trans *trans)
                        return ret;
        }
 
-       trans_for_each_update(trans, i) {
+       for (unsigned idx = 0; idx < trans->nr_updates; idx++) {
+               struct btree_insert_entry *i = trans->updates + idx;
+
                if (i->btree_id > BTREE_ID_alloc)
                        break;
                if (i->btree_id == BTREE_ID_alloc) {
-                       ret = run_btree_triggers(trans, BTREE_ID_alloc, i);
+                       ret = run_btree_triggers(trans, BTREE_ID_alloc, idx);
                        if (ret)
                                return ret;
                        break;
@@ -826,7 +827,8 @@ static inline int do_bch2_trans_commit(struct btree_trans *trans, unsigned flags
        struct bch_fs *c = trans->c;
        int ret = 0, u64s_delta = 0;
 
-       trans_for_each_update(trans, i) {
+       for (unsigned idx = 0; idx < trans->nr_updates; idx++) {
+               struct btree_insert_entry *i = trans->updates + idx;
                if (i->cached)
                        continue;
 
index c4a5e83a56a436548263445e3b7a329644757cc7..6030c396754f6f494c3c137abd313f6bf80c2ffb 100644 (file)
@@ -21,6 +21,7 @@
 #include "keylist.h"
 #include "recovery_passes.h"
 #include "replicas.h"
+#include "sb-members.h"
 #include "super-io.h"
 #include "trace.h"
 
@@ -605,6 +606,26 @@ static void btree_update_add_key(struct btree_update *as,
        bch2_keylist_push(keys);
 }
 
+static bool btree_update_new_nodes_marked_sb(struct btree_update *as)
+{
+       for_each_keylist_key(&as->new_keys, k)
+               if (!bch2_dev_btree_bitmap_marked(as->c, bkey_i_to_s_c(k)))
+                       return false;
+       return true;
+}
+
+static void btree_update_new_nodes_mark_sb(struct btree_update *as)
+{
+       struct bch_fs *c = as->c;
+
+       mutex_lock(&c->sb_lock);
+       for_each_keylist_key(&as->new_keys, k)
+               bch2_dev_btree_bitmap_mark(c, bkey_i_to_s_c(k));
+
+       bch2_write_super(c);
+       mutex_unlock(&c->sb_lock);
+}
+
 /*
  * The transactional part of an interior btree node update, where we journal the
  * update we did to the interior node and update alloc info:
@@ -662,6 +683,9 @@ static void btree_update_nodes_written(struct btree_update *as)
        if (ret)
                goto err;
 
+       if (!btree_update_new_nodes_marked_sb(as))
+               btree_update_new_nodes_mark_sb(as);
+
        /*
         * Wait for any in flight writes to finish before we free the old nodes
         * on disk:
@@ -1280,23 +1304,29 @@ static void bch2_btree_set_root_inmem(struct bch_fs *c, struct btree *b)
        bch2_recalc_btree_reserve(c);
 }
 
-static void bch2_btree_set_root(struct btree_update *as,
-                               struct btree_trans *trans,
-                               struct btree_path *path,
-                               struct btree *b)
+static int bch2_btree_set_root(struct btree_update *as,
+                              struct btree_trans *trans,
+                              struct btree_path *path,
+                              struct btree *b,
+                              bool nofail)
 {
        struct bch_fs *c = as->c;
-       struct btree *old;
 
        trace_and_count(c, btree_node_set_root, trans, b);
 
-       old = btree_node_root(c, b);
+       struct btree *old = btree_node_root(c, b);
 
        /*
         * Ensure no one is using the old root while we switch to the
         * new root:
         */
-       bch2_btree_node_lock_write_nofail(trans, path, &old->c);
+       if (nofail) {
+               bch2_btree_node_lock_write_nofail(trans, path, &old->c);
+       } else {
+               int ret = bch2_btree_node_lock_write(trans, path, &old->c);
+               if (ret)
+                       return ret;
+       }
 
        bch2_btree_set_root_inmem(c, b);
 
@@ -1310,6 +1340,7 @@ static void bch2_btree_set_root(struct btree_update *as,
         * depend on the new root would have to update the new root.
         */
        bch2_btree_node_unlock_write(trans, path, old);
+       return 0;
 }
 
 /* Interior node updates: */
@@ -1652,15 +1683,16 @@ static int btree_split(struct btree_update *as, struct btree_trans *trans,
        if (parent) {
                /* Split a non root node */
                ret = bch2_btree_insert_node(as, trans, path, parent, &as->parent_keys);
-               if (ret)
-                       goto err;
        } else if (n3) {
-               bch2_btree_set_root(as, trans, trans->paths + path, n3);
+               ret = bch2_btree_set_root(as, trans, trans->paths + path, n3, false);
        } else {
                /* Root filled up but didn't need to be split */
-               bch2_btree_set_root(as, trans, trans->paths + path, n1);
+               ret = bch2_btree_set_root(as, trans, trans->paths + path, n1, false);
        }
 
+       if (ret)
+               goto err;
+
        if (n3) {
                bch2_btree_update_get_open_buckets(as, n3);
                bch2_btree_node_write(c, n3, SIX_LOCK_intent, 0);
@@ -1863,7 +1895,9 @@ static void __btree_increase_depth(struct btree_update *as, struct btree_trans *
        bch2_keylist_add(&as->parent_keys, &b->key);
        btree_split_insert_keys(as, trans, path_idx, n, &as->parent_keys);
 
-       bch2_btree_set_root(as, trans, path, n);
+       int ret = bch2_btree_set_root(as, trans, path, n, true);
+       BUG_ON(ret);
+
        bch2_btree_update_get_open_buckets(as, n);
        bch2_btree_node_write(c, n, SIX_LOCK_intent, 0);
        bch2_trans_node_add(trans, path, n);
@@ -1916,6 +1950,18 @@ int __bch2_foreground_maybe_merge(struct btree_trans *trans,
        BUG_ON(!trans->paths[path].should_be_locked);
        BUG_ON(!btree_node_locked(&trans->paths[path], level));
 
+       /*
+        * Work around a deadlock caused by the btree write buffer not doing
+        * merges and leaving tons of merges for us to do - we really don't need
+        * to be doing merges at all from the interior update path, and if the
+        * interior update path is generating too many new interior updates we
+        * deadlock:
+        */
+       if ((flags & BCH_WATERMARK_MASK) == BCH_WATERMARK_interior_updates)
+               return 0;
+
+       flags &= ~BCH_WATERMARK_MASK;
+
        b = trans->paths[path].l[level].b;
 
        if ((sib == btree_prev_sib && bpos_eq(b->data->min_key, POS_MIN)) ||
@@ -2061,6 +2107,10 @@ err:
                bch2_path_put(trans, new_path, true);
        bch2_path_put(trans, sib_path, true);
        bch2_trans_verify_locks(trans);
+       if (ret == -BCH_ERR_journal_reclaim_would_deadlock)
+               ret = 0;
+       if (!ret)
+               ret = bch2_trans_relock(trans);
        return ret;
 err_free_update:
        bch2_btree_node_free_never_used(as, trans, n);
@@ -2106,12 +2156,13 @@ int bch2_btree_node_rewrite(struct btree_trans *trans,
        if (parent) {
                bch2_keylist_add(&as->parent_keys, &n->key);
                ret = bch2_btree_insert_node(as, trans, iter->path, parent, &as->parent_keys);
-               if (ret)
-                       goto err;
        } else {
-               bch2_btree_set_root(as, trans, btree_iter_path(trans, iter), n);
+               ret = bch2_btree_set_root(as, trans, btree_iter_path(trans, iter), n, false);
        }
 
+       if (ret)
+               goto err;
+
        bch2_btree_update_get_open_buckets(as, n);
        bch2_btree_node_write(c, n, SIX_LOCK_intent, 0);
 
index baf63e2fddb64cd8f4c745d0cc80c864c86ffaa6..36a6f42aba5e6fc5a36418c1d7565e07e8f90420 100644 (file)
@@ -316,6 +316,16 @@ static int bch2_btree_write_buffer_flush_locked(struct btree_trans *trans)
                            bpos_gt(k->k.k.p, path->l[0].b->key.k.p)) {
                                bch2_btree_node_unlock_write(trans, path, path->l[0].b);
                                write_locked = false;
+
+                               ret = lockrestart_do(trans,
+                                       bch2_btree_iter_traverse(&iter) ?:
+                                       bch2_foreground_maybe_merge(trans, iter.path, 0,
+                                                       BCH_WATERMARK_reclaim|
+                                                       BCH_TRANS_COMMIT_journal_reclaim|
+                                                       BCH_TRANS_COMMIT_no_check_rw|
+                                                       BCH_TRANS_COMMIT_no_enospc));
+                               if (ret)
+                                       goto err;
                        }
                }
 
@@ -382,10 +392,10 @@ static int bch2_btree_write_buffer_flush_locked(struct btree_trans *trans)
 
                        ret = commit_do(trans, NULL, NULL,
                                        BCH_WATERMARK_reclaim|
+                                       BCH_TRANS_COMMIT_journal_reclaim|
                                        BCH_TRANS_COMMIT_no_check_rw|
                                        BCH_TRANS_COMMIT_no_enospc|
-                                       BCH_TRANS_COMMIT_no_journal_res|
-                                       BCH_TRANS_COMMIT_journal_reclaim,
+                                       BCH_TRANS_COMMIT_no_journal_res ,
                                        btree_write_buffered_insert(trans, i));
                        if (ret)
                                goto err;
index 00aaf4bb513974a6b9c0353ea9445f92671c32eb..f9af5adabe83638eea7ffd15ea2f730085f81cc1 100644 (file)
@@ -395,14 +395,6 @@ static inline const char *bch2_data_type_str(enum bch_data_type type)
                : "(invalid data type)";
 }
 
-static inline void bch2_prt_data_type(struct printbuf *out, enum bch_data_type type)
-{
-       if (type < BCH_DATA_NR)
-               prt_str(out, __bch2_data_types[type]);
-       else
-               prt_printf(out, "(invalid data type %u)", type);
-}
-
 /* disk reservations: */
 
 static inline void bch2_disk_reservation_put(struct bch_fs *c,
index 4701457f6381ca820e17a12707009c272ed5b4ac..7ed779b411f61e4e3f05a703ce9e091474237939 100644 (file)
@@ -429,15 +429,20 @@ int bch2_rechecksum_bio(struct bch_fs *c, struct bio *bio,
                                extent_nonce(version, crc_old), bio);
 
        if (bch2_crc_cmp(merged, crc_old.csum) && !c->opts.no_data_io) {
-               bch_err(c, "checksum error in %s() (memory corruption or bug?)\n"
-                       "expected %0llx:%0llx got %0llx:%0llx (old type %s new type %s)",
-                       __func__,
-                       crc_old.csum.hi,
-                       crc_old.csum.lo,
-                       merged.hi,
-                       merged.lo,
-                       bch2_csum_types[crc_old.csum_type],
-                       bch2_csum_types[new_csum_type]);
+               struct printbuf buf = PRINTBUF;
+               prt_printf(&buf, "checksum error in %s() (memory corruption or bug?)\n"
+                          "expected %0llx:%0llx got %0llx:%0llx (old type ",
+                          __func__,
+                          crc_old.csum.hi,
+                          crc_old.csum.lo,
+                          merged.hi,
+                          merged.lo);
+               bch2_prt_csum_type(&buf, crc_old.csum_type);
+               prt_str(&buf, " new type ");
+               bch2_prt_csum_type(&buf, new_csum_type);
+               prt_str(&buf, ")");
+               bch_err(c, "%s", buf.buf);
+               printbuf_exit(&buf);
                return -EIO;
        }
 
index 1b8c2c1016dc6347ce12ef3161d4723835dfa56e..e40499fde9a4019fc75d62f825e9e5583caf803b 100644 (file)
@@ -61,11 +61,12 @@ static inline void bch2_csum_err_msg(struct printbuf *out,
                                     struct bch_csum expected,
                                     struct bch_csum got)
 {
-       prt_printf(out, "checksum error: got ");
+       prt_str(out, "checksum error, type ");
+       bch2_prt_csum_type(out, type);
+       prt_str(out, ": got ");
        bch2_csum_to_text(out, type, got);
        prt_str(out, " should be ");
        bch2_csum_to_text(out, type, expected);
-       prt_printf(out, " type %s", bch2_csum_types[type]);
 }
 
 int bch2_chacha_encrypt_key(struct bch_key *, struct nonce, void *, size_t);
index 58c2eb45570ff022764720f9beb10ecfa2926367..607fd5e232c902dbb39f3dac84ea2e214e6b106c 100644 (file)
@@ -47,14 +47,6 @@ static inline enum bch_compression_type bch2_compression_opt_to_type(unsigned v)
        return __bch2_compression_opt_to_type[bch2_compression_decode(v).type];
 }
 
-static inline void bch2_prt_compression_type(struct printbuf *out, enum bch_compression_type type)
-{
-       if (type < BCH_COMPRESSION_TYPE_NR)
-               prt_str(out, __bch2_compression_types[type]);
-       else
-               prt_printf(out, "(invalid compression type %u)", type);
-}
-
 int bch2_bio_uncompress_inplace(struct bch_fs *, struct bio *,
                                struct bch_extent_crc_unpacked *);
 int bch2_bio_uncompress(struct bch_fs *, struct bio *, struct bio *,
index 082075244e16aedc824249b239ecec6efb1a07fa..556a217108d32ef35890da0463751afc688186f3 100644 (file)
@@ -131,29 +131,33 @@ fsck_err:
 void bch2_stripe_to_text(struct printbuf *out, struct bch_fs *c,
                         struct bkey_s_c k)
 {
-       const struct bch_stripe *s = bkey_s_c_to_stripe(k).v;
-       unsigned i, nr_data = s->nr_blocks - s->nr_redundant;
+       const struct bch_stripe *sp = bkey_s_c_to_stripe(k).v;
+       struct bch_stripe s = {};
+
+       memcpy(&s, sp, min(sizeof(s), bkey_val_bytes(k.k)));
+
+       unsigned nr_data = s.nr_blocks - s.nr_redundant;
+
+       prt_printf(out, "algo %u sectors %u blocks %u:%u csum ",
+                  s.algorithm,
+                  le16_to_cpu(s.sectors),
+                  nr_data,
+                  s.nr_redundant);
+       bch2_prt_csum_type(out, s.csum_type);
+       prt_printf(out, " gran %u", 1U << s.csum_granularity_bits);
+
+       for (unsigned i = 0; i < s.nr_blocks; i++) {
+               const struct bch_extent_ptr *ptr = sp->ptrs + i;
+
+               if ((void *) ptr >= bkey_val_end(k))
+                       break;
+
+               bch2_extent_ptr_to_text(out, c, ptr);
 
-       prt_printf(out, "algo %u sectors %u blocks %u:%u csum %u gran %u",
-              s->algorithm,
-              le16_to_cpu(s->sectors),
-              nr_data,
-              s->nr_redundant,
-              s->csum_type,
-              1U << s->csum_granularity_bits);
-
-       for (i = 0; i < s->nr_blocks; i++) {
-               const struct bch_extent_ptr *ptr = s->ptrs + i;
-               struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev);
-               u32 offset;
-               u64 b = sector_to_bucket_and_offset(ca, ptr->offset, &offset);
-
-               prt_printf(out, " %u:%llu:%u", ptr->dev, b, offset);
-               if (i < nr_data)
-                       prt_printf(out, "#%u", stripe_blockcount_get(s, i));
-               prt_printf(out, " gen %u", ptr->gen);
-               if (ptr_stale(ca, ptr))
-                       prt_printf(out, " stale");
+               if (s.csum_type < BCH_CSUM_NR &&
+                   i < nr_data &&
+                   stripe_blockcount_offset(&s, i) < bkey_val_bytes(k.k))
+                       prt_printf(out,  "#%u", stripe_blockcount_get(sp, i));
        }
 }
 
@@ -607,10 +611,8 @@ static void ec_validate_checksums(struct bch_fs *c, struct ec_stripe_buf *buf)
                                struct printbuf err = PRINTBUF;
                                struct bch_dev *ca = bch_dev_bkey_exists(c, v->ptrs[i].dev);
 
-                               prt_printf(&err, "stripe checksum error: expected %0llx:%0llx got %0llx:%0llx (type %s)\n",
-                                          want.hi, want.lo,
-                                          got.hi, got.lo,
-                                          bch2_csum_types[v->csum_type]);
+                               prt_str(&err, "stripe ");
+                               bch2_csum_err_msg(&err, v->csum_type, want, got);
                                prt_printf(&err, "  for %ps at %u of\n  ", (void *) _RET_IP_, i);
                                bch2_bkey_val_to_text(&err, c, bkey_i_to_s_c(&buf->key));
                                bch_err_ratelimited(ca, "%s", err.buf);
index f4369b02e805f0a24572a8cf87d18867c3d3301a..f042616888b0a1d47d7797e987c912c58d0945b3 100644 (file)
@@ -32,6 +32,8 @@ static inline unsigned stripe_csums_per_device(const struct bch_stripe *s)
 static inline unsigned stripe_csum_offset(const struct bch_stripe *s,
                                          unsigned dev, unsigned csum_idx)
 {
+       EBUG_ON(s->csum_type >= BCH_CSUM_NR);
+
        unsigned csum_bytes = bch_crc_bytes[s->csum_type];
 
        return sizeof(struct bch_stripe) +
index 0e3ca99fbd2de1522c5e8dea8ac313232f60f7f3..1a331e539204852d4db9e7620df0282abe262f1e 100644 (file)
@@ -998,7 +998,9 @@ void bch2_extent_ptr_to_text(struct printbuf *out, struct bch_fs *c, const struc
                        prt_str(out, " cached");
                if (ptr->unwritten)
                        prt_str(out, " unwritten");
-               if (ca && ptr_stale(ca, ptr))
+               if (b >= ca->mi.first_bucket &&
+                   b <  ca->mi.nbuckets &&
+                   ptr_stale(ca, ptr))
                        prt_printf(out, " stale");
        }
 }
@@ -1028,11 +1030,12 @@ void bch2_bkey_ptrs_to_text(struct printbuf *out, struct bch_fs *c,
                        struct bch_extent_crc_unpacked crc =
                                bch2_extent_crc_unpack(k.k, entry_to_crc(entry));
 
-                       prt_printf(out, "crc: c_size %u size %u offset %u nonce %u csum %s compress ",
+                       prt_printf(out, "crc: c_size %u size %u offset %u nonce %u csum ",
                               crc.compressed_size,
                               crc.uncompressed_size,
-                              crc.offset, crc.nonce,
-                              bch2_csum_types[crc.csum_type]);
+                              crc.offset, crc.nonce);
+                       bch2_prt_csum_type(out, crc.csum_type);
+                       prt_str(out, " compress ");
                        bch2_prt_compression_type(out, crc.compression_type);
                        break;
                }
index f49e6c0f0f6835968202ab2f1fa194933945554a..b889370a5088113a2417787bdbb4b98a16597063 100644 (file)
@@ -387,6 +387,8 @@ static __always_inline long bch2_dio_write_done(struct dio_write *dio)
        ret = dio->op.error ?: ((long) dio->written << 9);
        bio_put(&dio->op.wbio.bio);
 
+       bch2_write_ref_put(dio->op.c, BCH_WRITE_REF_dio_write);
+
        /* inode->i_dio_count is our ref on inode and thus bch_fs */
        inode_dio_end(&inode->v);
 
@@ -590,22 +592,25 @@ ssize_t bch2_direct_write(struct kiocb *req, struct iov_iter *iter)
        prefetch(&inode->ei_inode);
        prefetch((void *) &inode->ei_inode + 64);
 
+       if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_dio_write))
+               return -EROFS;
+
        inode_lock(&inode->v);
 
        ret = generic_write_checks(req, iter);
        if (unlikely(ret <= 0))
-               goto err;
+               goto err_put_write_ref;
 
        ret = file_remove_privs(file);
        if (unlikely(ret))
-               goto err;
+               goto err_put_write_ref;
 
        ret = file_update_time(file);
        if (unlikely(ret))
-               goto err;
+               goto err_put_write_ref;
 
        if (unlikely((req->ki_pos|iter->count) & (block_bytes(c) - 1)))
-               goto err;
+               goto err_put_write_ref;
 
        inode_dio_begin(&inode->v);
        bch2_pagecache_block_get(inode);
@@ -645,7 +650,7 @@ ssize_t bch2_direct_write(struct kiocb *req, struct iov_iter *iter)
        }
 
        ret = bch2_dio_write_loop(dio);
-err:
+out:
        if (locked)
                inode_unlock(&inode->v);
        return ret;
@@ -653,7 +658,9 @@ err_put_bio:
        bch2_pagecache_block_put(inode);
        bio_put(bio);
        inode_dio_end(&inode->v);
-       goto err;
+err_put_write_ref:
+       bch2_write_ref_put(c, BCH_WRITE_REF_dio_write);
+       goto out;
 }
 
 void bch2_fs_fs_io_direct_exit(struct bch_fs *c)
index 8c70123b6a0c809b6d50040593281c2e9c115828..20b40477425f49449499b11d63930d92e10ed3ba 100644 (file)
@@ -174,18 +174,18 @@ void __bch2_i_sectors_acct(struct bch_fs *c, struct bch_inode_info *inode,
 static int bch2_flush_inode(struct bch_fs *c,
                            struct bch_inode_info *inode)
 {
-       struct bch_inode_unpacked u;
-       int ret;
-
        if (c->opts.journal_flush_disabled)
                return 0;
 
-       ret = bch2_inode_find_by_inum(c, inode_inum(inode), &u);
-       if (ret)
-               return ret;
+       if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_fsync))
+               return -EROFS;
 
-       return bch2_journal_flush_seq(&c->journal, u.bi_journal_seq) ?:
-               bch2_inode_flush_nocow_writes(c, inode);
+       struct bch_inode_unpacked u;
+       int ret = bch2_inode_find_by_inum(c, inode_inum(inode), &u) ?:
+                 bch2_journal_flush_seq(&c->journal, u.bi_journal_seq) ?:
+                 bch2_inode_flush_nocow_writes(c, inode);
+       bch2_write_ref_put(c, BCH_WRITE_REF_fsync);
+       return ret;
 }
 
 int bch2_fsync(struct file *file, loff_t start, loff_t end, int datasync)
index 725fcf46f6312c267c2a7c05f1eaa6aed5fb83e7..9aa28b52ab926c567f49e0bb68b9c6791fb326e5 100644 (file)
@@ -247,7 +247,7 @@ static void journal_entry_err_msg(struct printbuf *out,
 
        if (entry) {
                prt_str(out, " type=");
-               prt_str(out, bch2_jset_entry_types[entry->type]);
+               bch2_prt_jset_entry_type(out, entry->type);
        }
 
        if (!jset) {
@@ -403,7 +403,8 @@ static void journal_entry_btree_keys_to_text(struct printbuf *out, struct bch_fs
        jset_entry_for_each_key(entry, k) {
                if (!first) {
                        prt_newline(out);
-                       prt_printf(out, "%s: ", bch2_jset_entry_types[entry->type]);
+                       bch2_prt_jset_entry_type(out, entry->type);
+                       prt_str(out, ": ");
                }
                prt_printf(out, "btree=%s l=%u ", bch2_btree_id_str(entry->btree_id), entry->level);
                bch2_bkey_val_to_text(out, c, bkey_i_to_s_c(k));
@@ -563,9 +564,9 @@ static void journal_entry_usage_to_text(struct printbuf *out, struct bch_fs *c,
        struct jset_entry_usage *u =
                container_of(entry, struct jset_entry_usage, entry);
 
-       prt_printf(out, "type=%s v=%llu",
-              bch2_fs_usage_types[u->entry.btree_id],
-              le64_to_cpu(u->v));
+       prt_str(out, "type=");
+       bch2_prt_fs_usage_type(out, u->entry.btree_id);
+       prt_printf(out, " v=%llu", le64_to_cpu(u->v));
 }
 
 static int journal_entry_data_usage_validate(struct bch_fs *c,
@@ -827,11 +828,11 @@ int bch2_journal_entry_validate(struct bch_fs *c,
 void bch2_journal_entry_to_text(struct printbuf *out, struct bch_fs *c,
                                struct jset_entry *entry)
 {
+       bch2_prt_jset_entry_type(out, entry->type);
+
        if (entry->type < BCH_JSET_ENTRY_NR) {
-               prt_printf(out, "%s: ", bch2_jset_entry_types[entry->type]);
+               prt_str(out, ": ");
                bch2_jset_entry_ops[entry->type].to_text(out, c, entry);
-       } else {
-               prt_printf(out, "(unknown type %u)", entry->type);
        }
 }
 
index e1800c4119b5fbaf8ebbfcdaef996e1dd9c35ca8..bb068fd724656cf8307d14022ca537f918b65747 100644 (file)
@@ -43,7 +43,7 @@ const char * const __bch2_btree_ids[] = {
        NULL
 };
 
-const char * const bch2_csum_types[] = {
+static const char * const __bch2_csum_types[] = {
        BCH_CSUM_TYPES()
        NULL
 };
@@ -53,7 +53,7 @@ const char * const bch2_csum_opts[] = {
        NULL
 };
 
-const char * const __bch2_compression_types[] = {
+static const char * const __bch2_compression_types[] = {
        BCH_COMPRESSION_TYPES()
        NULL
 };
@@ -83,18 +83,39 @@ const char * const bch2_member_states[] = {
        NULL
 };
 
-const char * const bch2_jset_entry_types[] = {
+static const char * const __bch2_jset_entry_types[] = {
        BCH_JSET_ENTRY_TYPES()
        NULL
 };
 
-const char * const bch2_fs_usage_types[] = {
+static const char * const __bch2_fs_usage_types[] = {
        BCH_FS_USAGE_TYPES()
        NULL
 };
 
 #undef x
 
+static void prt_str_opt_boundscheck(struct printbuf *out, const char * const opts[],
+                                   unsigned nr, const char *type, unsigned idx)
+{
+       if (idx < nr)
+               prt_str(out, opts[idx]);
+       else
+               prt_printf(out, "(unknown %s %u)", type, idx);
+}
+
+#define PRT_STR_OPT_BOUNDSCHECKED(name, type)                                  \
+void bch2_prt_##name(struct printbuf *out, type t)                             \
+{                                                                              \
+       prt_str_opt_boundscheck(out, __bch2_##name##s, ARRAY_SIZE(__bch2_##name##s) - 1, #name, t);\
+}
+
+PRT_STR_OPT_BOUNDSCHECKED(jset_entry_type,     enum bch_jset_entry_type);
+PRT_STR_OPT_BOUNDSCHECKED(fs_usage_type,       enum bch_fs_usage_type);
+PRT_STR_OPT_BOUNDSCHECKED(data_type,           enum bch_data_type);
+PRT_STR_OPT_BOUNDSCHECKED(csum_type,           enum bch_csum_type);
+PRT_STR_OPT_BOUNDSCHECKED(compression_type,    enum bch_compression_type);
+
 static int bch2_opt_fix_errors_parse(struct bch_fs *c, const char *val, u64 *res,
                                     struct printbuf *err)
 {
index 1ac4135cca1c3dccc71a75a0d062ee30df33111c..84e452835a17d84d36c4d0f3906501578bf702d3 100644 (file)
@@ -16,18 +16,20 @@ extern const char * const bch2_version_upgrade_opts[];
 extern const char * const bch2_sb_features[];
 extern const char * const bch2_sb_compat[];
 extern const char * const __bch2_btree_ids[];
-extern const char * const bch2_csum_types[];
 extern const char * const bch2_csum_opts[];
-extern const char * const __bch2_compression_types[];
 extern const char * const bch2_compression_opts[];
 extern const char * const bch2_str_hash_types[];
 extern const char * const bch2_str_hash_opts[];
 extern const char * const __bch2_data_types[];
 extern const char * const bch2_member_states[];
-extern const char * const bch2_jset_entry_types[];
-extern const char * const bch2_fs_usage_types[];
 extern const char * const bch2_d_types[];
 
+void bch2_prt_jset_entry_type(struct printbuf *,       enum bch_jset_entry_type);
+void bch2_prt_fs_usage_type(struct printbuf *,         enum bch_fs_usage_type);
+void bch2_prt_data_type(struct printbuf *,             enum bch_data_type);
+void bch2_prt_csum_type(struct printbuf *,             enum bch_csum_type);
+void bch2_prt_compression_type(struct printbuf *,      enum bch_compression_type);
+
 static inline const char *bch2_d_type_str(unsigned d_type)
 {
        return (d_type < BCH_DT_MAX ? bch2_d_types[d_type] : NULL) ?: "(bad d_type)";
index cb501460d6152b31a4ae57d9dea6db0792c47c0f..0cec0f7d9703520a3cf24bcc2ca2ce7f86285ebc 100644 (file)
@@ -44,7 +44,7 @@ static int bch2_set_may_go_rw(struct bch_fs *c)
 
        set_bit(BCH_FS_may_go_rw, &c->flags);
 
-       if (keys->nr || c->opts.fsck || !c->sb.clean)
+       if (keys->nr || c->opts.fsck || !c->sb.clean || c->recovery_passes_explicit)
                return bch2_fs_read_write_early(c);
        return 0;
 }
index d6f81179c3a29b6e884f92c94628d512626c6b45..a98ef940b7a3280bd0da0474ef4f387fdcd0cc18 100644 (file)
          BCH_FSCK_ERR_subvol_fs_path_parent_wrong)             \
        x(btree_subvolume_children,                             \
          BIT_ULL(BCH_RECOVERY_PASS_check_subvols),             \
-         BCH_FSCK_ERR_subvol_children_not_set)
+         BCH_FSCK_ERR_subvol_children_not_set)                 \
+       x(mi_btree_bitmap,                                      \
+         BIT_ULL(BCH_RECOVERY_PASS_check_allocations),         \
+         BCH_FSCK_ERR_btree_bitmap_not_marked)
 
 #define DOWNGRADE_TABLE()
 
index d7d609131030a817c5fa2867fc3cee5796fb898c..4ca6e7b0d8aaed2c4b95fff82c2ed964c6a102ad 100644 (file)
        x(bucket_gens_nonzero_for_invalid_buckets,              122)    \
        x(need_discard_freespace_key_to_invalid_dev_bucket,     123)    \
        x(need_discard_freespace_key_bad,                       124)    \
-       x(backpointer_pos_wrong,                                125)    \
+       x(backpointer_bucket_offset_wrong,                      125)    \
        x(backpointer_to_missing_device,                        126)    \
        x(backpointer_to_missing_alloc,                         127)    \
        x(backpointer_to_missing_ptr,                           128)    \
        x(btree_ptr_v2_min_key_bad,                             262)    \
        x(btree_root_unreadable_and_scan_found_nothing,         263)    \
        x(snapshot_node_missing,                                264)    \
-       x(dup_backpointer_to_bad_csum_extent,                   265)
+       x(dup_backpointer_to_bad_csum_extent,                   265)    \
+       x(btree_bitmap_not_marked,                              266)
 
 enum bch_sb_error_id {
 #define x(t, n) BCH_FSCK_ERR_##t = n,
index eff5ce18c69c0600047c1fef688a5980af33c678..522a969345e5289ac87cf53b5f5a735e3b5f8d67 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 
 #include "bcachefs.h"
+#include "btree_cache.h"
 #include "disk_groups.h"
 #include "opts.h"
 #include "replicas.h"
@@ -426,3 +427,55 @@ void bch2_dev_errors_reset(struct bch_dev *ca)
        bch2_write_super(c);
        mutex_unlock(&c->sb_lock);
 }
+
+/*
+ * Per member "range has btree nodes" bitmap:
+ *
+ * This is so that if we ever have to run the btree node scan to repair we don't
+ * have to scan full devices:
+ */
+
+bool bch2_dev_btree_bitmap_marked(struct bch_fs *c, struct bkey_s_c k)
+{
+       bkey_for_each_ptr(bch2_bkey_ptrs_c(k), ptr)
+               if (!bch2_dev_btree_bitmap_marked_sectors(bch_dev_bkey_exists(c, ptr->dev),
+                                                         ptr->offset, btree_sectors(c)))
+                       return false;
+       return true;
+}
+
+static void __bch2_dev_btree_bitmap_mark(struct bch_sb_field_members_v2 *mi, unsigned dev,
+                               u64 start, unsigned sectors)
+{
+       struct bch_member *m = __bch2_members_v2_get_mut(mi, dev);
+       u64 bitmap = le64_to_cpu(m->btree_allocated_bitmap);
+
+       u64 end = start + sectors;
+
+       int resize = ilog2(roundup_pow_of_two(end)) - (m->btree_bitmap_shift + 6);
+       if (resize > 0) {
+               u64 new_bitmap = 0;
+
+               for (unsigned i = 0; i < 64; i++)
+                       if (bitmap & BIT_ULL(i))
+                               new_bitmap |= BIT_ULL(i >> resize);
+               bitmap = new_bitmap;
+               m->btree_bitmap_shift += resize;
+       }
+
+       for (unsigned bit = sectors >> m->btree_bitmap_shift;
+            bit << m->btree_bitmap_shift < end;
+            bit++)
+               bitmap |= BIT_ULL(bit);
+
+       m->btree_allocated_bitmap = cpu_to_le64(bitmap);
+}
+
+void bch2_dev_btree_bitmap_mark(struct bch_fs *c, struct bkey_s_c k)
+{
+       lockdep_assert_held(&c->sb_lock);
+
+       struct bch_sb_field_members_v2 *mi = bch2_sb_field_get(c->disk_sb.sb, members_v2);
+       bkey_for_each_ptr(bch2_bkey_ptrs_c(k), ptr)
+               __bch2_dev_btree_bitmap_mark(mi, ptr->dev, ptr->offset, btree_sectors(c));
+}
index be0a941832715a32634b8c3dea60bbf1685a672f..b27c3e4467cf288d67587143e5343d57d5aa41c9 100644 (file)
@@ -3,6 +3,7 @@
 #define _BCACHEFS_SB_MEMBERS_H
 
 #include "darray.h"
+#include "bkey_types.h"
 
 extern char * const bch2_member_error_strs[];
 
@@ -220,6 +221,8 @@ static inline struct bch_member_cpu bch2_mi_to_cpu(struct bch_member *mi)
                        : 1,
                .freespace_initialized = BCH_MEMBER_FREESPACE_INITIALIZED(mi),
                .valid          = bch2_member_exists(mi),
+               .btree_bitmap_shift     = mi->btree_bitmap_shift,
+               .btree_allocated_bitmap = le64_to_cpu(mi->btree_allocated_bitmap),
        };
 }
 
@@ -228,4 +231,22 @@ void bch2_sb_members_from_cpu(struct bch_fs *);
 void bch2_dev_io_errors_to_text(struct printbuf *, struct bch_dev *);
 void bch2_dev_errors_reset(struct bch_dev *);
 
+static inline bool bch2_dev_btree_bitmap_marked_sectors(struct bch_dev *ca, u64 start, unsigned sectors)
+{
+       u64 end = start + sectors;
+
+       if (end > 64 << ca->mi.btree_bitmap_shift)
+               return false;
+
+       for (unsigned bit = sectors >> ca->mi.btree_bitmap_shift;
+            bit << ca->mi.btree_bitmap_shift < end;
+            bit++)
+               if (!(ca->mi.btree_allocated_bitmap & BIT_ULL(bit)))
+                       return false;
+       return true;
+}
+
+bool bch2_dev_btree_bitmap_marked(struct bch_fs *, struct bkey_s_c);
+void bch2_dev_btree_bitmap_mark(struct bch_fs *, struct bkey_s_c);
+
 #endif /* _BCACHEFS_SB_MEMBERS_H */
index 5eee055ee2721a3967fb31ca38adcbc5672521d6..08ea3dbbbe97ce11833fe79baa5fd87935919339 100644 (file)
@@ -700,8 +700,11 @@ retry:
                return -ENOMEM;
 
        sb->sb_name = kstrdup(path, GFP_KERNEL);
-       if (!sb->sb_name)
-               return -ENOMEM;
+       if (!sb->sb_name) {
+               ret = -ENOMEM;
+               prt_printf(&err, "error allocating memory for sb_name");
+               goto err;
+       }
 
 #ifndef __KERNEL__
        if (opt_get(*opts, direct_io) == false)
index ec784d975f6655a378207692644975e53271ddca..11bcef170c2c22644108e9fbec9b24eaf478059c 100644 (file)
@@ -37,6 +37,8 @@ struct bch_member_cpu {
        u8                      durability;
        u8                      freespace_initialized;
        u8                      valid;
+       u8                      btree_bitmap_shift;
+       u64                     btree_allocated_bitmap;
 };
 
 #endif /* _BCACHEFS_SUPER_TYPES_H */
index b18b0cc81b594ad6144b43599418418a1caf5e95..5be92fe3f4ea4e115512f0b7a31482919406a507 100644 (file)
@@ -25,6 +25,7 @@
 #include "ec.h"
 #include "inode.h"
 #include "journal.h"
+#include "journal_reclaim.h"
 #include "keylist.h"
 #include "move.h"
 #include "movinggc.h"
@@ -138,6 +139,7 @@ do {                                                                        \
 write_attribute(trigger_gc);
 write_attribute(trigger_discards);
 write_attribute(trigger_invalidates);
+write_attribute(trigger_journal_flush);
 write_attribute(prune_cache);
 write_attribute(btree_wakeup);
 rw_attribute(btree_gc_periodic);
@@ -500,7 +502,7 @@ STORE(bch2_fs)
 
        /* Debugging: */
 
-       if (!test_bit(BCH_FS_rw, &c->flags))
+       if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_sysfs))
                return -EROFS;
 
        if (attr == &sysfs_prune_cache) {
@@ -533,6 +535,11 @@ STORE(bch2_fs)
        if (attr == &sysfs_trigger_invalidates)
                bch2_do_invalidates(c);
 
+       if (attr == &sysfs_trigger_journal_flush) {
+               bch2_journal_flush_all_pins(&c->journal);
+               bch2_journal_meta(&c->journal);
+       }
+
 #ifdef CONFIG_BCACHEFS_TESTS
        if (attr == &sysfs_perf_test) {
                char *tmp = kstrdup(buf, GFP_KERNEL), *p = tmp;
@@ -553,6 +560,7 @@ STORE(bch2_fs)
                        size = ret;
        }
 #endif
+       bch2_write_ref_put(c, BCH_WRITE_REF_sysfs);
        return size;
 }
 SYSFS_OPS(bch2_fs);
@@ -651,6 +659,7 @@ struct attribute *bch2_fs_internal_files[] = {
        &sysfs_trigger_gc,
        &sysfs_trigger_discards,
        &sysfs_trigger_invalidates,
+       &sysfs_trigger_journal_flush,
        &sysfs_prune_cache,
        &sysfs_btree_wakeup,
 
index beedd6ed64d39bd7f53ad814c22df36b80b96235..257d044bca9158c95e205ff22ff0d662d0d7f074 100644 (file)
@@ -3464,6 +3464,14 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
        if (root_id != BTRFS_TREE_LOG_OBJECTID) {
                struct btrfs_ref generic_ref = { 0 };
 
+               /*
+                * Assert that the extent buffer is not cleared due to
+                * EXTENT_BUFFER_ZONED_ZEROOUT. Please refer
+                * btrfs_clear_buffer_dirty() and btree_csum_one_bio() for
+                * detail.
+                */
+               ASSERT(btrfs_header_bytenr(buf) != 0);
+
                btrfs_init_generic_ref(&generic_ref, BTRFS_DROP_DELAYED_REF,
                                       buf->start, buf->len, parent,
                                       btrfs_header_owner(buf));
index 61594eaf1f8969fc3ba04604e3470a8932450767..2776112dbdf8d471a7cb4d515fdd443e6fadbac5 100644 (file)
@@ -681,31 +681,21 @@ static void end_bbio_data_read(struct btrfs_bio *bbio)
 int btrfs_alloc_page_array(unsigned int nr_pages, struct page **page_array,
                           gfp_t extra_gfp)
 {
+       const gfp_t gfp = GFP_NOFS | extra_gfp;
        unsigned int allocated;
 
        for (allocated = 0; allocated < nr_pages;) {
                unsigned int last = allocated;
 
-               allocated = alloc_pages_bulk_array(GFP_NOFS | extra_gfp,
-                                                  nr_pages, page_array);
-
-               if (allocated == nr_pages)
-                       return 0;
-
-               /*
-                * During this iteration, no page could be allocated, even
-                * though alloc_pages_bulk_array() falls back to alloc_page()
-                * if  it could not bulk-allocate. So we must be out of memory.
-                */
-               if (allocated == last) {
+               allocated = alloc_pages_bulk_array(gfp, nr_pages, page_array);
+               if (unlikely(allocated == last)) {
+                       /* No progress, fail and do cleanup. */
                        for (int i = 0; i < allocated; i++) {
                                __free_page(page_array[i]);
                                page_array[i] = NULL;
                        }
                        return -ENOMEM;
                }
-
-               memalloc_retry_wait(GFP_NOFS);
        }
        return 0;
 }
@@ -4154,7 +4144,7 @@ void btrfs_clear_buffer_dirty(struct btrfs_trans_handle *trans,
         * The actual zeroout of the buffer will happen later in
         * btree_csum_one_bio.
         */
-       if (btrfs_is_zoned(fs_info)) {
+       if (btrfs_is_zoned(fs_info) && test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags)) {
                set_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags);
                return;
        }
@@ -4193,6 +4183,7 @@ void set_extent_buffer_dirty(struct extent_buffer *eb)
        num_folios = num_extent_folios(eb);
        WARN_ON(atomic_read(&eb->refs) == 0);
        WARN_ON(!test_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags));
+       WARN_ON(test_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags));
 
        if (!was_dirty) {
                bool subpage = eb->fs_info->nodesize < PAGE_SIZE;
index b6cad106c37e44258bd6e4433cd4aaedfbb98f65..0b2da7b7e2ad019ebf363ba652480476f702a75d 100644 (file)
@@ -310,6 +310,10 @@ struct cuse_init_args {
 /**
  * cuse_process_init_reply - finish initializing CUSE channel
  *
+ * @fm: The fuse mount information containing the CUSE connection.
+ * @args: The arguments passed to the init reply.
+ * @error: The error code signifying if any error occurred during the process.
+ *
  * This function creates the character device and sets up all the
  * required data structures for it.  Please read the comment at the
  * top of this file for high level overview.
index 4a6df591add61cd8960caa213e2102643bd2c8db..2b0d4781f39484d50d1fd7f4f673d8b08c5fd7cf 100644 (file)
@@ -1321,6 +1321,7 @@ retry:
                        err = fuse_do_statx(inode, file, stat);
                        if (err == -ENOSYS) {
                                fc->no_statx = 1;
+                               err = 0;
                                goto retry;
                        }
                } else {
index a56e7bffd0004e3755d648ad9b35f67d4eba863a..b57ce41576407be3d910da8916629f640668ee9a 100644 (file)
@@ -1362,7 +1362,7 @@ static void fuse_dio_lock(struct kiocb *iocb, struct iov_iter *from,
                          bool *exclusive)
 {
        struct inode *inode = file_inode(iocb->ki_filp);
-       struct fuse_file *ff = iocb->ki_filp->private_data;
+       struct fuse_inode *fi = get_fuse_inode(inode);
 
        *exclusive = fuse_dio_wr_exclusive_lock(iocb, from);
        if (*exclusive) {
@@ -1377,7 +1377,7 @@ static void fuse_dio_lock(struct kiocb *iocb, struct iov_iter *from,
                 * have raced, so check it again.
                 */
                if (fuse_io_past_eof(iocb, from) ||
-                   fuse_file_uncached_io_start(inode, ff, NULL) != 0) {
+                   fuse_inode_uncached_io_start(fi, NULL) != 0) {
                        inode_unlock_shared(inode);
                        inode_lock(inode);
                        *exclusive = true;
@@ -1388,13 +1388,13 @@ static void fuse_dio_lock(struct kiocb *iocb, struct iov_iter *from,
 static void fuse_dio_unlock(struct kiocb *iocb, bool exclusive)
 {
        struct inode *inode = file_inode(iocb->ki_filp);
-       struct fuse_file *ff = iocb->ki_filp->private_data;
+       struct fuse_inode *fi = get_fuse_inode(inode);
 
        if (exclusive) {
                inode_unlock(inode);
        } else {
                /* Allow opens in caching mode after last parallel dio end */
-               fuse_file_uncached_io_end(inode, ff);
+               fuse_inode_uncached_io_end(fi);
                inode_unlock_shared(inode);
        }
 }
@@ -2574,8 +2574,10 @@ static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
                 * First mmap of direct_io file enters caching inode io mode.
                 * Also waits for parallel dio writers to go into serial mode
                 * (exclusive instead of shared lock).
+                * After first mmap, the inode stays in caching io mode until
+                * the direct_io file release.
                 */
-               rc = fuse_file_cached_io_start(inode, ff);
+               rc = fuse_file_cached_io_open(inode, ff);
                if (rc)
                        return rc;
        }
index b24084b60864ee57c82864cffda5048dc7f45fb7..f2391961031374d8d55916c326c6472f0c03aae6 100644 (file)
@@ -1394,9 +1394,10 @@ int fuse_fileattr_set(struct mnt_idmap *idmap,
                      struct dentry *dentry, struct fileattr *fa);
 
 /* iomode.c */
-int fuse_file_cached_io_start(struct inode *inode, struct fuse_file *ff);
-int fuse_file_uncached_io_start(struct inode *inode, struct fuse_file *ff, struct fuse_backing *fb);
-void fuse_file_uncached_io_end(struct inode *inode, struct fuse_file *ff);
+int fuse_file_cached_io_open(struct inode *inode, struct fuse_file *ff);
+int fuse_inode_uncached_io_start(struct fuse_inode *fi,
+                                struct fuse_backing *fb);
+void fuse_inode_uncached_io_end(struct fuse_inode *fi);
 
 int fuse_file_io_open(struct file *file, struct inode *inode);
 void fuse_file_io_release(struct fuse_file *ff, struct inode *inode);
index 3a5d888783353cce48e18243ea386e97c788e12a..99e44ea7d8756ded7145f38b49d129b361b991ba 100644 (file)
@@ -175,6 +175,7 @@ static void fuse_evict_inode(struct inode *inode)
                }
        }
        if (S_ISREG(inode->i_mode) && !fuse_is_bad(inode)) {
+               WARN_ON(fi->iocachectr != 0);
                WARN_ON(!list_empty(&fi->write_files));
                WARN_ON(!list_empty(&fi->queued_writes));
        }
index c653ddcf057872663237a0be1820257a656d4945..c99e285f3183ef92f7662ac84956ad1a03315ea9 100644 (file)
@@ -21,12 +21,13 @@ static inline bool fuse_is_io_cache_wait(struct fuse_inode *fi)
 }
 
 /*
- * Start cached io mode.
+ * Called on cached file open() and on first mmap() of direct_io file.
+ * Takes cached_io inode mode reference to be dropped on file release.
  *
  * Blocks new parallel dio writes and waits for the in-progress parallel dio
  * writes to complete.
  */
-int fuse_file_cached_io_start(struct inode *inode, struct fuse_file *ff)
+int fuse_file_cached_io_open(struct inode *inode, struct fuse_file *ff)
 {
        struct fuse_inode *fi = get_fuse_inode(inode);
 
@@ -67,10 +68,9 @@ int fuse_file_cached_io_start(struct inode *inode, struct fuse_file *ff)
        return 0;
 }
 
-static void fuse_file_cached_io_end(struct inode *inode, struct fuse_file *ff)
+static void fuse_file_cached_io_release(struct fuse_file *ff,
+                                       struct fuse_inode *fi)
 {
-       struct fuse_inode *fi = get_fuse_inode(inode);
-
        spin_lock(&fi->lock);
        WARN_ON(fi->iocachectr <= 0);
        WARN_ON(ff->iomode != IOM_CACHED);
@@ -82,16 +82,15 @@ static void fuse_file_cached_io_end(struct inode *inode, struct fuse_file *ff)
 }
 
 /* Start strictly uncached io mode where cache access is not allowed */
-int fuse_file_uncached_io_start(struct inode *inode, struct fuse_file *ff, struct fuse_backing *fb)
+int fuse_inode_uncached_io_start(struct fuse_inode *fi, struct fuse_backing *fb)
 {
-       struct fuse_inode *fi = get_fuse_inode(inode);
        struct fuse_backing *oldfb;
        int err = 0;
 
        spin_lock(&fi->lock);
        /* deny conflicting backing files on same fuse inode */
        oldfb = fuse_inode_backing(fi);
-       if (oldfb && oldfb != fb) {
+       if (fb && oldfb && oldfb != fb) {
                err = -EBUSY;
                goto unlock;
        }
@@ -99,12 +98,10 @@ int fuse_file_uncached_io_start(struct inode *inode, struct fuse_file *ff, struc
                err = -ETXTBSY;
                goto unlock;
        }
-       WARN_ON(ff->iomode != IOM_NONE);
        fi->iocachectr--;
-       ff->iomode = IOM_UNCACHED;
 
        /* fuse inode holds a single refcount of backing file */
-       if (!oldfb) {
+       if (fb && !oldfb) {
                oldfb = fuse_inode_backing_set(fi, fb);
                WARN_ON_ONCE(oldfb != NULL);
        } else {
@@ -115,15 +112,29 @@ unlock:
        return err;
 }
 
-void fuse_file_uncached_io_end(struct inode *inode, struct fuse_file *ff)
+/* Takes uncached_io inode mode reference to be dropped on file release */
+static int fuse_file_uncached_io_open(struct inode *inode,
+                                     struct fuse_file *ff,
+                                     struct fuse_backing *fb)
 {
        struct fuse_inode *fi = get_fuse_inode(inode);
+       int err;
+
+       err = fuse_inode_uncached_io_start(fi, fb);
+       if (err)
+               return err;
+
+       WARN_ON(ff->iomode != IOM_NONE);
+       ff->iomode = IOM_UNCACHED;
+       return 0;
+}
+
+void fuse_inode_uncached_io_end(struct fuse_inode *fi)
+{
        struct fuse_backing *oldfb = NULL;
 
        spin_lock(&fi->lock);
        WARN_ON(fi->iocachectr >= 0);
-       WARN_ON(ff->iomode != IOM_UNCACHED);
-       ff->iomode = IOM_NONE;
        fi->iocachectr++;
        if (!fi->iocachectr) {
                wake_up(&fi->direct_io_waitq);
@@ -134,6 +145,15 @@ void fuse_file_uncached_io_end(struct inode *inode, struct fuse_file *ff)
                fuse_backing_put(oldfb);
 }
 
+/* Drop uncached_io reference from passthrough open */
+static void fuse_file_uncached_io_release(struct fuse_file *ff,
+                                         struct fuse_inode *fi)
+{
+       WARN_ON(ff->iomode != IOM_UNCACHED);
+       ff->iomode = IOM_NONE;
+       fuse_inode_uncached_io_end(fi);
+}
+
 /*
  * Open flags that are allowed in combination with FOPEN_PASSTHROUGH.
  * A combination of FOPEN_PASSTHROUGH and FOPEN_DIRECT_IO means that read/write
@@ -163,7 +183,7 @@ static int fuse_file_passthrough_open(struct inode *inode, struct file *file)
                return PTR_ERR(fb);
 
        /* First passthrough file open denies caching inode io mode */
-       err = fuse_file_uncached_io_start(inode, ff, fb);
+       err = fuse_file_uncached_io_open(inode, ff, fb);
        if (!err)
                return 0;
 
@@ -216,7 +236,7 @@ int fuse_file_io_open(struct file *file, struct inode *inode)
        if (ff->open_flags & FOPEN_PASSTHROUGH)
                err = fuse_file_passthrough_open(inode, file);
        else
-               err = fuse_file_cached_io_start(inode, ff);
+               err = fuse_file_cached_io_open(inode, ff);
        if (err)
                goto fail;
 
@@ -236,8 +256,10 @@ fail:
 /* No more pending io and no new io possible to inode via open/mmapped file */
 void fuse_file_io_release(struct fuse_file *ff, struct inode *inode)
 {
+       struct fuse_inode *fi = get_fuse_inode(inode);
+
        /*
-        * Last parallel dio close allows caching inode io mode.
+        * Last passthrough file close allows caching inode io mode.
         * Last caching file close exits caching inode io mode.
         */
        switch (ff->iomode) {
@@ -245,10 +267,10 @@ void fuse_file_io_release(struct fuse_file *ff, struct inode *inode)
                /* Nothing to do */
                break;
        case IOM_UNCACHED:
-               fuse_file_uncached_io_end(inode, ff);
+               fuse_file_uncached_io_release(ff, fi);
                break;
        case IOM_CACHED:
-               fuse_file_cached_io_end(inode, ff);
+               fuse_file_cached_io_release(ff, fi);
                break;
        }
 }
index fac938f563ad022ce79cdc5f67321bc7f529cc1c..1955481832e03796170ea8f80361bc25cc452ca6 100644 (file)
@@ -3490,11 +3490,13 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
                    struct dentry *dentry, const u32 *bmval,
                    int ignore_crossmnt)
 {
+       DECLARE_BITMAP(attr_bitmap, ARRAY_SIZE(nfsd4_enc_fattr4_encode_ops));
        struct nfsd4_fattr_args args;
        struct svc_fh *tempfh = NULL;
        int starting_len = xdr->buf->len;
        __be32 *attrlen_p, status;
        int attrlen_offset;
+       u32 attrmask[3];
        int err;
        struct nfsd4_compoundres *resp = rqstp->rq_resp;
        u32 minorversion = resp->cstate.minorversion;
@@ -3502,10 +3504,6 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
                .mnt    = exp->ex_path.mnt,
                .dentry = dentry,
        };
-       union {
-               u32             attrmask[3];
-               unsigned long   mask[2];
-       } u;
        unsigned long bit;
        bool file_modified = false;
        u64 size = 0;
@@ -3521,20 +3519,19 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
        /*
         * Make a local copy of the attribute bitmap that can be modified.
         */
-       memset(&u, 0, sizeof(u));
-       u.attrmask[0] = bmval[0];
-       u.attrmask[1] = bmval[1];
-       u.attrmask[2] = bmval[2];
+       attrmask[0] = bmval[0];
+       attrmask[1] = bmval[1];
+       attrmask[2] = bmval[2];
 
        args.rdattr_err = 0;
        if (exp->ex_fslocs.migrated) {
-               status = fattr_handle_absent_fs(&u.attrmask[0], &u.attrmask[1],
-                                               &u.attrmask[2], &args.rdattr_err);
+               status = fattr_handle_absent_fs(&attrmask[0], &attrmask[1],
+                                               &attrmask[2], &args.rdattr_err);
                if (status)
                        goto out;
        }
        args.size = 0;
-       if (u.attrmask[0] & (FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE)) {
+       if (attrmask[0] & (FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE)) {
                status = nfsd4_deleg_getattr_conflict(rqstp, d_inode(dentry),
                                        &file_modified, &size);
                if (status)
@@ -3553,16 +3550,16 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 
        if (!(args.stat.result_mask & STATX_BTIME))
                /* underlying FS does not offer btime so we can't share it */
-               u.attrmask[1] &= ~FATTR4_WORD1_TIME_CREATE;
-       if ((u.attrmask[0] & (FATTR4_WORD0_FILES_AVAIL | FATTR4_WORD0_FILES_FREE |
+               attrmask[1] &= ~FATTR4_WORD1_TIME_CREATE;
+       if ((attrmask[0] & (FATTR4_WORD0_FILES_AVAIL | FATTR4_WORD0_FILES_FREE |
                        FATTR4_WORD0_FILES_TOTAL | FATTR4_WORD0_MAXNAME)) ||
-           (u.attrmask[1] & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE |
+           (attrmask[1] & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE |
                       FATTR4_WORD1_SPACE_TOTAL))) {
                err = vfs_statfs(&path, &args.statfs);
                if (err)
                        goto out_nfserr;
        }
-       if ((u.attrmask[0] & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) &&
+       if ((attrmask[0] & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) &&
            !fhp) {
                tempfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL);
                status = nfserr_jukebox;
@@ -3577,10 +3574,10 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
                args.fhp = fhp;
 
        args.acl = NULL;
-       if (u.attrmask[0] & FATTR4_WORD0_ACL) {
+       if (attrmask[0] & FATTR4_WORD0_ACL) {
                err = nfsd4_get_nfs4_acl(rqstp, dentry, &args.acl);
                if (err == -EOPNOTSUPP)
-                       u.attrmask[0] &= ~FATTR4_WORD0_ACL;
+                       attrmask[0] &= ~FATTR4_WORD0_ACL;
                else if (err == -EINVAL) {
                        status = nfserr_attrnotsupp;
                        goto out;
@@ -3592,17 +3589,17 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 
 #ifdef CONFIG_NFSD_V4_SECURITY_LABEL
        args.context = NULL;
-       if ((u.attrmask[2] & FATTR4_WORD2_SECURITY_LABEL) ||
-            u.attrmask[0] & FATTR4_WORD0_SUPPORTED_ATTRS) {
+       if ((attrmask[2] & FATTR4_WORD2_SECURITY_LABEL) ||
+            attrmask[0] & FATTR4_WORD0_SUPPORTED_ATTRS) {
                if (exp->ex_flags & NFSEXP_SECURITY_LABEL)
                        err = security_inode_getsecctx(d_inode(dentry),
                                                &args.context, &args.contextlen);
                else
                        err = -EOPNOTSUPP;
                args.contextsupport = (err == 0);
-               if (u.attrmask[2] & FATTR4_WORD2_SECURITY_LABEL) {
+               if (attrmask[2] & FATTR4_WORD2_SECURITY_LABEL) {
                        if (err == -EOPNOTSUPP)
-                               u.attrmask[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
+                               attrmask[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
                        else if (err)
                                goto out_nfserr;
                }
@@ -3610,8 +3607,8 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 #endif /* CONFIG_NFSD_V4_SECURITY_LABEL */
 
        /* attrmask */
-       status = nfsd4_encode_bitmap4(xdr, u.attrmask[0],
-                                     u.attrmask[1], u.attrmask[2]);
+       status = nfsd4_encode_bitmap4(xdr, attrmask[0], attrmask[1],
+                                     attrmask[2]);
        if (status)
                goto out;
 
@@ -3620,7 +3617,9 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
        attrlen_p = xdr_reserve_space(xdr, XDR_UNIT);
        if (!attrlen_p)
                goto out_resource;
-       for_each_set_bit(bit, (const unsigned long *)&u.mask,
+       bitmap_from_arr32(attr_bitmap, attrmask,
+                         ARRAY_SIZE(nfsd4_enc_fattr4_encode_ops));
+       for_each_set_bit(bit, attr_bitmap,
                         ARRAY_SIZE(nfsd4_enc_fattr4_encode_ops)) {
                status = nfsd4_enc_fattr4_encode_ops[bit](xdr, &args);
                if (status != nfs_ok)
index bc846b904b68d43816c48c69c3ae83152cadabf1..aee40db7a036fb9f7d34e2e456fb6d61ae3bbf2d 100644 (file)
@@ -240,7 +240,7 @@ nilfs_filetype_table[NILFS_FT_MAX] = {
 
 #define S_SHIFT 12
 static unsigned char
-nilfs_type_by_mode[S_IFMT >> S_SHIFT] = {
+nilfs_type_by_mode[(S_IFMT >> S_SHIFT) + 1] = {
        [S_IFREG >> S_SHIFT]    = NILFS_FT_REG_FILE,
        [S_IFDIR >> S_SHIFT]    = NILFS_FT_DIR,
        [S_IFCHR >> S_SHIFT]    = NILFS_FT_CHRDEV,
index aa3411354e66d00c48db30adf73b34eedb84cb6d..16bd693d0b3aa23ce87af9cc1540e113a4c2a286 100644 (file)
@@ -48,6 +48,10 @@ static int squashfs_new_inode(struct super_block *sb, struct inode *inode,
        gid_t i_gid;
        int err;
 
+       inode->i_ino = le32_to_cpu(sqsh_ino->inode_number);
+       if (inode->i_ino == 0)
+               return -EINVAL;
+
        err = squashfs_get_id(sb, le16_to_cpu(sqsh_ino->uid), &i_uid);
        if (err)
                return err;
@@ -58,7 +62,6 @@ static int squashfs_new_inode(struct super_block *sb, struct inode *inode,
 
        i_uid_write(inode, i_uid);
        i_gid_write(inode, i_gid);
-       inode->i_ino = le32_to_cpu(sqsh_ino->inode_number);
        inode_set_mtime(inode, le32_to_cpu(sqsh_ino->mtime), 0);
        inode_set_atime(inode, inode_get_mtime_sec(inode), 0);
        inode_set_ctime(inode, inode_get_mtime_sec(inode), 0);
index e5ee2c694401e0972d4a644f01ca523f63f83475..3f4b4ac527ca28c66119cf00fc13083633ec80a3 100644 (file)
@@ -288,7 +288,12 @@ int __init xbc_init(const char *buf, size_t size, const char **emsg, int *epos);
 int __init xbc_get_info(int *node_size, size_t *data_size);
 
 /* XBC cleanup data structures */
-void __init xbc_exit(void);
+void __init _xbc_exit(bool early);
+
+static inline void xbc_exit(void)
+{
+       _xbc_exit(false);
+}
 
 /* XBC embedded bootconfig data in kernel */
 #ifdef CONFIG_BOOT_CONFIG_EMBED
index 00623f4de5e195d5a4b880db633b1bfd335f34fc..0fa56d672532157290264c8dfa0a79dab94657bb 100644 (file)
@@ -286,6 +286,11 @@ static inline int clk_rate_exclusive_get(struct clk *clk)
        return 0;
 }
 
+static inline int devm_clk_rate_exclusive_get(struct device *dev, struct clk *clk)
+{
+       return 0;
+}
+
 static inline void clk_rate_exclusive_put(struct clk *clk) {}
 
 #endif
index 6c75c8bd44a0bb627020ba267c3d0debb2379ba4..1a14e239221f7e9aec06b510d450c9f30b34fc2c 100644 (file)
@@ -2,7 +2,6 @@
 #ifndef __LINUX_GPIO_PROPERTY_H
 #define __LINUX_GPIO_PROPERTY_H
 
-#include <dt-bindings/gpio/gpio.h> /* for GPIO_* flags */
 #include <linux/property.h>
 
 #define PROPERTY_ENTRY_GPIO(_name_, _chip_node_, _idx_, _flags_) \
index a4c15db2f5e5401373e66a1b1f66ffd5e97ae35e..3fb18f7eb73eafecf8101a6e73a141cc4d46a0f9 100644 (file)
@@ -110,8 +110,17 @@ extern struct page *shmem_read_mapping_page_gfp(struct address_space *mapping,
 extern void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end);
 int shmem_unuse(unsigned int type);
 
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
 extern bool shmem_is_huge(struct inode *inode, pgoff_t index, bool shmem_huge_force,
                          struct mm_struct *mm, unsigned long vm_flags);
+#else
+static __always_inline bool shmem_is_huge(struct inode *inode, pgoff_t index, bool shmem_huge_force,
+                                         struct mm_struct *mm, unsigned long vm_flags)
+{
+       return false;
+}
+#endif
+
 #ifdef CONFIG_SHMEM
 extern unsigned long shmem_swap_usage(struct vm_area_struct *vma);
 #else
index 48b700ba1d188a798209d4de4693173bfc6b98af..a5c560a2f8c25867e8e3e53588d551ea3b356feb 100644 (file)
@@ -390,6 +390,35 @@ static inline bool is_migration_entry_dirty(swp_entry_t entry)
 }
 #endif /* CONFIG_MIGRATION */
 
+#ifdef CONFIG_MEMORY_FAILURE
+
+/*
+ * Support for hardware poisoned pages
+ */
+static inline swp_entry_t make_hwpoison_entry(struct page *page)
+{
+       BUG_ON(!PageLocked(page));
+       return swp_entry(SWP_HWPOISON, page_to_pfn(page));
+}
+
+static inline int is_hwpoison_entry(swp_entry_t entry)
+{
+       return swp_type(entry) == SWP_HWPOISON;
+}
+
+#else
+
+static inline swp_entry_t make_hwpoison_entry(struct page *page)
+{
+       return swp_entry(0, 0);
+}
+
+static inline int is_hwpoison_entry(swp_entry_t swp)
+{
+       return 0;
+}
+#endif
+
 typedef unsigned long pte_marker;
 
 #define  PTE_MARKER_UFFD_WP                    BIT(0)
@@ -483,8 +512,9 @@ static inline struct folio *pfn_swap_entry_folio(swp_entry_t entry)
 
 /*
  * A pfn swap entry is a special type of swap entry that always has a pfn stored
- * in the swap offset. They are used to represent unaddressable device memory
- * and to restrict access to a page undergoing migration.
+ * in the swap offset. They can either be used to represent unaddressable device
+ * memory, to restrict access to a page undergoing migration or to represent a
+ * pfn which has been hwpoisoned and unmapped.
  */
 static inline bool is_pfn_swap_entry(swp_entry_t entry)
 {
@@ -492,7 +522,7 @@ static inline bool is_pfn_swap_entry(swp_entry_t entry)
        BUILD_BUG_ON(SWP_TYPE_SHIFT < SWP_PFN_BITS);
 
        return is_migration_entry(entry) || is_device_private_entry(entry) ||
-              is_device_exclusive_entry(entry);
+              is_device_exclusive_entry(entry) || is_hwpoison_entry(entry);
 }
 
 struct page_vma_mapped_walk;
@@ -561,35 +591,6 @@ static inline int is_pmd_migration_entry(pmd_t pmd)
 }
 #endif  /* CONFIG_ARCH_ENABLE_THP_MIGRATION */
 
-#ifdef CONFIG_MEMORY_FAILURE
-
-/*
- * Support for hardware poisoned pages
- */
-static inline swp_entry_t make_hwpoison_entry(struct page *page)
-{
-       BUG_ON(!PageLocked(page));
-       return swp_entry(SWP_HWPOISON, page_to_pfn(page));
-}
-
-static inline int is_hwpoison_entry(swp_entry_t entry)
-{
-       return swp_type(entry) == SWP_HWPOISON;
-}
-
-#else
-
-static inline swp_entry_t make_hwpoison_entry(struct page *page)
-{
-       return swp_entry(0, 0);
-}
-
-static inline int is_hwpoison_entry(swp_entry_t swp)
-{
-       return 0;
-}
-#endif
-
 static inline int non_swap_entry(swp_entry_t entry)
 {
        return swp_type(entry) >= MAX_SWAPFILES;
index 17539d08966618bfe4c2f0b41f4893c8951b22fe..e398e1dbd2d365c54874a6f368adacf6734e9f03 100644 (file)
@@ -108,7 +108,7 @@ struct udp_sock {
 #define udp_assign_bit(nr, sk, val)            \
        assign_bit(UDP_FLAGS_##nr, &udp_sk(sk)->udp_flags, val)
 
-#define UDP_MAX_SEGMENTS       (1 << 6UL)
+#define UDP_MAX_SEGMENTS       (1 << 7UL)
 
 #define udp_sk(ptr) container_of_const(ptr, struct udp_sock, inet.sk)
 
index a763dd327c6ea95d6b94fda1ea2efd8f1784335f..9abb7ee40d72fc2e7d2ef0ec86ef18df939ddd9c 100644 (file)
@@ -336,7 +336,7 @@ int nf_flow_rule_route_ipv6(struct net *net, struct flow_offload *flow,
 int nf_flow_table_offload_init(void);
 void nf_flow_table_offload_exit(void);
 
-static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb)
+static inline __be16 __nf_flow_pppoe_proto(const struct sk_buff *skb)
 {
        __be16 proto;
 
@@ -352,6 +352,16 @@ static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb)
        return 0;
 }
 
+static inline bool nf_flow_pppoe_proto(struct sk_buff *skb, __be16 *inner_proto)
+{
+       if (!pskb_may_pull(skb, PPPOE_SES_HLEN))
+               return false;
+
+       *inner_proto = __nf_flow_pppoe_proto(skb);
+
+       return true;
+}
+
 #define NF_FLOW_TABLE_STAT_INC(net, count) __this_cpu_inc((net)->ft.stat->count)
 #define NF_FLOW_TABLE_STAT_DEC(net, count) __this_cpu_dec((net)->ft.stat->count)
 #define NF_FLOW_TABLE_STAT_INC_ATOMIC(net, count)      \
index e27c28b612e464ca41c9f07e213d48bf84f11bf6..3f1ed467f951f6342d9ee8da6b576cf8c787af2d 100644 (file)
@@ -307,9 +307,23 @@ static inline void *nft_elem_priv_cast(const struct nft_elem_priv *priv)
        return (void *)priv;
 }
 
+
+/**
+ * enum nft_iter_type - nftables set iterator type
+ *
+ * @NFT_ITER_READ: read-only iteration over set elements
+ * @NFT_ITER_UPDATE: iteration under mutex to update set element state
+ */
+enum nft_iter_type {
+       NFT_ITER_UNSPEC,
+       NFT_ITER_READ,
+       NFT_ITER_UPDATE,
+};
+
 struct nft_set;
 struct nft_set_iter {
        u8              genmask;
+       enum nft_iter_type type:8;
        unsigned int    count;
        unsigned int    skip;
        int             err;
index cefe0c4bdae34c91868c22731a3b666f8e16e996..41ca14e81d55f926dc4002e820d7e027f4729021 100644 (file)
@@ -117,6 +117,7 @@ struct Qdisc {
        struct qdisc_skb_head   q;
        struct gnet_stats_basic_sync bstats;
        struct gnet_stats_queue qstats;
+       int                     owner;
        unsigned long           state;
        unsigned long           state2; /* must be written under qdisc spinlock */
        struct Qdisc            *next_sched;
index ba2d96a1bc2f94703945c5f79294a66af1fe8fd4..f50fcafc69de20b8b20a53a45f29b23f4259a65e 100644 (file)
@@ -609,7 +609,7 @@ TRACE_EVENT(rpcgss_context,
                __field(unsigned int, timeout)
                __field(u32, window_size)
                __field(int, len)
-               __string(acceptor, data)
+               __string_len(acceptor, data, len)
        ),
 
        TP_fast_assign(
@@ -618,7 +618,7 @@ TRACE_EVENT(rpcgss_context,
                __entry->timeout = timeout;
                __entry->window_size = window_size;
                __entry->len = len;
-               strncpy(__get_str(acceptor), data, len);
+               __assign_str(acceptor, data);
        ),
 
        TP_printk("win_size=%u expiry=%lu now=%lu timeout=%u acceptor=%.*s",
index 881f6230ee59e9675eb98b62adf761ee74823a16..5dcf5274c09c7ae60232051569bd24651a8379af 100644 (file)
@@ -636,6 +636,8 @@ static void __init setup_command_line(char *command_line)
        if (!saved_command_line)
                panic("%s: Failed to allocate %zu bytes\n", __func__, len + ilen);
 
+       len = xlen + strlen(command_line) + 1;
+
        static_command_line = memblock_alloc(len, SMP_CACHE_BYTES);
        if (!static_command_line)
                panic("%s: Failed to allocate %zu bytes\n", __func__, len);
index 7a5bbfc024b7d0ee0c376f71474a0cca042c0824..4b4cfcba319013e8bc715e3cbfcd285088bf977c 100644 (file)
@@ -39,11 +39,12 @@ CONFIG_UBSAN=y
 CONFIG_UBSAN_TRAP=y
 CONFIG_UBSAN_BOUNDS=y
 # CONFIG_UBSAN_SHIFT is not set
-# CONFIG_UBSAN_DIV_ZERO
-# CONFIG_UBSAN_UNREACHABLE
-# CONFIG_UBSAN_BOOL
-# CONFIG_UBSAN_ENUM
-# CONFIG_UBSAN_ALIGNMENT
+# CONFIG_UBSAN_DIV_ZERO is not set
+# CONFIG_UBSAN_UNREACHABLE is not set
+# CONFIG_UBSAN_SIGNED_WRAP is not set
+# CONFIG_UBSAN_BOOL is not set
+# CONFIG_UBSAN_ENUM is not set
+# CONFIG_UBSAN_ALIGNMENT is not set
 
 # Sampling-based heap out-of-bounds and use-after-free detection.
 CONFIG_KFENCE=y
index 39a5046c2f0bf49e1bcade15c4c3c5574742b09d..aebb3e6c96dc62e5818ce16e31779868ea669067 100644 (file)
@@ -714,6 +714,23 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
                } else if (anon_vma_fork(tmp, mpnt))
                        goto fail_nomem_anon_vma_fork;
                vm_flags_clear(tmp, VM_LOCKED_MASK);
+               /*
+                * Copy/update hugetlb private vma information.
+                */
+               if (is_vm_hugetlb_page(tmp))
+                       hugetlb_dup_vma_private(tmp);
+
+               /*
+                * Link the vma into the MT. After using __mt_dup(), memory
+                * allocation is not necessary here, so it cannot fail.
+                */
+               vma_iter_bulk_store(&vmi, tmp);
+
+               mm->map_count++;
+
+               if (tmp->vm_ops && tmp->vm_ops->open)
+                       tmp->vm_ops->open(tmp);
+
                file = tmp->vm_file;
                if (file) {
                        struct address_space *mapping = file->f_mapping;
@@ -730,25 +747,9 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
                        i_mmap_unlock_write(mapping);
                }
 
-               /*
-                * Copy/update hugetlb private vma information.
-                */
-               if (is_vm_hugetlb_page(tmp))
-                       hugetlb_dup_vma_private(tmp);
-
-               /*
-                * Link the vma into the MT. After using __mt_dup(), memory
-                * allocation is not necessary here, so it cannot fail.
-                */
-               vma_iter_bulk_store(&vmi, tmp);
-
-               mm->map_count++;
                if (!(tmp->vm_flags & VM_WIPEONFORK))
                        retval = copy_page_range(tmp, mpnt);
 
-               if (tmp->vm_ops && tmp->vm_ops->open)
-                       tmp->vm_ops->open(tmp);
-
                if (retval) {
                        mpnt = vma_next(&vmi);
                        goto loop_out;
index c59d26068a6401990343e26c03002fcc4022ef98..97f8911ea339e69cc23228ef7d63b4381e883b34 100644 (file)
@@ -61,9 +61,12 @@ static inline void * __init xbc_alloc_mem(size_t size)
        return memblock_alloc(size, SMP_CACHE_BYTES);
 }
 
-static inline void __init xbc_free_mem(void *addr, size_t size)
+static inline void __init xbc_free_mem(void *addr, size_t size, bool early)
 {
-       memblock_free(addr, size);
+       if (early)
+               memblock_free(addr, size);
+       else if (addr)
+               memblock_free_late(__pa(addr), size);
 }
 
 #else /* !__KERNEL__ */
@@ -73,7 +76,7 @@ static inline void *xbc_alloc_mem(size_t size)
        return malloc(size);
 }
 
-static inline void xbc_free_mem(void *addr, size_t size)
+static inline void xbc_free_mem(void *addr, size_t size, bool early)
 {
        free(addr);
 }
@@ -898,19 +901,20 @@ static int __init xbc_parse_tree(void)
 }
 
 /**
- * xbc_exit() - Clean up all parsed bootconfig
+ * _xbc_exit() - Clean up all parsed bootconfig
+ * @early: Set true if this is called before budy system is initialized.
  *
  * This clears all data structures of parsed bootconfig on memory.
  * If you need to reuse xbc_init() with new boot config, you can
  * use this.
  */
-void __init xbc_exit(void)
+void __init _xbc_exit(bool early)
 {
-       xbc_free_mem(xbc_data, xbc_data_size);
+       xbc_free_mem(xbc_data, xbc_data_size, early);
        xbc_data = NULL;
        xbc_data_size = 0;
        xbc_node_num = 0;
-       xbc_free_mem(xbc_nodes, sizeof(struct xbc_node) * XBC_NODE_MAX);
+       xbc_free_mem(xbc_nodes, sizeof(struct xbc_node) * XBC_NODE_MAX, early);
        xbc_nodes = NULL;
        brace_index = 0;
 }
@@ -963,7 +967,7 @@ int __init xbc_init(const char *data, size_t size, const char **emsg, int *epos)
        if (!xbc_nodes) {
                if (emsg)
                        *emsg = "Failed to allocate bootconfig nodes";
-               xbc_exit();
+               _xbc_exit(true);
                return -ENOMEM;
        }
        memset(xbc_nodes, 0, sizeof(struct xbc_node) * XBC_NODE_MAX);
@@ -977,7 +981,7 @@ int __init xbc_init(const char *data, size_t size, const char **emsg, int *epos)
                        *epos = xbc_err_pos;
                if (emsg)
                        *emsg = xbc_err_msg;
-               xbc_exit();
+               _xbc_exit(true);
        } else
                ret = xbc_node_num;
 
index 5fc107f61934c28bd38b6997cd070ee8a25185b5..a1c983d148f16fe34493d6b933577556832bcdf6 100644 (file)
@@ -44,9 +44,10 @@ const char *report_ubsan_failure(struct pt_regs *regs, u32 check_type)
        case ubsan_shift_out_of_bounds:
                return "UBSAN: shift out of bounds";
 #endif
-#ifdef CONFIG_UBSAN_DIV_ZERO
+#if defined(CONFIG_UBSAN_DIV_ZERO) || defined(CONFIG_UBSAN_SIGNED_WRAP)
        /*
-        * SanitizerKind::IntegerDivideByZero emits
+        * SanitizerKind::IntegerDivideByZero and
+        * SanitizerKind::SignedIntegerOverflow emit
         * SanitizerHandler::DivremOverflow.
         */
        case ubsan_divrem_overflow:
@@ -77,6 +78,19 @@ const char *report_ubsan_failure(struct pt_regs *regs, u32 check_type)
                return "UBSAN: alignment assumption";
        case ubsan_type_mismatch:
                return "UBSAN: type mismatch";
+#endif
+#ifdef CONFIG_UBSAN_SIGNED_WRAP
+       /*
+        * SanitizerKind::SignedIntegerOverflow emits
+        * SanitizerHandler::AddOverflow, SanitizerHandler::SubOverflow,
+        * or SanitizerHandler::MulOverflow.
+        */
+       case ubsan_add_overflow:
+               return "UBSAN: integer addition overflow";
+       case ubsan_sub_overflow:
+               return "UBSAN: integer subtraction overflow";
+       case ubsan_mul_overflow:
+               return "UBSAN: integer multiplication overflow";
 #endif
        default:
                return "UBSAN: unrecognized failure code";
index af8edadc05d1b87200050bd34ff3d58ec52abd52..1611e73b1121b1b9031356ccac6b765c60327ba1 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -1206,6 +1206,22 @@ static long __get_user_pages(struct mm_struct *mm,
 
                /* first iteration or cross vma bound */
                if (!vma || start >= vma->vm_end) {
+                       /*
+                        * MADV_POPULATE_(READ|WRITE) wants to handle VMA
+                        * lookups+error reporting differently.
+                        */
+                       if (gup_flags & FOLL_MADV_POPULATE) {
+                               vma = vma_lookup(mm, start);
+                               if (!vma) {
+                                       ret = -ENOMEM;
+                                       goto out;
+                               }
+                               if (check_vma_flags(vma, gup_flags)) {
+                                       ret = -EINVAL;
+                                       goto out;
+                               }
+                               goto retry;
+                       }
                        vma = gup_vma_lookup(mm, start);
                        if (!vma && in_gate_area(mm, start)) {
                                ret = get_gate_page(mm, start & PAGE_MASK,
@@ -1685,35 +1701,35 @@ long populate_vma_page_range(struct vm_area_struct *vma,
 }
 
 /*
- * faultin_vma_page_range() - populate (prefault) page tables inside the
- *                           given VMA range readable/writable
+ * faultin_page_range() - populate (prefault) page tables inside the
+ *                       given range readable/writable
  *
  * This takes care of mlocking the pages, too, if VM_LOCKED is set.
  *
- * @vma: target vma
+ * @mm: the mm to populate page tables in
  * @start: start address
  * @end: end address
  * @write: whether to prefault readable or writable
  * @locked: whether the mmap_lock is still held
  *
- * Returns either number of processed pages in the vma, or a negative error
- * code on error (see __get_user_pages()).
+ * Returns either number of processed pages in the MM, or a negative error
+ * code on error (see __get_user_pages()). Note that this function reports
+ * errors related to VMAs, such as incompatible mappings, as expected by
+ * MADV_POPULATE_(READ|WRITE).
  *
- * vma->vm_mm->mmap_lock must be held. The range must be page-aligned and
- * covered by the VMA. If it's released, *@locked will be set to 0.
+ * The range must be page-aligned.
+ *
+ * mm->mmap_lock must be held. If it's released, *@locked will be set to 0.
  */
-long faultin_vma_page_range(struct vm_area_struct *vma, unsigned long start,
-                           unsigned long end, bool write, int *locked)
+long faultin_page_range(struct mm_struct *mm, unsigned long start,
+                       unsigned long end, bool write, int *locked)
 {
-       struct mm_struct *mm = vma->vm_mm;
        unsigned long nr_pages = (end - start) / PAGE_SIZE;
        int gup_flags;
        long ret;
 
        VM_BUG_ON(!PAGE_ALIGNED(start));
        VM_BUG_ON(!PAGE_ALIGNED(end));
-       VM_BUG_ON_VMA(start < vma->vm_start, vma);
-       VM_BUG_ON_VMA(end > vma->vm_end, vma);
        mmap_assert_locked(mm);
 
        /*
@@ -1725,19 +1741,13 @@ long faultin_vma_page_range(struct vm_area_struct *vma, unsigned long start,
         *                a poisoned page.
         * !FOLL_FORCE: Require proper access permissions.
         */
-       gup_flags = FOLL_TOUCH | FOLL_HWPOISON | FOLL_UNLOCKABLE;
+       gup_flags = FOLL_TOUCH | FOLL_HWPOISON | FOLL_UNLOCKABLE |
+                   FOLL_MADV_POPULATE;
        if (write)
                gup_flags |= FOLL_WRITE;
 
-       /*
-        * We want to report -EINVAL instead of -EFAULT for any permission
-        * problems or incompatible mappings.
-        */
-       if (check_vma_flags(vma, gup_flags))
-               return -EINVAL;
-
-       ret = __get_user_pages(mm, start, nr_pages, gup_flags,
-                              NULL, locked);
+       ret = __get_user_pages_locked(mm, start, nr_pages, NULL, locked,
+                                     gup_flags);
        lru_add_drain();
        return ret;
 }
index 9859aa4f755380a88013c70791e6e6df90ce861f..89f58c7603b255feb3dceaccfee603a503c40e49 100644 (file)
@@ -2259,9 +2259,6 @@ int move_pages_huge_pmd(struct mm_struct *mm, pmd_t *dst_pmd, pmd_t *src_pmd, pm
                        goto unlock_ptls;
                }
 
-               folio_move_anon_rmap(src_folio, dst_vma);
-               WRITE_ONCE(src_folio->index, linear_page_index(dst_vma, dst_addr));
-
                src_pmdval = pmdp_huge_clear_flush(src_vma, src_addr, src_pmd);
                /* Folio got pinned from under us. Put it back and fail the move. */
                if (folio_maybe_dma_pinned(src_folio)) {
@@ -2270,6 +2267,9 @@ int move_pages_huge_pmd(struct mm_struct *mm, pmd_t *dst_pmd, pmd_t *src_pmd, pm
                        goto unlock_ptls;
                }
 
+               folio_move_anon_rmap(src_folio, dst_vma);
+               WRITE_ONCE(src_folio->index, linear_page_index(dst_vma, dst_addr));
+
                _dst_pmd = mk_huge_pmd(&src_folio->page, dst_vma->vm_page_prot);
                /* Follow mremap() behavior and treat the entry dirty after the move */
                _dst_pmd = pmd_mkwrite(pmd_mkdirty(_dst_pmd), dst_vma);
index 23ef240ba48a60a77102f7bf1beb2e76a987486d..31d00eee028f1179b99405f0fdd3461b16e17d2e 100644 (file)
@@ -7044,9 +7044,13 @@ long hugetlb_change_protection(struct vm_area_struct *vma,
                        if (!pte_same(pte, newpte))
                                set_huge_pte_at(mm, address, ptep, newpte, psize);
                } else if (unlikely(is_pte_marker(pte))) {
-                       /* No other markers apply for now. */
-                       WARN_ON_ONCE(!pte_marker_uffd_wp(pte));
-                       if (uffd_wp_resolve)
+                       /*
+                        * Do nothing on a poison marker; page is
+                        * corrupted, permissons do not apply.  Here
+                        * pte_marker_uffd_wp()==true implies !poison
+                        * because they're mutual exclusive.
+                        */
+                       if (pte_marker_uffd_wp(pte) && uffd_wp_resolve)
                                /* Safe to modify directly (non-present->none). */
                                huge_pte_clear(mm, address, ptep, psize);
                } else if (!huge_pte_none(pte)) {
index 7e486f2c502cee245991e2468a0655228a81aef5..07ad2675a88b4798b140d3af3a303a20519cddc3 100644 (file)
@@ -686,9 +686,8 @@ struct anon_vma *folio_anon_vma(struct folio *folio);
 void unmap_mapping_folio(struct folio *folio);
 extern long populate_vma_page_range(struct vm_area_struct *vma,
                unsigned long start, unsigned long end, int *locked);
-extern long faultin_vma_page_range(struct vm_area_struct *vma,
-                                  unsigned long start, unsigned long end,
-                                  bool write, int *locked);
+extern long faultin_page_range(struct mm_struct *mm, unsigned long start,
+               unsigned long end, bool write, int *locked);
 extern bool mlock_future_ok(struct mm_struct *mm, unsigned long flags,
                               unsigned long bytes);
 
@@ -1127,10 +1126,13 @@ enum {
        FOLL_FAST_ONLY = 1 << 20,
        /* allow unlocking the mmap lock */
        FOLL_UNLOCKABLE = 1 << 21,
+       /* VMA lookup+checks compatible with MADV_POPULATE_(READ|WRITE) */
+       FOLL_MADV_POPULATE = 1 << 22,
 };
 
 #define INTERNAL_GUP_FLAGS (FOLL_TOUCH | FOLL_TRIED | FOLL_REMOTE | FOLL_PIN | \
-                           FOLL_FAST_ONLY | FOLL_UNLOCKABLE)
+                           FOLL_FAST_ONLY | FOLL_UNLOCKABLE | \
+                           FOLL_MADV_POPULATE)
 
 /*
  * Indicates for which pages that are write-protected in the page table,
index 44a498c94158c882c624eac2e29a5f07d854e322..1a073fcc4c0c021496667619a20f6ee1afaef7c0 100644 (file)
@@ -908,27 +908,14 @@ static long madvise_populate(struct vm_area_struct *vma,
 {
        const bool write = behavior == MADV_POPULATE_WRITE;
        struct mm_struct *mm = vma->vm_mm;
-       unsigned long tmp_end;
        int locked = 1;
        long pages;
 
        *prev = vma;
 
        while (start < end) {
-               /*
-                * We might have temporarily dropped the lock. For example,
-                * our VMA might have been split.
-                */
-               if (!vma || start >= vma->vm_end) {
-                       vma = vma_lookup(mm, start);
-                       if (!vma)
-                               return -ENOMEM;
-               }
-
-               tmp_end = min_t(unsigned long, end, vma->vm_end);
                /* Populate (prefault) page tables readable/writable. */
-               pages = faultin_vma_page_range(vma, start, tmp_end, write,
-                                              &locked);
+               pages = faultin_page_range(mm, start, end, write, &locked);
                if (!locked) {
                        mmap_read_lock(mm);
                        locked = 1;
@@ -949,7 +936,7 @@ static long madvise_populate(struct vm_area_struct *vma,
                                pr_warn_once("%s: unhandled return value: %ld\n",
                                             __func__, pages);
                                fallthrough;
-                       case -ENOMEM:
+                       case -ENOMEM: /* No VMA or out of memory. */
                                return -ENOMEM;
                        }
                }
index 9349948f1abfd120977706bbda23456999f057bc..9e62a00b46ddee5899f85cfc252dabd7c0d04121 100644 (file)
@@ -154,11 +154,23 @@ static int __page_handle_poison(struct page *page)
 {
        int ret;
 
-       zone_pcp_disable(page_zone(page));
+       /*
+        * zone_pcp_disable() can't be used here. It will
+        * hold pcp_batch_high_lock and dissolve_free_huge_page() might hold
+        * cpu_hotplug_lock via static_key_slow_dec() when hugetlb vmemmap
+        * optimization is enabled. This will break current lock dependency
+        * chain and leads to deadlock.
+        * Disabling pcp before dissolving the page was a deterministic
+        * approach because we made sure that those pages cannot end up in any
+        * PCP list. Draining PCP lists expels those pages to the buddy system,
+        * but nothing guarantees that those pages do not get back to a PCP
+        * queue if we need to refill those.
+        */
        ret = dissolve_free_huge_page(page);
-       if (!ret)
+       if (!ret) {
+               drain_all_pages(page_zone(page));
                ret = take_page_off_buddy(page);
-       zone_pcp_enable(page_zone(page));
+       }
 
        return ret;
 }
index d17d1351ec84af6ae4f49dc34d4c27c56bf77468..742f432e5bf06f560abdc675d658401f76df5237 100644 (file)
@@ -118,7 +118,6 @@ static __init void init_page_owner(void)
        register_dummy_stack();
        register_failure_stack();
        register_early_stack();
-       static_branch_enable(&page_owner_inited);
        init_early_allocated_pages();
        /* Initialize dummy and failure stacks and link them to stack_list */
        dummy_stack.stack_record = __stack_depot_get_stack_record(dummy_handle);
@@ -129,6 +128,7 @@ static __init void init_page_owner(void)
                refcount_set(&failure_stack.stack_record->count, 1);
        dummy_stack.next = &failure_stack;
        stack_list = &dummy_stack;
+       static_branch_enable(&page_owner_inited);
 }
 
 struct page_ext_operations page_owner_ops = {
@@ -196,7 +196,8 @@ static void add_stack_record_to_list(struct stack_record *stack_record,
        spin_unlock_irqrestore(&stack_list_lock, flags);
 }
 
-static void inc_stack_record_count(depot_stack_handle_t handle, gfp_t gfp_mask)
+static void inc_stack_record_count(depot_stack_handle_t handle, gfp_t gfp_mask,
+                                  int nr_base_pages)
 {
        struct stack_record *stack_record = __stack_depot_get_stack_record(handle);
 
@@ -217,20 +218,74 @@ static void inc_stack_record_count(depot_stack_handle_t handle, gfp_t gfp_mask)
                        /* Add the new stack_record to our list */
                        add_stack_record_to_list(stack_record, gfp_mask);
        }
-       refcount_inc(&stack_record->count);
+       refcount_add(nr_base_pages, &stack_record->count);
 }
 
-static void dec_stack_record_count(depot_stack_handle_t handle)
+static void dec_stack_record_count(depot_stack_handle_t handle,
+                                  int nr_base_pages)
 {
        struct stack_record *stack_record = __stack_depot_get_stack_record(handle);
 
-       if (stack_record)
-               refcount_dec(&stack_record->count);
+       if (!stack_record)
+               return;
+
+       if (refcount_sub_and_test(nr_base_pages, &stack_record->count))
+               pr_warn("%s: refcount went to 0 for %u handle\n", __func__,
+                       handle);
 }
 
-void __reset_page_owner(struct page *page, unsigned short order)
+static inline void __update_page_owner_handle(struct page_ext *page_ext,
+                                             depot_stack_handle_t handle,
+                                             unsigned short order,
+                                             gfp_t gfp_mask,
+                                             short last_migrate_reason, u64 ts_nsec,
+                                             pid_t pid, pid_t tgid, char *comm)
 {
        int i;
+       struct page_owner *page_owner;
+
+       for (i = 0; i < (1 << order); i++) {
+               page_owner = get_page_owner(page_ext);
+               page_owner->handle = handle;
+               page_owner->order = order;
+               page_owner->gfp_mask = gfp_mask;
+               page_owner->last_migrate_reason = last_migrate_reason;
+               page_owner->pid = pid;
+               page_owner->tgid = tgid;
+               page_owner->ts_nsec = ts_nsec;
+               strscpy(page_owner->comm, comm,
+                       sizeof(page_owner->comm));
+               __set_bit(PAGE_EXT_OWNER, &page_ext->flags);
+               __set_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags);
+               page_ext = page_ext_next(page_ext);
+       }
+}
+
+static inline void __update_page_owner_free_handle(struct page_ext *page_ext,
+                                                  depot_stack_handle_t handle,
+                                                  unsigned short order,
+                                                  pid_t pid, pid_t tgid,
+                                                  u64 free_ts_nsec)
+{
+       int i;
+       struct page_owner *page_owner;
+
+       for (i = 0; i < (1 << order); i++) {
+               page_owner = get_page_owner(page_ext);
+               /* Only __reset_page_owner() wants to clear the bit */
+               if (handle) {
+                       __clear_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags);
+                       page_owner->free_handle = handle;
+               }
+               page_owner->free_ts_nsec = free_ts_nsec;
+               page_owner->free_pid = current->pid;
+               page_owner->free_tgid = current->tgid;
+               page_ext = page_ext_next(page_ext);
+       }
+}
+
+void __reset_page_owner(struct page *page, unsigned short order)
+{
        struct page_ext *page_ext;
        depot_stack_handle_t handle;
        depot_stack_handle_t alloc_handle;
@@ -245,16 +300,10 @@ void __reset_page_owner(struct page *page, unsigned short order)
        alloc_handle = page_owner->handle;
 
        handle = save_stack(GFP_NOWAIT | __GFP_NOWARN);
-       for (i = 0; i < (1 << order); i++) {
-               __clear_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags);
-               page_owner->free_handle = handle;
-               page_owner->free_ts_nsec = free_ts_nsec;
-               page_owner->free_pid = current->pid;
-               page_owner->free_tgid = current->tgid;
-               page_ext = page_ext_next(page_ext);
-               page_owner = get_page_owner(page_ext);
-       }
+       __update_page_owner_free_handle(page_ext, handle, order, current->pid,
+                                       current->tgid, free_ts_nsec);
        page_ext_put(page_ext);
+
        if (alloc_handle != early_handle)
                /*
                 * early_handle is being set as a handle for all those
@@ -263,39 +312,14 @@ void __reset_page_owner(struct page *page, unsigned short order)
                 * the machinery is not ready yet, we cannot decrement
                 * their refcount either.
                 */
-               dec_stack_record_count(alloc_handle);
-}
-
-static inline void __set_page_owner_handle(struct page_ext *page_ext,
-                                       depot_stack_handle_t handle,
-                                       unsigned short order, gfp_t gfp_mask)
-{
-       struct page_owner *page_owner;
-       int i;
-       u64 ts_nsec = local_clock();
-
-       for (i = 0; i < (1 << order); i++) {
-               page_owner = get_page_owner(page_ext);
-               page_owner->handle = handle;
-               page_owner->order = order;
-               page_owner->gfp_mask = gfp_mask;
-               page_owner->last_migrate_reason = -1;
-               page_owner->pid = current->pid;
-               page_owner->tgid = current->tgid;
-               page_owner->ts_nsec = ts_nsec;
-               strscpy(page_owner->comm, current->comm,
-                       sizeof(page_owner->comm));
-               __set_bit(PAGE_EXT_OWNER, &page_ext->flags);
-               __set_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags);
-
-               page_ext = page_ext_next(page_ext);
-       }
+               dec_stack_record_count(alloc_handle, 1 << order);
 }
 
 noinline void __set_page_owner(struct page *page, unsigned short order,
                                        gfp_t gfp_mask)
 {
        struct page_ext *page_ext;
+       u64 ts_nsec = local_clock();
        depot_stack_handle_t handle;
 
        handle = save_stack(gfp_mask);
@@ -303,9 +327,11 @@ noinline void __set_page_owner(struct page *page, unsigned short order,
        page_ext = page_ext_get(page);
        if (unlikely(!page_ext))
                return;
-       __set_page_owner_handle(page_ext, handle, order, gfp_mask);
+       __update_page_owner_handle(page_ext, handle, order, gfp_mask, -1,
+                                  current->pid, current->tgid, ts_nsec,
+                                  current->comm);
        page_ext_put(page_ext);
-       inc_stack_record_count(handle, gfp_mask);
+       inc_stack_record_count(handle, gfp_mask, 1 << order);
 }
 
 void __set_page_owner_migrate_reason(struct page *page, int reason)
@@ -340,9 +366,12 @@ void __split_page_owner(struct page *page, int old_order, int new_order)
 
 void __folio_copy_owner(struct folio *newfolio, struct folio *old)
 {
+       int i;
        struct page_ext *old_ext;
        struct page_ext *new_ext;
-       struct page_owner *old_page_owner, *new_page_owner;
+       struct page_owner *old_page_owner;
+       struct page_owner *new_page_owner;
+       depot_stack_handle_t migrate_handle;
 
        old_ext = page_ext_get(&old->page);
        if (unlikely(!old_ext))
@@ -356,30 +385,32 @@ void __folio_copy_owner(struct folio *newfolio, struct folio *old)
 
        old_page_owner = get_page_owner(old_ext);
        new_page_owner = get_page_owner(new_ext);
-       new_page_owner->order = old_page_owner->order;
-       new_page_owner->gfp_mask = old_page_owner->gfp_mask;
-       new_page_owner->last_migrate_reason =
-               old_page_owner->last_migrate_reason;
-       new_page_owner->handle = old_page_owner->handle;
-       new_page_owner->pid = old_page_owner->pid;
-       new_page_owner->tgid = old_page_owner->tgid;
-       new_page_owner->free_pid = old_page_owner->free_pid;
-       new_page_owner->free_tgid = old_page_owner->free_tgid;
-       new_page_owner->ts_nsec = old_page_owner->ts_nsec;
-       new_page_owner->free_ts_nsec = old_page_owner->ts_nsec;
-       strcpy(new_page_owner->comm, old_page_owner->comm);
-
+       migrate_handle = new_page_owner->handle;
+       __update_page_owner_handle(new_ext, old_page_owner->handle,
+                                  old_page_owner->order, old_page_owner->gfp_mask,
+                                  old_page_owner->last_migrate_reason,
+                                  old_page_owner->ts_nsec, old_page_owner->pid,
+                                  old_page_owner->tgid, old_page_owner->comm);
+       /*
+        * Do not proactively clear PAGE_EXT_OWNER{_ALLOCATED} bits as the folio
+        * will be freed after migration. Keep them until then as they may be
+        * useful.
+        */
+       __update_page_owner_free_handle(new_ext, 0, old_page_owner->order,
+                                       old_page_owner->free_pid,
+                                       old_page_owner->free_tgid,
+                                       old_page_owner->free_ts_nsec);
        /*
-        * We don't clear the bit on the old folio as it's going to be freed
-        * after migration. Until then, the info can be useful in case of
-        * a bug, and the overall stats will be off a bit only temporarily.
-        * Also, migrate_misplaced_transhuge_page() can still fail the
-        * migration and then we want the old folio to retain the info. But
-        * in that case we also don't need to explicitly clear the info from
-        * the new page, which will be freed.
+        * We linked the original stack to the new folio, we need to do the same
+        * for the new one and the old folio otherwise there will be an imbalance
+        * when subtracting those pages from the stack.
         */
-       __set_bit(PAGE_EXT_OWNER, &new_ext->flags);
-       __set_bit(PAGE_EXT_OWNER_ALLOCATED, &new_ext->flags);
+       for (i = 0; i < (1 << new_page_owner->order); i++) {
+               old_page_owner->handle = migrate_handle;
+               old_ext = page_ext_next(old_ext);
+               old_page_owner = get_page_owner(old_ext);
+       }
+
        page_ext_put(new_ext);
        page_ext_put(old_ext);
 }
@@ -787,8 +818,9 @@ static void init_pages_in_zone(pg_data_t *pgdat, struct zone *zone)
                                goto ext_put_continue;
 
                        /* Found early allocated page */
-                       __set_page_owner_handle(page_ext, early_handle,
-                                               0, 0);
+                       __update_page_owner_handle(page_ext, early_handle, 0, 0,
+                                                  -1, local_clock(), current->pid,
+                                                  current->tgid, current->comm);
                        count++;
 ext_put_continue:
                        page_ext_put(page_ext);
@@ -840,13 +872,11 @@ static void *stack_start(struct seq_file *m, loff_t *ppos)
                 * value of stack_list.
                 */
                stack = smp_load_acquire(&stack_list);
+               m->private = stack;
        } else {
                stack = m->private;
-               stack = stack->next;
        }
 
-       m->private = stack;
-
        return stack;
 }
 
@@ -861,11 +891,11 @@ static void *stack_next(struct seq_file *m, void *v, loff_t *ppos)
        return stack;
 }
 
-static unsigned long page_owner_stack_threshold;
+static unsigned long page_owner_pages_threshold;
 
 static int stack_print(struct seq_file *m, void *v)
 {
-       int i, stack_count;
+       int i, nr_base_pages;
        struct stack *stack = v;
        unsigned long *entries;
        unsigned long nr_entries;
@@ -876,14 +906,14 @@ static int stack_print(struct seq_file *m, void *v)
 
        nr_entries = stack_record->size;
        entries = stack_record->entries;
-       stack_count = refcount_read(&stack_record->count) - 1;
+       nr_base_pages = refcount_read(&stack_record->count) - 1;
 
-       if (stack_count < 1 || stack_count < page_owner_stack_threshold)
+       if (nr_base_pages < 1 || nr_base_pages < page_owner_pages_threshold)
                return 0;
 
        for (i = 0; i < nr_entries; i++)
                seq_printf(m, " %pS\n", (void *)entries[i]);
-       seq_printf(m, "stack_count: %d\n\n", stack_count);
+       seq_printf(m, "nr_base_pages: %d\n\n", nr_base_pages);
 
        return 0;
 }
@@ -913,13 +943,13 @@ static const struct file_operations page_owner_stack_operations = {
 
 static int page_owner_threshold_get(void *data, u64 *val)
 {
-       *val = READ_ONCE(page_owner_stack_threshold);
+       *val = READ_ONCE(page_owner_pages_threshold);
        return 0;
 }
 
 static int page_owner_threshold_set(void *data, u64 val)
 {
-       WRITE_ONCE(page_owner_stack_threshold, val);
+       WRITE_ONCE(page_owner_pages_threshold, val);
        return 0;
 }
 
index 0aad0d9a621b80e7a3f758125806bfb64e984c12..94ab99b6b574a461e34bb875fdec497ad24728ce 100644 (file)
@@ -748,12 +748,6 @@ static long shmem_unused_huge_count(struct super_block *sb,
 
 #define shmem_huge SHMEM_HUGE_DENY
 
-bool shmem_is_huge(struct inode *inode, pgoff_t index, bool shmem_huge_force,
-                  struct mm_struct *mm, unsigned long vm_flags)
-{
-       return false;
-}
-
 static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo,
                struct shrink_control *sc, unsigned long nr_to_split)
 {
index f21097e734827891f87adb9d0a1f7cebf9f15380..ceaa5a89b947fc574ee2a05003db3de7cc9797b1 100644 (file)
@@ -30,7 +30,7 @@ br_netif_receive_skb(struct net *net, struct sock *sk, struct sk_buff *skb)
        return netif_receive_skb(skb);
 }
 
-static int br_pass_frame_up(struct sk_buff *skb)
+static int br_pass_frame_up(struct sk_buff *skb, bool promisc)
 {
        struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev;
        struct net_bridge *br = netdev_priv(brdev);
@@ -65,6 +65,8 @@ static int br_pass_frame_up(struct sk_buff *skb)
        br_multicast_count(br, NULL, skb, br_multicast_igmp_type(skb),
                           BR_MCAST_DIR_TX);
 
+       BR_INPUT_SKB_CB(skb)->promisc = promisc;
+
        return NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN,
                       dev_net(indev), NULL, skb, indev, NULL,
                       br_netif_receive_skb);
@@ -82,6 +84,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
        struct net_bridge_mcast *brmctx;
        struct net_bridge_vlan *vlan;
        struct net_bridge *br;
+       bool promisc;
        u16 vid = 0;
        u8 state;
 
@@ -137,7 +140,9 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
        if (p->flags & BR_LEARNING)
                br_fdb_update(br, p, eth_hdr(skb)->h_source, vid, 0);
 
-       local_rcv = !!(br->dev->flags & IFF_PROMISC);
+       promisc = !!(br->dev->flags & IFF_PROMISC);
+       local_rcv = promisc;
+
        if (is_multicast_ether_addr(eth_hdr(skb)->h_dest)) {
                /* by definition the broadcast is also a multicast address */
                if (is_broadcast_ether_addr(eth_hdr(skb)->h_dest)) {
@@ -200,7 +205,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
                unsigned long now = jiffies;
 
                if (test_bit(BR_FDB_LOCAL, &dst->flags))
-                       return br_pass_frame_up(skb);
+                       return br_pass_frame_up(skb, false);
 
                if (now != dst->used)
                        dst->used = now;
@@ -213,7 +218,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
        }
 
        if (local_rcv)
-               return br_pass_frame_up(skb);
+               return br_pass_frame_up(skb, promisc);
 
 out:
        return 0;
@@ -386,6 +391,8 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
                                goto forward;
                }
 
+               BR_INPUT_SKB_CB(skb)->promisc = false;
+
                /* The else clause should be hit when nf_hook():
                 *   - returns < 0 (drop/error)
                 *   - returns = 0 (stolen/nf_queue)
index 35e10c5a766d550e0c5cb85cf5a0c4835b52a89d..22e35623c148ac41056d7c24e3996227726ec1a6 100644 (file)
@@ -600,11 +600,17 @@ static unsigned int br_nf_local_in(void *priv,
                                   struct sk_buff *skb,
                                   const struct nf_hook_state *state)
 {
+       bool promisc = BR_INPUT_SKB_CB(skb)->promisc;
        struct nf_conntrack *nfct = skb_nfct(skb);
        const struct nf_ct_hook *ct_hook;
        struct nf_conn *ct;
        int ret;
 
+       if (promisc) {
+               nf_reset_ct(skb);
+               return NF_ACCEPT;
+       }
+
        if (!nfct || skb->pkt_type == PACKET_HOST)
                return NF_ACCEPT;
 
index 86ea5e6689b5ce49a4b71b383893d2ef5b53d110..d4bedc87b1d8f1bcf96c714fc80078227470550a 100644 (file)
@@ -589,6 +589,7 @@ struct br_input_skb_cb {
 #endif
        u8 proxyarp_replied:1;
        u8 src_port_isolated:1;
+       u8 promisc:1;
 #ifdef CONFIG_BRIDGE_VLAN_FILTERING
        u8 vlan_filtered:1;
 #endif
index 6f877e31709bad3646ea15bf3a96999ed275bdc1..c3c51b9a68265b443326432274e7fd75675e0e28 100644 (file)
@@ -294,18 +294,24 @@ static unsigned int nf_ct_bridge_pre(void *priv, struct sk_buff *skb,
 static unsigned int nf_ct_bridge_in(void *priv, struct sk_buff *skb,
                                    const struct nf_hook_state *state)
 {
-       enum ip_conntrack_info ctinfo;
+       bool promisc = BR_INPUT_SKB_CB(skb)->promisc;
+       struct nf_conntrack *nfct = skb_nfct(skb);
        struct nf_conn *ct;
 
-       if (skb->pkt_type == PACKET_HOST)
+       if (promisc) {
+               nf_reset_ct(skb);
+               return NF_ACCEPT;
+       }
+
+       if (!nfct || skb->pkt_type == PACKET_HOST)
                return NF_ACCEPT;
 
        /* nf_conntrack_confirm() cannot handle concurrent clones,
         * this happens for broad/multicast frames with e.g. macvlan on top
         * of the bridge device.
         */
-       ct = nf_ct_get(skb, &ctinfo);
-       if (!ct || nf_ct_is_confirmed(ct) || nf_ct_is_template(ct))
+       ct = container_of(nfct, struct nf_conn, ct_general);
+       if (nf_ct_is_confirmed(ct) || nf_ct_is_template(ct))
                return NF_ACCEPT;
 
        /* let inet prerouting call conntrack again */
index 984ff8b9d0e1aa5646a7237a8cf0b0a21c2aa559..331848eca7d3109d8043bba1f99e84d8e46d5507 100644 (file)
@@ -3775,6 +3775,10 @@ no_lock_out:
                return rc;
        }
 
+       if (unlikely(READ_ONCE(q->owner) == smp_processor_id())) {
+               kfree_skb_reason(skb, SKB_DROP_REASON_TC_RECLASSIFY_LOOP);
+               return NET_XMIT_DROP;
+       }
        /*
         * Heuristic to force contended enqueues to serialize on a
         * separate lock before trying to get qdisc main lock.
@@ -3814,7 +3818,9 @@ no_lock_out:
                qdisc_run_end(q);
                rc = NET_XMIT_SUCCESS;
        } else {
+               WRITE_ONCE(q->owner, smp_processor_id());
                rc = dev_qdisc_enqueue(skb, q, &to_free, txq);
+               WRITE_ONCE(q->owner, -1);
                if (qdisc_run_begin(q)) {
                        if (unlikely(contended)) {
                                spin_unlock(&q->busylock);
index 48741352a88a72e0232977cc9f2cf172f45df89b..c484b1c0fc00a79a45a1c3e7fde230ce59cb67a3 100644 (file)
@@ -1050,6 +1050,11 @@ next:
                        e++;
                }
        }
+
+       /* Don't let NLM_DONE coalesce into a message, even if it could.
+        * Some user space expects NLM_DONE in a separate recv().
+        */
+       err = skb->len;
 out:
 
        cb->args[1] = e;
index 9505f9d188ff257a8ca35f30ee111c2f19805a5a..6eef15648b7b0853fb249288bf4545dca3a2cf85 100644 (file)
@@ -21,7 +21,8 @@ nf_flow_offload_inet_hook(void *priv, struct sk_buff *skb,
                proto = veth->h_vlan_encapsulated_proto;
                break;
        case htons(ETH_P_PPP_SES):
-               proto = nf_flow_pppoe_proto(skb);
+               if (!nf_flow_pppoe_proto(skb, &proto))
+                       return NF_ACCEPT;
                break;
        default:
                proto = skb->protocol;
index e45fade764096182443814e8dcd70700e7956742..5383bed3d3e002661f01468e1a8bef8425e229b4 100644 (file)
@@ -157,7 +157,7 @@ static void nf_flow_tuple_encap(struct sk_buff *skb,
                tuple->encap[i].proto = skb->protocol;
                break;
        case htons(ETH_P_PPP_SES):
-               phdr = (struct pppoe_hdr *)skb_mac_header(skb);
+               phdr = (struct pppoe_hdr *)skb_network_header(skb);
                tuple->encap[i].id = ntohs(phdr->sid);
                tuple->encap[i].proto = skb->protocol;
                break;
@@ -273,10 +273,11 @@ static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb,
        return NF_STOLEN;
 }
 
-static bool nf_flow_skb_encap_protocol(const struct sk_buff *skb, __be16 proto,
+static bool nf_flow_skb_encap_protocol(struct sk_buff *skb, __be16 proto,
                                       u32 *offset)
 {
        struct vlan_ethhdr *veth;
+       __be16 inner_proto;
 
        switch (skb->protocol) {
        case htons(ETH_P_8021Q):
@@ -287,7 +288,8 @@ static bool nf_flow_skb_encap_protocol(const struct sk_buff *skb, __be16 proto,
                }
                break;
        case htons(ETH_P_PPP_SES):
-               if (nf_flow_pppoe_proto(skb) == proto) {
+               if (nf_flow_pppoe_proto(skb, &inner_proto) &&
+                   inner_proto == proto) {
                        *offset += PPPOE_SES_HLEN;
                        return true;
                }
@@ -316,7 +318,7 @@ static void nf_flow_encap_pop(struct sk_buff *skb,
                        skb_reset_network_header(skb);
                        break;
                case htons(ETH_P_PPP_SES):
-                       skb->protocol = nf_flow_pppoe_proto(skb);
+                       skb->protocol = __nf_flow_pppoe_proto(skb);
                        skb_pull(skb, PPPOE_SES_HLEN);
                        skb_reset_network_header(skb);
                        break;
index d89d779467197a0846406e0b0ce6938e8a3d404d..167074283ea91dff50a7aa0299a5794bcddeb32a 100644 (file)
@@ -594,6 +594,12 @@ static int nft_mapelem_deactivate(const struct nft_ctx *ctx,
                                  const struct nft_set_iter *iter,
                                  struct nft_elem_priv *elem_priv)
 {
+       struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
+
+       if (!nft_set_elem_active(ext, iter->genmask))
+               return 0;
+
+       nft_set_elem_change_active(ctx->net, set, ext);
        nft_setelem_data_deactivate(ctx->net, set, elem_priv);
 
        return 0;
@@ -617,6 +623,7 @@ static void nft_map_catchall_deactivate(const struct nft_ctx *ctx,
                if (!nft_set_elem_active(ext, genmask))
                        continue;
 
+               nft_set_elem_change_active(ctx->net, set, ext);
                nft_setelem_data_deactivate(ctx->net, set, catchall->elem);
                break;
        }
@@ -626,6 +633,7 @@ static void nft_map_deactivate(const struct nft_ctx *ctx, struct nft_set *set)
 {
        struct nft_set_iter iter = {
                .genmask        = nft_genmask_next(ctx->net),
+               .type           = NFT_ITER_UPDATE,
                .fn             = nft_mapelem_deactivate,
        };
 
@@ -3060,7 +3068,7 @@ static const struct nft_expr_type *__nft_expr_type_get(u8 family,
 {
        const struct nft_expr_type *type, *candidate = NULL;
 
-       list_for_each_entry(type, &nf_tables_expressions, list) {
+       list_for_each_entry_rcu(type, &nf_tables_expressions, list) {
                if (!nla_strcmp(nla, type->name)) {
                        if (!type->family && !candidate)
                                candidate = type;
@@ -3092,9 +3100,13 @@ static const struct nft_expr_type *nft_expr_type_get(struct net *net,
        if (nla == NULL)
                return ERR_PTR(-EINVAL);
 
+       rcu_read_lock();
        type = __nft_expr_type_get(family, nla);
-       if (type != NULL && try_module_get(type->owner))
+       if (type != NULL && try_module_get(type->owner)) {
+               rcu_read_unlock();
                return type;
+       }
+       rcu_read_unlock();
 
        lockdep_nfnl_nft_mutex_not_held();
 #ifdef CONFIG_MODULES
@@ -3875,6 +3887,9 @@ int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
        const struct nft_data *data;
        int err;
 
+       if (!nft_set_elem_active(ext, iter->genmask))
+               return 0;
+
        if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) &&
            *nft_set_ext_flags(ext) & NFT_SET_ELEM_INTERVAL_END)
                return 0;
@@ -3898,17 +3913,20 @@ int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
 
 int nft_set_catchall_validate(const struct nft_ctx *ctx, struct nft_set *set)
 {
-       u8 genmask = nft_genmask_next(ctx->net);
+       struct nft_set_iter dummy_iter = {
+               .genmask        = nft_genmask_next(ctx->net),
+       };
        struct nft_set_elem_catchall *catchall;
+
        struct nft_set_ext *ext;
        int ret = 0;
 
        list_for_each_entry_rcu(catchall, &set->catchall_list, list) {
                ext = nft_set_elem_ext(set, catchall->elem);
-               if (!nft_set_elem_active(ext, genmask))
+               if (!nft_set_elem_active(ext, dummy_iter.genmask))
                        continue;
 
-               ret = nft_setelem_validate(ctx, set, NULL, catchall->elem);
+               ret = nft_setelem_validate(ctx, set, &dummy_iter, catchall->elem);
                if (ret < 0)
                        return ret;
        }
@@ -5397,6 +5415,11 @@ static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx,
                                        const struct nft_set_iter *iter,
                                        struct nft_elem_priv *elem_priv)
 {
+       const struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
+
+       if (!nft_set_elem_active(ext, iter->genmask))
+               return 0;
+
        return nft_setelem_data_validate(ctx, set, elem_priv);
 }
 
@@ -5441,6 +5464,7 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
                }
 
                iter.genmask    = nft_genmask_next(ctx->net);
+               iter.type       = NFT_ITER_UPDATE;
                iter.skip       = 0;
                iter.count      = 0;
                iter.err        = 0;
@@ -5488,6 +5512,13 @@ static int nft_mapelem_activate(const struct nft_ctx *ctx,
                                const struct nft_set_iter *iter,
                                struct nft_elem_priv *elem_priv)
 {
+       struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
+
+       /* called from abort path, reverse check to undo changes. */
+       if (nft_set_elem_active(ext, iter->genmask))
+               return 0;
+
+       nft_clear(ctx->net, ext);
        nft_setelem_data_activate(ctx->net, set, elem_priv);
 
        return 0;
@@ -5505,6 +5536,7 @@ static void nft_map_catchall_activate(const struct nft_ctx *ctx,
                if (!nft_set_elem_active(ext, genmask))
                        continue;
 
+               nft_clear(ctx->net, ext);
                nft_setelem_data_activate(ctx->net, set, catchall->elem);
                break;
        }
@@ -5514,6 +5546,7 @@ static void nft_map_activate(const struct nft_ctx *ctx, struct nft_set *set)
 {
        struct nft_set_iter iter = {
                .genmask        = nft_genmask_next(ctx->net),
+               .type           = NFT_ITER_UPDATE,
                .fn             = nft_mapelem_activate,
        };
 
@@ -5778,6 +5811,9 @@ static int nf_tables_dump_setelem(const struct nft_ctx *ctx,
        const struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
        struct nft_set_dump_args *args;
 
+       if (!nft_set_elem_active(ext, iter->genmask))
+               return 0;
+
        if (nft_set_elem_expired(ext) || nft_set_elem_is_dead(ext))
                return 0;
 
@@ -5888,6 +5924,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
        args.skb                = skb;
        args.reset              = dump_ctx->reset;
        args.iter.genmask       = nft_genmask_cur(net);
+       args.iter.type          = NFT_ITER_READ;
        args.iter.skip          = cb->args[0];
        args.iter.count         = 0;
        args.iter.err           = 0;
@@ -6627,7 +6664,7 @@ static void nft_setelem_activate(struct net *net, struct nft_set *set,
        struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
 
        if (nft_setelem_is_catchall(set, elem_priv)) {
-               nft_set_elem_change_active(net, set, ext);
+               nft_clear(net, ext);
        } else {
                set->ops->activate(net, set, elem_priv);
        }
@@ -7186,6 +7223,16 @@ void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
        }
 }
 
+static int nft_setelem_active_next(const struct net *net,
+                                  const struct nft_set *set,
+                                  struct nft_elem_priv *elem_priv)
+{
+       const struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
+       u8 genmask = nft_genmask_next(net);
+
+       return nft_set_elem_active(ext, genmask);
+}
+
 static void nft_setelem_data_activate(const struct net *net,
                                      const struct nft_set *set,
                                      struct nft_elem_priv *elem_priv)
@@ -7309,8 +7356,12 @@ static int nft_setelem_flush(const struct nft_ctx *ctx,
                             const struct nft_set_iter *iter,
                             struct nft_elem_priv *elem_priv)
 {
+       const struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
        struct nft_trans *trans;
 
+       if (!nft_set_elem_active(ext, iter->genmask))
+               return 0;
+
        trans = nft_trans_alloc_gfp(ctx, NFT_MSG_DELSETELEM,
                                    sizeof(struct nft_trans_elem), GFP_ATOMIC);
        if (!trans)
@@ -7372,6 +7423,7 @@ static int nft_set_flush(struct nft_ctx *ctx, struct nft_set *set, u8 genmask)
 {
        struct nft_set_iter iter = {
                .genmask        = genmask,
+               .type           = NFT_ITER_UPDATE,
                .fn             = nft_setelem_flush,
        };
 
@@ -7607,7 +7659,7 @@ static const struct nft_object_type *__nft_obj_type_get(u32 objtype, u8 family)
 {
        const struct nft_object_type *type;
 
-       list_for_each_entry(type, &nf_tables_objects, list) {
+       list_for_each_entry_rcu(type, &nf_tables_objects, list) {
                if (type->family != NFPROTO_UNSPEC &&
                    type->family != family)
                        continue;
@@ -7623,9 +7675,13 @@ nft_obj_type_get(struct net *net, u32 objtype, u8 family)
 {
        const struct nft_object_type *type;
 
+       rcu_read_lock();
        type = __nft_obj_type_get(objtype, family);
-       if (type != NULL && try_module_get(type->owner))
+       if (type != NULL && try_module_get(type->owner)) {
+               rcu_read_unlock();
                return type;
+       }
+       rcu_read_unlock();
 
        lockdep_nfnl_nft_mutex_not_held();
 #ifdef CONFIG_MODULES
@@ -10598,8 +10654,10 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
                case NFT_MSG_DESTROYSETELEM:
                        te = (struct nft_trans_elem *)trans->data;
 
-                       nft_setelem_data_activate(net, te->set, te->elem_priv);
-                       nft_setelem_activate(net, te->set, te->elem_priv);
+                       if (!nft_setelem_active_next(net, te->set, te->elem_priv)) {
+                               nft_setelem_data_activate(net, te->set, te->elem_priv);
+                               nft_setelem_activate(net, te->set, te->elem_priv);
+                       }
                        if (!nft_setelem_is_catchall(te->set, te->elem_priv))
                                te->set->ndeact--;
 
@@ -10787,6 +10845,9 @@ static int nf_tables_loop_check_setelem(const struct nft_ctx *ctx,
 {
        const struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
 
+       if (!nft_set_elem_active(ext, iter->genmask))
+               return 0;
+
        if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) &&
            *nft_set_ext_flags(ext) & NFT_SET_ELEM_INTERVAL_END)
                return 0;
@@ -10871,6 +10932,7 @@ static int nf_tables_check_loops(const struct nft_ctx *ctx,
                                continue;
 
                        iter.genmask    = nft_genmask_next(ctx->net);
+                       iter.type       = NFT_ITER_UPDATE;
                        iter.skip       = 0;
                        iter.count      = 0;
                        iter.err        = 0;
index a0055f510e31e9b77526a11c66c565b973897706..b314ca728a2912da717995840ef3dc337eace815 100644 (file)
@@ -216,6 +216,7 @@ static int nft_lookup_validate(const struct nft_ctx *ctx,
                return 0;
 
        iter.genmask    = nft_genmask_next(ctx->net);
+       iter.type       = NFT_ITER_UPDATE;
        iter.skip       = 0;
        iter.count      = 0;
        iter.err        = 0;
index 32df7a16835da3e1d850d34a8236e0a45f06f026..1caa04619dc6da37f845acc65c8ca86c173096de 100644 (file)
@@ -172,7 +172,7 @@ static void nft_bitmap_activate(const struct net *net,
        nft_bitmap_location(set, nft_set_ext_key(&be->ext), &idx, &off);
        /* Enter 11 state. */
        priv->bitmap[idx] |= (genmask << off);
-       nft_set_elem_change_active(net, set, &be->ext);
+       nft_clear(net, &be->ext);
 }
 
 static void nft_bitmap_flush(const struct net *net,
@@ -222,8 +222,6 @@ static void nft_bitmap_walk(const struct nft_ctx *ctx,
        list_for_each_entry_rcu(be, &priv->list, head) {
                if (iter->count < iter->skip)
                        goto cont;
-               if (!nft_set_elem_active(&be->ext, iter->genmask))
-                       goto cont;
 
                iter->err = iter->fn(ctx, set, iter, &be->priv);
 
index 6968a3b342367c6c0cb0df7523fdfd5864038802..daa56dda737ae2e6b4727c2d3930d68e58a33efb 100644 (file)
@@ -199,7 +199,7 @@ static void nft_rhash_activate(const struct net *net, const struct nft_set *set,
 {
        struct nft_rhash_elem *he = nft_elem_priv_cast(elem_priv);
 
-       nft_set_elem_change_active(net, set, &he->ext);
+       nft_clear(net, &he->ext);
 }
 
 static void nft_rhash_flush(const struct net *net,
@@ -286,8 +286,6 @@ static void nft_rhash_walk(const struct nft_ctx *ctx, struct nft_set *set,
 
                if (iter->count < iter->skip)
                        goto cont;
-               if (!nft_set_elem_active(&he->ext, iter->genmask))
-                       goto cont;
 
                iter->err = iter->fn(ctx, set, iter, &he->priv);
                if (iter->err < 0)
@@ -599,7 +597,7 @@ static void nft_hash_activate(const struct net *net, const struct nft_set *set,
 {
        struct nft_hash_elem *he = nft_elem_priv_cast(elem_priv);
 
-       nft_set_elem_change_active(net, set, &he->ext);
+       nft_clear(net, &he->ext);
 }
 
 static void nft_hash_flush(const struct net *net,
@@ -652,8 +650,6 @@ static void nft_hash_walk(const struct nft_ctx *ctx, struct nft_set *set,
                hlist_for_each_entry_rcu(he, &priv->table[i], node) {
                        if (iter->count < iter->skip)
                                goto cont;
-                       if (!nft_set_elem_active(&he->ext, iter->genmask))
-                               goto cont;
 
                        iter->err = iter->fn(ctx, set, iter, &he->priv);
                        if (iter->err < 0)
index df8de50902463738642d4d24b59f12b17b5ff726..187138afac45d479f89ea23ec9b09fcd6b6da866 100644 (file)
@@ -1847,7 +1847,7 @@ static void nft_pipapo_activate(const struct net *net,
 {
        struct nft_pipapo_elem *e = nft_elem_priv_cast(elem_priv);
 
-       nft_set_elem_change_active(net, set, &e->ext);
+       nft_clear(net, &e->ext);
 }
 
 /**
@@ -2077,6 +2077,8 @@ static void nft_pipapo_remove(const struct net *net, const struct nft_set *set,
                rules_fx = rules_f0;
 
                nft_pipapo_for_each_field(f, i, m) {
+                       bool last = i == m->field_count - 1;
+
                        if (!pipapo_match_field(f, start, rules_fx,
                                                match_start, match_end))
                                break;
@@ -2089,16 +2091,18 @@ static void nft_pipapo_remove(const struct net *net, const struct nft_set *set,
 
                        match_start += NFT_PIPAPO_GROUPS_PADDED_SIZE(f);
                        match_end += NFT_PIPAPO_GROUPS_PADDED_SIZE(f);
-               }
 
-               if (i == m->field_count) {
-                       priv->dirty = true;
-                       pipapo_drop(m, rulemap);
-                       return;
+                       if (last && f->mt[rulemap[i].to].e == e) {
+                               priv->dirty = true;
+                               pipapo_drop(m, rulemap);
+                               return;
+                       }
                }
 
                first_rule += rules_f0;
        }
+
+       WARN_ON_ONCE(1); /* elem_priv not found */
 }
 
 /**
@@ -2115,13 +2119,15 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set,
                            struct nft_set_iter *iter)
 {
        struct nft_pipapo *priv = nft_set_priv(set);
-       struct net *net = read_pnet(&set->net);
        const struct nft_pipapo_match *m;
        const struct nft_pipapo_field *f;
        unsigned int i, r;
 
+       WARN_ON_ONCE(iter->type != NFT_ITER_READ &&
+                    iter->type != NFT_ITER_UPDATE);
+
        rcu_read_lock();
-       if (iter->genmask == nft_genmask_cur(net))
+       if (iter->type == NFT_ITER_READ)
                m = rcu_dereference(priv->match);
        else
                m = priv->clone;
@@ -2143,9 +2149,6 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set,
 
                e = f->mt[r].e;
 
-               if (!nft_set_elem_active(&e->ext, iter->genmask))
-                       goto cont;
-
                iter->err = iter->fn(ctx, set, iter, &e->priv);
                if (iter->err < 0)
                        goto out;
index 9944fe479e5361dc140f75be8b90bf3c5deb40f6..b7ea21327549b353c087b3e607e722f391ea94c1 100644 (file)
@@ -532,7 +532,7 @@ static void nft_rbtree_activate(const struct net *net,
 {
        struct nft_rbtree_elem *rbe = nft_elem_priv_cast(elem_priv);
 
-       nft_set_elem_change_active(net, set, &rbe->ext);
+       nft_clear(net, &rbe->ext);
 }
 
 static void nft_rbtree_flush(const struct net *net,
@@ -600,8 +600,6 @@ static void nft_rbtree_walk(const struct nft_ctx *ctx,
 
                if (iter->count < iter->skip)
                        goto cont;
-               if (!nft_set_elem_active(&rbe->ext, iter->genmask))
-                       goto cont;
 
                iter->err = iter->fn(ctx, set, iter, &rbe->priv);
                if (iter->err < 0) {
index ff5336493777507242320d7e9214c637663f0734..4a2c763e2d116693469e6c8bd9ce0ed8f7f667d9 100644 (file)
@@ -974,6 +974,7 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
        sch->enqueue = ops->enqueue;
        sch->dequeue = ops->dequeue;
        sch->dev_queue = dev_queue;
+       sch->owner = -1;
        netdev_hold(dev, &sch->dev_tracker, GFP_KERNEL);
        refcount_set(&sch->refcnt, 1);
 
index d032eb5fa6df1eb7422fdf8a54de40bd4f0683ac..9a6ad5974dff5e855cbc0ba2a1f7837733420c5f 100644 (file)
@@ -2663,7 +2663,9 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk,
                                        WRITE_ONCE(u->oob_skb, NULL);
                                        consume_skb(skb);
                                }
-                       } else if (!(flags & MSG_PEEK)) {
+                       } else if (flags & MSG_PEEK) {
+                               skb = NULL;
+                       } else {
                                skb_unlink(skb, &sk->sk_receive_queue);
                                WRITE_ONCE(u->oob_skb, NULL);
                                if (!WARN_ON_ONCE(skb_unref(skb)))
@@ -2741,18 +2743,16 @@ redo:
                last = skb = skb_peek(&sk->sk_receive_queue);
                last_len = last ? last->len : 0;
 
+again:
 #if IS_ENABLED(CONFIG_AF_UNIX_OOB)
                if (skb) {
                        skb = manage_oob(skb, sk, flags, copied);
-                       if (!skb) {
+                       if (!skb && copied) {
                                unix_state_unlock(sk);
-                               if (copied)
-                                       break;
-                               goto redo;
+                               break;
                        }
                }
 #endif
-again:
                if (skb == NULL) {
                        if (copied >= target)
                                goto unlock;
index b141024830ecc831430c697858ce409a56c711af..ee6ac649df836d695133f93da9cfd0518cc1ae23 100644 (file)
@@ -428,7 +428,7 @@ static int cvt_ump_midi2_to_midi1(struct snd_seq_client *dest,
        midi1->note.group = midi2->note.group;
        midi1->note.status = midi2->note.status;
        midi1->note.channel = midi2->note.channel;
-       switch (midi2->note.status << 4) {
+       switch (midi2->note.status) {
        case UMP_MSG_STATUS_NOTE_ON:
        case UMP_MSG_STATUS_NOTE_OFF:
                midi1->note.note = midi2->note.note;
index cdcb28aa9d7bf028d429aeea0016cec7c6bc0c22..70d80b6af3fe370aa9c6f9fd471676ba9c18da72 100644 (file)
@@ -7467,6 +7467,10 @@ enum {
        ALC285_FIXUP_CS35L56_I2C_2,
        ALC285_FIXUP_CS35L56_I2C_4,
        ALC285_FIXUP_ASUS_GA403U,
+       ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC,
+       ALC285_FIXUP_ASUS_GA403U_I2C_SPEAKER2_TO_DAC1,
+       ALC285_FIXUP_ASUS_GU605_SPI_2_HEADSET_MIC,
+       ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1
 };
 
 /* A special fixup for Lenovo C940 and Yoga Duet 7;
@@ -9690,6 +9694,38 @@ static const struct hda_fixup alc269_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc285_fixup_asus_ga403u,
        },
+       [ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x19, 0x03a11050 },
+                       { 0x1b, 0x03a11c30 },
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC285_FIXUP_ASUS_GA403U_I2C_SPEAKER2_TO_DAC1
+       },
+       [ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc285_fixup_speaker2_to_dac1,
+               .chained = true,
+               .chain_id = ALC285_FIXUP_ASUS_GU605_SPI_2_HEADSET_MIC,
+       },
+       [ALC285_FIXUP_ASUS_GU605_SPI_2_HEADSET_MIC] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x19, 0x03a11050 },
+                       { 0x1b, 0x03a11c30 },
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC285_FIXUP_CS35L56_SPI_2
+       },
+       [ALC285_FIXUP_ASUS_GA403U_I2C_SPEAKER2_TO_DAC1] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc285_fixup_speaker2_to_dac1,
+               .chained = true,
+               .chain_id = ALC285_FIXUP_ASUS_GA403U,
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -10084,6 +10120,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x8ca7, "HP ZBook Fury", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8cdd, "HP Spectre", ALC287_FIXUP_CS35L41_I2C_2),
        SND_PCI_QUIRK(0x103c, 0x8cde, "HP Spectre", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x103c, 0x8cdf, "HP SnowWhite", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8ce0, "HP SnowWhite", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8cf5, "HP ZBook Studio 16", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED),
        SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
        SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
@@ -10143,7 +10181,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1a83, "ASUS UM5302LA", ALC294_FIXUP_CS35L41_I2C_2),
        SND_PCI_QUIRK(0x1043, 0x1a8f, "ASUS UX582ZS", ALC245_FIXUP_CS35L41_SPI_2),
        SND_PCI_QUIRK(0x1043, 0x1b11, "ASUS UX431DA", ALC294_FIXUP_ASUS_COEF_1B),
-       SND_PCI_QUIRK(0x1043, 0x1b13, "ASUS U41SV/GA403U", ALC285_FIXUP_ASUS_GA403U),
+       SND_PCI_QUIRK(0x1043, 0x1b13, "ASUS U41SV/GA403U", ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC),
        SND_PCI_QUIRK(0x1043, 0x1b93, "ASUS G614JVR/JIR", ALC245_FIXUP_CS35L41_SPI_2),
        SND_PCI_QUIRK(0x1043, 0x1bbd, "ASUS Z550MA", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1043, 0x1c03, "ASUS UM3406HA", ALC287_FIXUP_CS35L41_I2C_2),
@@ -10151,7 +10189,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1c33, "ASUS UX5304MA", ALC245_FIXUP_CS35L41_SPI_2),
        SND_PCI_QUIRK(0x1043, 0x1c43, "ASUS UX8406MA", ALC245_FIXUP_CS35L41_SPI_2),
        SND_PCI_QUIRK(0x1043, 0x1c62, "ASUS GU603", ALC289_FIXUP_ASUS_GA401),
-       SND_PCI_QUIRK(0x1043, 0x1c63, "ASUS GU605M", ALC285_FIXUP_CS35L56_SPI_2),
+       SND_PCI_QUIRK(0x1043, 0x1c63, "ASUS GU605M", ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1),
        SND_PCI_QUIRK(0x1043, 0x1c92, "ASUS ROG Strix G15", ALC285_FIXUP_ASUS_G533Z_PINS),
        SND_PCI_QUIRK(0x1043, 0x1c9f, "ASUS G614JU/JV/JI", ALC285_FIXUP_ASUS_HEADSET_MIC),
        SND_PCI_QUIRK(0x1043, 0x1caf, "ASUS G634JY/JZ/JI/JG", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
@@ -10228,6 +10266,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x152d, 0x1082, "Quanta NL3", ALC269_FIXUP_LIFEBOOK),
+       SND_PCI_QUIRK(0x152d, 0x1262, "Huawei NBLB-WAX9N", ALC2XX_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x1558, 0x0353, "Clevo V35[05]SN[CDE]Q", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x1323, "Clevo N130ZU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x1325, "Clevo N15[01][CW]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
@@ -10333,6 +10372,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x222e, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2231, "Thinkpad T560", ALC292_FIXUP_TPT460),
        SND_PCI_QUIRK(0x17aa, 0x2233, "Thinkpad", ALC292_FIXUP_TPT460),
+       SND_PCI_QUIRK(0x17aa, 0x2234, "Thinkpad ICE-1", ALC287_FIXUP_TAS2781_I2C),
        SND_PCI_QUIRK(0x17aa, 0x2245, "Thinkpad T470", ALC298_FIXUP_TPT470_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2246, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2247, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
@@ -10394,8 +10434,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x3886, "Y780 VECO DUAL", ALC287_FIXUP_TAS2781_I2C),
        SND_PCI_QUIRK(0x17aa, 0x38a7, "Y780P AMD YG dual", ALC287_FIXUP_TAS2781_I2C),
        SND_PCI_QUIRK(0x17aa, 0x38a8, "Y780P AMD VECO dual", ALC287_FIXUP_TAS2781_I2C),
-       SND_PCI_QUIRK(0x17aa, 0x38a9, "Thinkbook 16P", ALC287_FIXUP_CS35L41_I2C_2),
-       SND_PCI_QUIRK(0x17aa, 0x38ab, "Thinkbook 16P", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x17aa, 0x38a9, "Thinkbook 16P", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
+       SND_PCI_QUIRK(0x17aa, 0x38ab, "Thinkbook 16P", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
        SND_PCI_QUIRK(0x17aa, 0x38b4, "Legion Slim 7 16IRH8", ALC287_FIXUP_CS35L41_I2C_2),
        SND_PCI_QUIRK(0x17aa, 0x38b5, "Legion Slim 7 16IRH8", ALC287_FIXUP_CS35L41_I2C_2),
        SND_PCI_QUIRK(0x17aa, 0x38b6, "Legion Slim 7 16APH8", ALC287_FIXUP_CS35L41_I2C_2),
@@ -10457,6 +10497,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1d05, 0x115c, "TongFang GMxTGxx", ALC269_FIXUP_NO_SHUTUP),
        SND_PCI_QUIRK(0x1d05, 0x121b, "TongFang GMxAGxx", ALC269_FIXUP_NO_SHUTUP),
        SND_PCI_QUIRK(0x1d05, 0x1387, "TongFang GMxIXxx", ALC2XX_FIXUP_HEADSET_MIC),
+       SND_PCI_QUIRK(0x1d17, 0x3288, "Haier Boyue G42", ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS),
        SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
        SND_PCI_QUIRK(0x1d72, 0x1701, "XiaomiNotebook Pro", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC),
index 48dae3339305048fca2262821e5ebfea6bcf237a..75f7674c66ee7ae8d9c407798193f4618b82a6b7 100644 (file)
@@ -514,10 +514,10 @@ static int tas2563_save_calibration(struct tasdevice_priv *tas_priv)
 static void tas2781_apply_calib(struct tasdevice_priv *tas_priv)
 {
        static const unsigned char page_array[CALIB_MAX] = {
-               0x17, 0x18, 0x18, 0x0d, 0x18
+               0x17, 0x18, 0x18, 0x13, 0x18,
        };
        static const unsigned char rgno_array[CALIB_MAX] = {
-               0x74, 0x0c, 0x14, 0x3c, 0x7c
+               0x74, 0x0c, 0x14, 0x70, 0x7c,
        };
        unsigned char *data;
        int i, j, rc;
index 7c7493cb571f97bf98b0b4841aeb756d43990718..52f076afeb96006c42dfee6edefcf348048af96b 100644 (file)
@@ -61,6 +61,7 @@
 #define ARM_CPU_IMP_HISI               0x48
 #define ARM_CPU_IMP_APPLE              0x61
 #define ARM_CPU_IMP_AMPERE             0xC0
+#define ARM_CPU_IMP_MICROSOFT          0x6D
 
 #define ARM_CPU_PART_AEM_V8            0xD0F
 #define ARM_CPU_PART_FOUNDATION                0xD00
 
 #define AMPERE_CPU_PART_AMPERE1                0xAC3
 
+#define MICROSOFT_CPU_PART_AZURE_COBALT_100    0xD49 /* Based on r0p0 of ARM Neoverse N2 */
+
 #define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53)
 #define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57)
 #define MIDR_CORTEX_A72 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A72)
 #define MIDR_APPLE_M2_BLIZZARD_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD_MAX)
 #define MIDR_APPLE_M2_AVALANCHE_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE_MAX)
 #define MIDR_AMPERE1 MIDR_CPU_MODEL(ARM_CPU_IMP_AMPERE, AMPERE_CPU_PART_AMPERE1)
+#define MIDR_MICROSOFT_AZURE_COBALT_100 MIDR_CPU_MODEL(ARM_CPU_IMP_MICROSOFT, MICROSOFT_CPU_PART_AZURE_COBALT_100)
 
 /* Fujitsu Erratum 010001 affects A64FX 1.0 and 1.1, (v0r0 and v1r0) */
 #define MIDR_FUJITSU_ERRATUM_010001            MIDR_FUJITSU_A64FX
index 89d2fc872d9f5e63dce2e2a74dfb422c9e255030..964df31da9751c96c984358c66d6f73c8519b2e7 100644 (file)
@@ -37,9 +37,7 @@
 #include <asm/ptrace.h>
 #include <asm/sve_context.h>
 
-#define __KVM_HAVE_GUEST_DEBUG
 #define __KVM_HAVE_IRQ_LINE
-#define __KVM_HAVE_READONLY_MEM
 #define __KVM_HAVE_VCPU_EVENTS
 
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
@@ -76,11 +74,11 @@ struct kvm_regs {
 
 /* KVM_ARM_SET_DEVICE_ADDR ioctl id encoding */
 #define KVM_ARM_DEVICE_TYPE_SHIFT      0
-#define KVM_ARM_DEVICE_TYPE_MASK       GENMASK(KVM_ARM_DEVICE_TYPE_SHIFT + 15, \
-                                               KVM_ARM_DEVICE_TYPE_SHIFT)
+#define KVM_ARM_DEVICE_TYPE_MASK       __GENMASK(KVM_ARM_DEVICE_TYPE_SHIFT + 15, \
+                                                 KVM_ARM_DEVICE_TYPE_SHIFT)
 #define KVM_ARM_DEVICE_ID_SHIFT                16
-#define KVM_ARM_DEVICE_ID_MASK         GENMASK(KVM_ARM_DEVICE_ID_SHIFT + 15, \
-                                               KVM_ARM_DEVICE_ID_SHIFT)
+#define KVM_ARM_DEVICE_ID_MASK         __GENMASK(KVM_ARM_DEVICE_ID_SHIFT + 15, \
+                                                 KVM_ARM_DEVICE_ID_SHIFT)
 
 /* Supported device IDs */
 #define KVM_ARM_DEVICE_VGIC_V2         0
@@ -162,6 +160,11 @@ struct kvm_sync_regs {
        __u64 device_irq_level;
 };
 
+/* Bits for run->s.regs.device_irq_level */
+#define KVM_ARM_DEV_EL1_VTIMER         (1 << 0)
+#define KVM_ARM_DEV_EL1_PTIMER         (1 << 1)
+#define KVM_ARM_DEV_PMU                        (1 << 2)
+
 /*
  * PMU filter structure. Describe a range of events with a particular
  * action. To be used with KVM_ARM_VCPU_PMU_V3_FILTER.
index 9f18fa090f1f1d08179cba6f39f7b832bbd7b95b..1691297a766a9c1a4df9384c4ff02ecd8ce21b92 100644 (file)
@@ -28,7 +28,6 @@
 #define __KVM_HAVE_PPC_SMT
 #define __KVM_HAVE_IRQCHIP
 #define __KVM_HAVE_IRQ_LINE
-#define __KVM_HAVE_GUEST_DEBUG
 
 /* Not always available, but if it is, this is the correct offset.  */
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
@@ -733,4 +732,48 @@ struct kvm_ppc_xive_eq {
 #define KVM_XIVE_TIMA_PAGE_OFFSET      0
 #define KVM_XIVE_ESB_PAGE_OFFSET       4
 
+/* for KVM_PPC_GET_PVINFO */
+
+#define KVM_PPC_PVINFO_FLAGS_EV_IDLE   (1<<0)
+
+struct kvm_ppc_pvinfo {
+       /* out */
+       __u32 flags;
+       __u32 hcall[4];
+       __u8  pad[108];
+};
+
+/* for KVM_PPC_GET_SMMU_INFO */
+#define KVM_PPC_PAGE_SIZES_MAX_SZ      8
+
+struct kvm_ppc_one_page_size {
+       __u32 page_shift;       /* Page shift (or 0) */
+       __u32 pte_enc;          /* Encoding in the HPTE (>>12) */
+};
+
+struct kvm_ppc_one_seg_page_size {
+       __u32 page_shift;       /* Base page shift of segment (or 0) */
+       __u32 slb_enc;          /* SLB encoding for BookS */
+       struct kvm_ppc_one_page_size enc[KVM_PPC_PAGE_SIZES_MAX_SZ];
+};
+
+#define KVM_PPC_PAGE_SIZES_REAL                0x00000001
+#define KVM_PPC_1T_SEGMENTS            0x00000002
+#define KVM_PPC_NO_HASH                        0x00000004
+
+struct kvm_ppc_smmu_info {
+       __u64 flags;
+       __u32 slb_size;
+       __u16 data_keys;        /* # storage keys supported for data */
+       __u16 instr_keys;       /* # storage keys supported for instructions */
+       struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
+};
+
+/* for KVM_PPC_RESIZE_HPT_{PREPARE,COMMIT} */
+struct kvm_ppc_resize_hpt {
+       __u64 flags;
+       __u32 shift;
+       __u32 pad;
+};
+
 #endif /* __LINUX_KVM_POWERPC_H */
index abe926d43cbe0a06342f8c53f202cdd707ea1693..05eaf6db3ad4cba4269b1ce36563096eab236b1d 100644 (file)
 #include <linux/types.h>
 
 #define __KVM_S390
-#define __KVM_HAVE_GUEST_DEBUG
+
+struct kvm_s390_skeys {
+       __u64 start_gfn;
+       __u64 count;
+       __u64 skeydata_addr;
+       __u32 flags;
+       __u32 reserved[9];
+};
+
+#define KVM_S390_CMMA_PEEK (1 << 0)
+
+/**
+ * kvm_s390_cmma_log - Used for CMMA migration.
+ *
+ * Used both for input and output.
+ *
+ * @start_gfn: Guest page number to start from.
+ * @count: Size of the result buffer.
+ * @flags: Control operation mode via KVM_S390_CMMA_* flags
+ * @remaining: Used with KVM_S390_GET_CMMA_BITS. Indicates how many dirty
+ *             pages are still remaining.
+ * @mask: Used with KVM_S390_SET_CMMA_BITS. Bitmap of bits to actually set
+ *        in the PGSTE.
+ * @values: Pointer to the values buffer.
+ *
+ * Used in KVM_S390_{G,S}ET_CMMA_BITS ioctls.
+ */
+struct kvm_s390_cmma_log {
+       __u64 start_gfn;
+       __u32 count;
+       __u32 flags;
+       union {
+               __u64 remaining;
+               __u64 mask;
+       };
+       __u64 values;
+};
+
+#define KVM_S390_RESET_POR       1
+#define KVM_S390_RESET_CLEAR     2
+#define KVM_S390_RESET_SUBSYSTEM 4
+#define KVM_S390_RESET_CPU_INIT  8
+#define KVM_S390_RESET_IPL       16
+
+/* for KVM_S390_MEM_OP */
+struct kvm_s390_mem_op {
+       /* in */
+       __u64 gaddr;            /* the guest address */
+       __u64 flags;            /* flags */
+       __u32 size;             /* amount of bytes */
+       __u32 op;               /* type of operation */
+       __u64 buf;              /* buffer in userspace */
+       union {
+               struct {
+                       __u8 ar;        /* the access register number */
+                       __u8 key;       /* access key, ignored if flag unset */
+                       __u8 pad1[6];   /* ignored */
+                       __u64 old_addr; /* ignored if cmpxchg flag unset */
+               };
+               __u32 sida_offset; /* offset into the sida */
+               __u8 reserved[32]; /* ignored */
+       };
+};
+/* types for kvm_s390_mem_op->op */
+#define KVM_S390_MEMOP_LOGICAL_READ    0
+#define KVM_S390_MEMOP_LOGICAL_WRITE   1
+#define KVM_S390_MEMOP_SIDA_READ       2
+#define KVM_S390_MEMOP_SIDA_WRITE      3
+#define KVM_S390_MEMOP_ABSOLUTE_READ   4
+#define KVM_S390_MEMOP_ABSOLUTE_WRITE  5
+#define KVM_S390_MEMOP_ABSOLUTE_CMPXCHG        6
+
+/* flags for kvm_s390_mem_op->flags */
+#define KVM_S390_MEMOP_F_CHECK_ONLY            (1ULL << 0)
+#define KVM_S390_MEMOP_F_INJECT_EXCEPTION      (1ULL << 1)
+#define KVM_S390_MEMOP_F_SKEY_PROTECTION       (1ULL << 2)
+
+/* flags specifying extension support via KVM_CAP_S390_MEM_OP_EXTENSION */
+#define KVM_S390_MEMOP_EXTENSION_CAP_BASE      (1 << 0)
+#define KVM_S390_MEMOP_EXTENSION_CAP_CMPXCHG   (1 << 1)
+
+struct kvm_s390_psw {
+       __u64 mask;
+       __u64 addr;
+};
+
+/* valid values for type in kvm_s390_interrupt */
+#define KVM_S390_SIGP_STOP             0xfffe0000u
+#define KVM_S390_PROGRAM_INT           0xfffe0001u
+#define KVM_S390_SIGP_SET_PREFIX       0xfffe0002u
+#define KVM_S390_RESTART               0xfffe0003u
+#define KVM_S390_INT_PFAULT_INIT       0xfffe0004u
+#define KVM_S390_INT_PFAULT_DONE       0xfffe0005u
+#define KVM_S390_MCHK                  0xfffe1000u
+#define KVM_S390_INT_CLOCK_COMP                0xffff1004u
+#define KVM_S390_INT_CPU_TIMER         0xffff1005u
+#define KVM_S390_INT_VIRTIO            0xffff2603u
+#define KVM_S390_INT_SERVICE           0xffff2401u
+#define KVM_S390_INT_EMERGENCY         0xffff1201u
+#define KVM_S390_INT_EXTERNAL_CALL     0xffff1202u
+/* Anything below 0xfffe0000u is taken by INT_IO */
+#define KVM_S390_INT_IO(ai,cssid,ssid,schid)   \
+       (((schid)) |                           \
+        ((ssid) << 16) |                      \
+        ((cssid) << 18) |                     \
+        ((ai) << 26))
+#define KVM_S390_INT_IO_MIN            0x00000000u
+#define KVM_S390_INT_IO_MAX            0xfffdffffu
+#define KVM_S390_INT_IO_AI_MASK                0x04000000u
+
+
+struct kvm_s390_interrupt {
+       __u32 type;
+       __u32 parm;
+       __u64 parm64;
+};
+
+struct kvm_s390_io_info {
+       __u16 subchannel_id;
+       __u16 subchannel_nr;
+       __u32 io_int_parm;
+       __u32 io_int_word;
+};
+
+struct kvm_s390_ext_info {
+       __u32 ext_params;
+       __u32 pad;
+       __u64 ext_params2;
+};
+
+struct kvm_s390_pgm_info {
+       __u64 trans_exc_code;
+       __u64 mon_code;
+       __u64 per_address;
+       __u32 data_exc_code;
+       __u16 code;
+       __u16 mon_class_nr;
+       __u8 per_code;
+       __u8 per_atmid;
+       __u8 exc_access_id;
+       __u8 per_access_id;
+       __u8 op_access_id;
+#define KVM_S390_PGM_FLAGS_ILC_VALID   0x01
+#define KVM_S390_PGM_FLAGS_ILC_0       0x02
+#define KVM_S390_PGM_FLAGS_ILC_1       0x04
+#define KVM_S390_PGM_FLAGS_ILC_MASK    0x06
+#define KVM_S390_PGM_FLAGS_NO_REWIND   0x08
+       __u8 flags;
+       __u8 pad[2];
+};
+
+struct kvm_s390_prefix_info {
+       __u32 address;
+};
+
+struct kvm_s390_extcall_info {
+       __u16 code;
+};
+
+struct kvm_s390_emerg_info {
+       __u16 code;
+};
+
+#define KVM_S390_STOP_FLAG_STORE_STATUS        0x01
+struct kvm_s390_stop_info {
+       __u32 flags;
+};
+
+struct kvm_s390_mchk_info {
+       __u64 cr14;
+       __u64 mcic;
+       __u64 failing_storage_address;
+       __u32 ext_damage_code;
+       __u32 pad;
+       __u8 fixed_logout[16];
+};
+
+struct kvm_s390_irq {
+       __u64 type;
+       union {
+               struct kvm_s390_io_info io;
+               struct kvm_s390_ext_info ext;
+               struct kvm_s390_pgm_info pgm;
+               struct kvm_s390_emerg_info emerg;
+               struct kvm_s390_extcall_info extcall;
+               struct kvm_s390_prefix_info prefix;
+               struct kvm_s390_stop_info stop;
+               struct kvm_s390_mchk_info mchk;
+               char reserved[64];
+       } u;
+};
+
+struct kvm_s390_irq_state {
+       __u64 buf;
+       __u32 flags;        /* will stay unused for compatibility reasons */
+       __u32 len;
+       __u32 reserved[4];  /* will stay unused for compatibility reasons */
+};
+
+struct kvm_s390_ucas_mapping {
+       __u64 user_addr;
+       __u64 vcpu_addr;
+       __u64 length;
+};
+
+struct kvm_s390_pv_sec_parm {
+       __u64 origin;
+       __u64 length;
+};
+
+struct kvm_s390_pv_unp {
+       __u64 addr;
+       __u64 size;
+       __u64 tweak;
+};
+
+enum pv_cmd_dmp_id {
+       KVM_PV_DUMP_INIT,
+       KVM_PV_DUMP_CONFIG_STOR_STATE,
+       KVM_PV_DUMP_COMPLETE,
+       KVM_PV_DUMP_CPU,
+};
+
+struct kvm_s390_pv_dmp {
+       __u64 subcmd;
+       __u64 buff_addr;
+       __u64 buff_len;
+       __u64 gaddr;            /* For dump storage state */
+       __u64 reserved[4];
+};
+
+enum pv_cmd_info_id {
+       KVM_PV_INFO_VM,
+       KVM_PV_INFO_DUMP,
+};
+
+struct kvm_s390_pv_info_dump {
+       __u64 dump_cpu_buffer_len;
+       __u64 dump_config_mem_buffer_per_1m;
+       __u64 dump_config_finalize_len;
+};
+
+struct kvm_s390_pv_info_vm {
+       __u64 inst_calls_list[4];
+       __u64 max_cpus;
+       __u64 max_guests;
+       __u64 max_guest_addr;
+       __u64 feature_indication;
+};
+
+struct kvm_s390_pv_info_header {
+       __u32 id;
+       __u32 len_max;
+       __u32 len_written;
+       __u32 reserved;
+};
+
+struct kvm_s390_pv_info {
+       struct kvm_s390_pv_info_header header;
+       union {
+               struct kvm_s390_pv_info_dump dump;
+               struct kvm_s390_pv_info_vm vm;
+       };
+};
+
+enum pv_cmd_id {
+       KVM_PV_ENABLE,
+       KVM_PV_DISABLE,
+       KVM_PV_SET_SEC_PARMS,
+       KVM_PV_UNPACK,
+       KVM_PV_VERIFY,
+       KVM_PV_PREP_RESET,
+       KVM_PV_UNSHARE_ALL,
+       KVM_PV_INFO,
+       KVM_PV_DUMP,
+       KVM_PV_ASYNC_CLEANUP_PREPARE,
+       KVM_PV_ASYNC_CLEANUP_PERFORM,
+};
+
+struct kvm_pv_cmd {
+       __u32 cmd;      /* Command to be executed */
+       __u16 rc;       /* Ultravisor return code */
+       __u16 rrc;      /* Ultravisor return reason code */
+       __u64 data;     /* Data or address */
+       __u32 flags;    /* flags for future extensions. Must be 0 for now */
+       __u32 reserved[3];
+};
+
+struct kvm_s390_zpci_op {
+       /* in */
+       __u32 fh;               /* target device */
+       __u8  op;               /* operation to perform */
+       __u8  pad[3];
+       union {
+               /* for KVM_S390_ZPCIOP_REG_AEN */
+               struct {
+                       __u64 ibv;      /* Guest addr of interrupt bit vector */
+                       __u64 sb;       /* Guest addr of summary bit */
+                       __u32 flags;
+                       __u32 noi;      /* Number of interrupts */
+                       __u8 isc;       /* Guest interrupt subclass */
+                       __u8 sbo;       /* Offset of guest summary bit vector */
+                       __u16 pad;
+               } reg_aen;
+               __u64 reserved[8];
+       } u;
+};
+
+/* types for kvm_s390_zpci_op->op */
+#define KVM_S390_ZPCIOP_REG_AEN                0
+#define KVM_S390_ZPCIOP_DEREG_AEN      1
+
+/* flags for kvm_s390_zpci_op->u.reg_aen.flags */
+#define KVM_S390_ZPCIOP_REGAEN_HOST    (1 << 0)
 
 /* Device control API: s390-specific devices */
 #define KVM_DEV_FLIC_GET_ALL_IRQS      1
index 25160d26764b5e29c7f4e825979d6222ae15e5c4..a38f8f9ba65729125234814c08547498e4e3b8bc 100644 (file)
@@ -13,7 +13,7 @@
 /*
  * Defines x86 CPU feature bits
  */
-#define NCAPINTS                       21         /* N 32-bit words worth of info */
+#define NCAPINTS                       22         /* N 32-bit words worth of info */
 #define NBUGINTS                       2          /* N 32-bit bug flags */
 
 /*
 #define X86_FEATURE_K6_MTRR            ( 3*32+ 1) /* AMD K6 nonstandard MTRRs */
 #define X86_FEATURE_CYRIX_ARR          ( 3*32+ 2) /* Cyrix ARRs (= MTRRs) */
 #define X86_FEATURE_CENTAUR_MCR                ( 3*32+ 3) /* Centaur MCRs (= MTRRs) */
-
-/* CPU types for specific tunings: */
 #define X86_FEATURE_K8                 ( 3*32+ 4) /* "" Opteron, Athlon64 */
-/* FREE, was #define X86_FEATURE_K7                    ( 3*32+ 5) "" Athlon */
+#define X86_FEATURE_ZEN5               ( 3*32+ 5) /* "" CPU based on Zen5 microarchitecture */
 #define X86_FEATURE_P3                 ( 3*32+ 6) /* "" P3 */
 #define X86_FEATURE_P4                 ( 3*32+ 7) /* "" P4 */
 #define X86_FEATURE_CONSTANT_TSC       ( 3*32+ 8) /* TSC ticks at a constant rate */
@@ -97,7 +95,7 @@
 #define X86_FEATURE_SYSENTER32         ( 3*32+15) /* "" sysenter in IA32 userspace */
 #define X86_FEATURE_REP_GOOD           ( 3*32+16) /* REP microcode works well */
 #define X86_FEATURE_AMD_LBR_V2         ( 3*32+17) /* AMD Last Branch Record Extension Version 2 */
-/* FREE, was #define X86_FEATURE_LFENCE_RDTSC          ( 3*32+18) "" LFENCE synchronizes RDTSC */
+#define X86_FEATURE_CLEAR_CPU_BUF      ( 3*32+18) /* "" Clear CPU buffers using VERW */
 #define X86_FEATURE_ACC_POWER          ( 3*32+19) /* AMD Accumulated Power Mechanism */
 #define X86_FEATURE_NOPL               ( 3*32+20) /* The NOPL (0F 1F) instructions */
 #define X86_FEATURE_ALWAYS             ( 3*32+21) /* "" Always-present feature */
 #define X86_FEATURE_IBPB_BRTYPE                (20*32+28) /* "" MSR_PRED_CMD[IBPB] flushes all branch type predictions */
 #define X86_FEATURE_SRSO_NO            (20*32+29) /* "" CPU is not affected by SRSO */
 
+/*
+ * Extended auxiliary flags: Linux defined - for features scattered in various
+ * CPUID levels like 0x80000022, etc.
+ *
+ * Reuse free bits when adding new feature flags!
+ */
+#define X86_FEATURE_AMD_LBR_PMC_FREEZE (21*32+ 0) /* AMD LBR and PMC Freeze */
+
 /*
  * BUG word(s)
  */
 /* BUG word 2 */
 #define X86_BUG_SRSO                   X86_BUG(1*32 + 0) /* AMD SRSO bug */
 #define X86_BUG_DIV0                   X86_BUG(1*32 + 1) /* AMD DIV0 speculation bug */
+#define X86_BUG_RFDS                   X86_BUG(1*32 + 2) /* CPU is vulnerable to Register File Data Sampling */
 #endif /* _ASM_X86_CPUFEATURES_H */
index 1f23960d2b06e7bea48be6f7213e678962626e99..c492bdc97b0595ec77f89dc9b0cefe5e3e64be41 100644 (file)
 # define DISABLE_FRED  (1 << (X86_FEATURE_FRED & 31))
 #endif
 
+#ifdef CONFIG_KVM_AMD_SEV
+#define DISABLE_SEV_SNP                0
+#else
+#define DISABLE_SEV_SNP                (1 << (X86_FEATURE_SEV_SNP & 31))
+#endif
+
 /*
  * Make sure to add features to the correct mask
  */
                         DISABLE_ENQCMD)
 #define DISABLED_MASK17        0
 #define DISABLED_MASK18        (DISABLE_IBT)
-#define DISABLED_MASK19        0
+#define DISABLED_MASK19        (DISABLE_SEV_SNP)
 #define DISABLED_MASK20        0
-#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 21)
+#define DISABLED_MASK21        0
+#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 22)
 
 #endif /* _ASM_X86_DISABLED_FEATURES_H */
index 3f73ac3ed3a0709a700ae927bca01069a1910665..d18bfb238f660fcccdfdf444a60720f03163e4d5 100644 (file)
 #define HYPERVISOR_CALLBACK_VECTOR     0xf3
 
 /* Vector for KVM to deliver posted interrupt IPI */
-#if IS_ENABLED(CONFIG_KVM)
 #define POSTED_INTR_VECTOR             0xf2
 #define POSTED_INTR_WAKEUP_VECTOR      0xf1
 #define POSTED_INTR_NESTED_VECTOR      0xf0
-#endif
 
 #define MANAGED_IRQ_SHUTDOWN_VECTOR    0xef
 
index 1f9dc9bd13eb7e9c7bc509b1d09cec7f473157b4..05956bd8bacf50e35f463c13720a38735fe8b1b5 100644 (file)
                                                 * CPU is not vulnerable to Gather
                                                 * Data Sampling (GDS).
                                                 */
+#define ARCH_CAP_RFDS_NO               BIT(27) /*
+                                                * Not susceptible to Register
+                                                * File Data Sampling.
+                                                */
+#define ARCH_CAP_RFDS_CLEAR            BIT(28) /*
+                                                * VERW clears CPU Register
+                                                * File.
+                                                */
 
 #define ARCH_CAP_XAPIC_DISABLE         BIT(21) /*
                                                 * IA32_XAPIC_DISABLE_STATUS MSR
 #define MSR_AMD64_SEV_ES_GHCB          0xc0010130
 #define MSR_AMD64_SEV                  0xc0010131
 #define MSR_AMD64_SEV_ENABLED_BIT      0
-#define MSR_AMD64_SEV_ES_ENABLED_BIT   1
-#define MSR_AMD64_SEV_SNP_ENABLED_BIT  2
 #define MSR_AMD64_SEV_ENABLED          BIT_ULL(MSR_AMD64_SEV_ENABLED_BIT)
+#define MSR_AMD64_SEV_ES_ENABLED_BIT   1
 #define MSR_AMD64_SEV_ES_ENABLED       BIT_ULL(MSR_AMD64_SEV_ES_ENABLED_BIT)
+#define MSR_AMD64_SEV_SNP_ENABLED_BIT  2
 #define MSR_AMD64_SEV_SNP_ENABLED      BIT_ULL(MSR_AMD64_SEV_SNP_ENABLED_BIT)
-
-/* SNP feature bits enabled by the hypervisor */
-#define MSR_AMD64_SNP_VTOM                     BIT_ULL(3)
-#define MSR_AMD64_SNP_REFLECT_VC               BIT_ULL(4)
-#define MSR_AMD64_SNP_RESTRICTED_INJ           BIT_ULL(5)
-#define MSR_AMD64_SNP_ALT_INJ                  BIT_ULL(6)
-#define MSR_AMD64_SNP_DEBUG_SWAP               BIT_ULL(7)
-#define MSR_AMD64_SNP_PREVENT_HOST_IBS         BIT_ULL(8)
-#define MSR_AMD64_SNP_BTB_ISOLATION            BIT_ULL(9)
-#define MSR_AMD64_SNP_VMPL_SSS                 BIT_ULL(10)
-#define MSR_AMD64_SNP_SECURE_TSC               BIT_ULL(11)
-#define MSR_AMD64_SNP_VMGEXIT_PARAM            BIT_ULL(12)
-#define MSR_AMD64_SNP_IBS_VIRT                 BIT_ULL(14)
-#define MSR_AMD64_SNP_VMSA_REG_PROTECTION      BIT_ULL(16)
-#define MSR_AMD64_SNP_SMT_PROTECTION           BIT_ULL(17)
-
-/* SNP feature bits reserved for future use. */
-#define MSR_AMD64_SNP_RESERVED_BIT13           BIT_ULL(13)
-#define MSR_AMD64_SNP_RESERVED_BIT15           BIT_ULL(15)
-#define MSR_AMD64_SNP_RESERVED_MASK            GENMASK_ULL(63, 18)
+#define MSR_AMD64_SNP_VTOM_BIT         3
+#define MSR_AMD64_SNP_VTOM             BIT_ULL(MSR_AMD64_SNP_VTOM_BIT)
+#define MSR_AMD64_SNP_REFLECT_VC_BIT   4
+#define MSR_AMD64_SNP_REFLECT_VC       BIT_ULL(MSR_AMD64_SNP_REFLECT_VC_BIT)
+#define MSR_AMD64_SNP_RESTRICTED_INJ_BIT 5
+#define MSR_AMD64_SNP_RESTRICTED_INJ   BIT_ULL(MSR_AMD64_SNP_RESTRICTED_INJ_BIT)
+#define MSR_AMD64_SNP_ALT_INJ_BIT      6
+#define MSR_AMD64_SNP_ALT_INJ          BIT_ULL(MSR_AMD64_SNP_ALT_INJ_BIT)
+#define MSR_AMD64_SNP_DEBUG_SWAP_BIT   7
+#define MSR_AMD64_SNP_DEBUG_SWAP       BIT_ULL(MSR_AMD64_SNP_DEBUG_SWAP_BIT)
+#define MSR_AMD64_SNP_PREVENT_HOST_IBS_BIT 8
+#define MSR_AMD64_SNP_PREVENT_HOST_IBS BIT_ULL(MSR_AMD64_SNP_PREVENT_HOST_IBS_BIT)
+#define MSR_AMD64_SNP_BTB_ISOLATION_BIT        9
+#define MSR_AMD64_SNP_BTB_ISOLATION    BIT_ULL(MSR_AMD64_SNP_BTB_ISOLATION_BIT)
+#define MSR_AMD64_SNP_VMPL_SSS_BIT     10
+#define MSR_AMD64_SNP_VMPL_SSS         BIT_ULL(MSR_AMD64_SNP_VMPL_SSS_BIT)
+#define MSR_AMD64_SNP_SECURE_TSC_BIT   11
+#define MSR_AMD64_SNP_SECURE_TSC       BIT_ULL(MSR_AMD64_SNP_SECURE_TSC_BIT)
+#define MSR_AMD64_SNP_VMGEXIT_PARAM_BIT        12
+#define MSR_AMD64_SNP_VMGEXIT_PARAM    BIT_ULL(MSR_AMD64_SNP_VMGEXIT_PARAM_BIT)
+#define MSR_AMD64_SNP_RESERVED_BIT13   BIT_ULL(13)
+#define MSR_AMD64_SNP_IBS_VIRT_BIT     14
+#define MSR_AMD64_SNP_IBS_VIRT         BIT_ULL(MSR_AMD64_SNP_IBS_VIRT_BIT)
+#define MSR_AMD64_SNP_RESERVED_BIT15   BIT_ULL(15)
+#define MSR_AMD64_SNP_VMSA_REG_PROT_BIT        16
+#define MSR_AMD64_SNP_VMSA_REG_PROT    BIT_ULL(MSR_AMD64_SNP_VMSA_REG_PROT_BIT)
+#define MSR_AMD64_SNP_SMT_PROT_BIT     17
+#define MSR_AMD64_SNP_SMT_PROT         BIT_ULL(MSR_AMD64_SNP_SMT_PROT_BIT)
+#define MSR_AMD64_SNP_RESV_BIT         18
+#define MSR_AMD64_SNP_RESERVED_MASK    GENMASK_ULL(63, MSR_AMD64_SNP_RESV_BIT)
 
 #define MSR_AMD64_VIRT_SPEC_CTRL       0xc001011f
 
+#define MSR_AMD64_RMP_BASE             0xc0010132
+#define MSR_AMD64_RMP_END              0xc0010133
+
 /* AMD Collaborative Processor Performance Control MSRs */
 #define MSR_AMD_CPPC_CAP1              0xc00102b0
 #define MSR_AMD_CPPC_ENABLE            0xc00102b1
 #define MSR_K8_TOP_MEM1                        0xc001001a
 #define MSR_K8_TOP_MEM2                        0xc001001d
 #define MSR_AMD64_SYSCFG               0xc0010010
-#define MSR_AMD64_SYSCFG_MEM_ENCRYPT_BIT       23
+#define MSR_AMD64_SYSCFG_MEM_ENCRYPT_BIT 23
 #define MSR_AMD64_SYSCFG_MEM_ENCRYPT   BIT_ULL(MSR_AMD64_SYSCFG_MEM_ENCRYPT_BIT)
+#define MSR_AMD64_SYSCFG_SNP_EN_BIT    24
+#define MSR_AMD64_SYSCFG_SNP_EN                BIT_ULL(MSR_AMD64_SYSCFG_SNP_EN_BIT)
+#define MSR_AMD64_SYSCFG_SNP_VMPL_EN_BIT 25
+#define MSR_AMD64_SYSCFG_SNP_VMPL_EN   BIT_ULL(MSR_AMD64_SYSCFG_SNP_VMPL_EN_BIT)
+#define MSR_AMD64_SYSCFG_MFDM_BIT      19
+#define MSR_AMD64_SYSCFG_MFDM          BIT_ULL(MSR_AMD64_SYSCFG_MFDM_BIT)
+
 #define MSR_K8_INT_PENDING_MSG         0xc0010055
 /* C1E active bits in int pending message */
 #define K8_INTP_C1E_ACTIVE_MASK                0x18000000
index 7ba1726b71c7b8bfc95888dc78508998bba263fe..e9187ddd3d1fdc61fff087b0ea3b8b9b0ff33ac3 100644 (file)
@@ -99,6 +99,7 @@
 #define REQUIRED_MASK18        0
 #define REQUIRED_MASK19        0
 #define REQUIRED_MASK20        0
-#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 21)
+#define REQUIRED_MASK21        0
+#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 22)
 
 #endif /* _ASM_X86_REQUIRED_FEATURES_H */
index a448d0964fc06ebd0c15cd0b550e3c2cefbf57bf..ef11aa4cab42536cf1773bf5b787bcf715bd76e9 100644 (file)
@@ -7,6 +7,8 @@
  *
  */
 
+#include <linux/const.h>
+#include <linux/bits.h>
 #include <linux/types.h>
 #include <linux/ioctl.h>
 #include <linux/stddef.h>
@@ -40,7 +42,6 @@
 #define __KVM_HAVE_IRQ_LINE
 #define __KVM_HAVE_MSI
 #define __KVM_HAVE_USER_NMI
-#define __KVM_HAVE_GUEST_DEBUG
 #define __KVM_HAVE_MSIX
 #define __KVM_HAVE_MCE
 #define __KVM_HAVE_PIT_STATE2
@@ -49,7 +50,6 @@
 #define __KVM_HAVE_DEBUGREGS
 #define __KVM_HAVE_XSAVE
 #define __KVM_HAVE_XCRS
-#define __KVM_HAVE_READONLY_MEM
 
 /* Architectural interrupt line count. */
 #define KVM_NR_INTERRUPTS 256
@@ -526,9 +526,301 @@ struct kvm_pmu_event_filter {
 #define KVM_PMU_EVENT_ALLOW 0
 #define KVM_PMU_EVENT_DENY 1
 
-#define KVM_PMU_EVENT_FLAG_MASKED_EVENTS BIT(0)
+#define KVM_PMU_EVENT_FLAG_MASKED_EVENTS _BITUL(0)
 #define KVM_PMU_EVENT_FLAGS_VALID_MASK (KVM_PMU_EVENT_FLAG_MASKED_EVENTS)
 
+/* for KVM_CAP_MCE */
+struct kvm_x86_mce {
+       __u64 status;
+       __u64 addr;
+       __u64 misc;
+       __u64 mcg_status;
+       __u8 bank;
+       __u8 pad1[7];
+       __u64 pad2[3];
+};
+
+/* for KVM_CAP_XEN_HVM */
+#define KVM_XEN_HVM_CONFIG_HYPERCALL_MSR       (1 << 0)
+#define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL     (1 << 1)
+#define KVM_XEN_HVM_CONFIG_SHARED_INFO         (1 << 2)
+#define KVM_XEN_HVM_CONFIG_RUNSTATE            (1 << 3)
+#define KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL       (1 << 4)
+#define KVM_XEN_HVM_CONFIG_EVTCHN_SEND         (1 << 5)
+#define KVM_XEN_HVM_CONFIG_RUNSTATE_UPDATE_FLAG        (1 << 6)
+#define KVM_XEN_HVM_CONFIG_PVCLOCK_TSC_UNSTABLE        (1 << 7)
+#define KVM_XEN_HVM_CONFIG_SHARED_INFO_HVA     (1 << 8)
+
+struct kvm_xen_hvm_config {
+       __u32 flags;
+       __u32 msr;
+       __u64 blob_addr_32;
+       __u64 blob_addr_64;
+       __u8 blob_size_32;
+       __u8 blob_size_64;
+       __u8 pad2[30];
+};
+
+struct kvm_xen_hvm_attr {
+       __u16 type;
+       __u16 pad[3];
+       union {
+               __u8 long_mode;
+               __u8 vector;
+               __u8 runstate_update_flag;
+               union {
+                       __u64 gfn;
+#define KVM_XEN_INVALID_GFN ((__u64)-1)
+                       __u64 hva;
+               } shared_info;
+               struct {
+                       __u32 send_port;
+                       __u32 type; /* EVTCHNSTAT_ipi / EVTCHNSTAT_interdomain */
+                       __u32 flags;
+#define KVM_XEN_EVTCHN_DEASSIGN                (1 << 0)
+#define KVM_XEN_EVTCHN_UPDATE          (1 << 1)
+#define KVM_XEN_EVTCHN_RESET           (1 << 2)
+                       /*
+                        * Events sent by the guest are either looped back to
+                        * the guest itself (potentially on a different port#)
+                        * or signalled via an eventfd.
+                        */
+                       union {
+                               struct {
+                                       __u32 port;
+                                       __u32 vcpu;
+                                       __u32 priority;
+                               } port;
+                               struct {
+                                       __u32 port; /* Zero for eventfd */
+                                       __s32 fd;
+                               } eventfd;
+                               __u32 padding[4];
+                       } deliver;
+               } evtchn;
+               __u32 xen_version;
+               __u64 pad[8];
+       } u;
+};
+
+
+/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO */
+#define KVM_XEN_ATTR_TYPE_LONG_MODE            0x0
+#define KVM_XEN_ATTR_TYPE_SHARED_INFO          0x1
+#define KVM_XEN_ATTR_TYPE_UPCALL_VECTOR                0x2
+/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_EVTCHN_SEND */
+#define KVM_XEN_ATTR_TYPE_EVTCHN               0x3
+#define KVM_XEN_ATTR_TYPE_XEN_VERSION          0x4
+/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_RUNSTATE_UPDATE_FLAG */
+#define KVM_XEN_ATTR_TYPE_RUNSTATE_UPDATE_FLAG 0x5
+/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO_HVA */
+#define KVM_XEN_ATTR_TYPE_SHARED_INFO_HVA      0x6
+
+struct kvm_xen_vcpu_attr {
+       __u16 type;
+       __u16 pad[3];
+       union {
+               __u64 gpa;
+#define KVM_XEN_INVALID_GPA ((__u64)-1)
+               __u64 hva;
+               __u64 pad[8];
+               struct {
+                       __u64 state;
+                       __u64 state_entry_time;
+                       __u64 time_running;
+                       __u64 time_runnable;
+                       __u64 time_blocked;
+                       __u64 time_offline;
+               } runstate;
+               __u32 vcpu_id;
+               struct {
+                       __u32 port;
+                       __u32 priority;
+                       __u64 expires_ns;
+               } timer;
+               __u8 vector;
+       } u;
+};
+
+/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO */
+#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO       0x0
+#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO  0x1
+#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADDR   0x2
+#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_CURRENT        0x3
+#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_DATA   0x4
+#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST 0x5
+/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_EVTCHN_SEND */
+#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_ID         0x6
+#define KVM_XEN_VCPU_ATTR_TYPE_TIMER           0x7
+#define KVM_XEN_VCPU_ATTR_TYPE_UPCALL_VECTOR   0x8
+/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO_HVA */
+#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO_HVA   0x9
+
+/* Secure Encrypted Virtualization command */
+enum sev_cmd_id {
+       /* Guest initialization commands */
+       KVM_SEV_INIT = 0,
+       KVM_SEV_ES_INIT,
+       /* Guest launch commands */
+       KVM_SEV_LAUNCH_START,
+       KVM_SEV_LAUNCH_UPDATE_DATA,
+       KVM_SEV_LAUNCH_UPDATE_VMSA,
+       KVM_SEV_LAUNCH_SECRET,
+       KVM_SEV_LAUNCH_MEASURE,
+       KVM_SEV_LAUNCH_FINISH,
+       /* Guest migration commands (outgoing) */
+       KVM_SEV_SEND_START,
+       KVM_SEV_SEND_UPDATE_DATA,
+       KVM_SEV_SEND_UPDATE_VMSA,
+       KVM_SEV_SEND_FINISH,
+       /* Guest migration commands (incoming) */
+       KVM_SEV_RECEIVE_START,
+       KVM_SEV_RECEIVE_UPDATE_DATA,
+       KVM_SEV_RECEIVE_UPDATE_VMSA,
+       KVM_SEV_RECEIVE_FINISH,
+       /* Guest status and debug commands */
+       KVM_SEV_GUEST_STATUS,
+       KVM_SEV_DBG_DECRYPT,
+       KVM_SEV_DBG_ENCRYPT,
+       /* Guest certificates commands */
+       KVM_SEV_CERT_EXPORT,
+       /* Attestation report */
+       KVM_SEV_GET_ATTESTATION_REPORT,
+       /* Guest Migration Extension */
+       KVM_SEV_SEND_CANCEL,
+
+       KVM_SEV_NR_MAX,
+};
+
+struct kvm_sev_cmd {
+       __u32 id;
+       __u32 pad0;
+       __u64 data;
+       __u32 error;
+       __u32 sev_fd;
+};
+
+struct kvm_sev_launch_start {
+       __u32 handle;
+       __u32 policy;
+       __u64 dh_uaddr;
+       __u32 dh_len;
+       __u32 pad0;
+       __u64 session_uaddr;
+       __u32 session_len;
+       __u32 pad1;
+};
+
+struct kvm_sev_launch_update_data {
+       __u64 uaddr;
+       __u32 len;
+       __u32 pad0;
+};
+
+
+struct kvm_sev_launch_secret {
+       __u64 hdr_uaddr;
+       __u32 hdr_len;
+       __u32 pad0;
+       __u64 guest_uaddr;
+       __u32 guest_len;
+       __u32 pad1;
+       __u64 trans_uaddr;
+       __u32 trans_len;
+       __u32 pad2;
+};
+
+struct kvm_sev_launch_measure {
+       __u64 uaddr;
+       __u32 len;
+       __u32 pad0;
+};
+
+struct kvm_sev_guest_status {
+       __u32 handle;
+       __u32 policy;
+       __u32 state;
+};
+
+struct kvm_sev_dbg {
+       __u64 src_uaddr;
+       __u64 dst_uaddr;
+       __u32 len;
+       __u32 pad0;
+};
+
+struct kvm_sev_attestation_report {
+       __u8 mnonce[16];
+       __u64 uaddr;
+       __u32 len;
+       __u32 pad0;
+};
+
+struct kvm_sev_send_start {
+       __u32 policy;
+       __u32 pad0;
+       __u64 pdh_cert_uaddr;
+       __u32 pdh_cert_len;
+       __u32 pad1;
+       __u64 plat_certs_uaddr;
+       __u32 plat_certs_len;
+       __u32 pad2;
+       __u64 amd_certs_uaddr;
+       __u32 amd_certs_len;
+       __u32 pad3;
+       __u64 session_uaddr;
+       __u32 session_len;
+       __u32 pad4;
+};
+
+struct kvm_sev_send_update_data {
+       __u64 hdr_uaddr;
+       __u32 hdr_len;
+       __u32 pad0;
+       __u64 guest_uaddr;
+       __u32 guest_len;
+       __u32 pad1;
+       __u64 trans_uaddr;
+       __u32 trans_len;
+       __u32 pad2;
+};
+
+struct kvm_sev_receive_start {
+       __u32 handle;
+       __u32 policy;
+       __u64 pdh_uaddr;
+       __u32 pdh_len;
+       __u32 pad0;
+       __u64 session_uaddr;
+       __u32 session_len;
+       __u32 pad1;
+};
+
+struct kvm_sev_receive_update_data {
+       __u64 hdr_uaddr;
+       __u32 hdr_len;
+       __u32 pad0;
+       __u64 guest_uaddr;
+       __u32 guest_len;
+       __u32 pad1;
+       __u64 trans_uaddr;
+       __u32 trans_len;
+       __u32 pad2;
+};
+
+#define KVM_X2APIC_API_USE_32BIT_IDS            (1ULL << 0)
+#define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK  (1ULL << 1)
+
+struct kvm_hyperv_eventfd {
+       __u32 conn_id;
+       __s32 fd;
+       __u32 flags;
+       __u32 padding[3];
+};
+
+#define KVM_HYPERV_CONN_ID_MASK                0x00ffffff
+#define KVM_HYPERV_EVENTFD_DEASSIGN    (1 << 0)
+
 /*
  * Masked event layout.
  * Bits   Description
@@ -549,10 +841,10 @@ struct kvm_pmu_event_filter {
        ((__u64)(!!(exclude)) << 55))
 
 #define KVM_PMU_MASKED_ENTRY_EVENT_SELECT \
-       (GENMASK_ULL(7, 0) | GENMASK_ULL(35, 32))
-#define KVM_PMU_MASKED_ENTRY_UMASK_MASK                (GENMASK_ULL(63, 56))
-#define KVM_PMU_MASKED_ENTRY_UMASK_MATCH       (GENMASK_ULL(15, 8))
-#define KVM_PMU_MASKED_ENTRY_EXCLUDE           (BIT_ULL(55))
+       (__GENMASK_ULL(7, 0) | __GENMASK_ULL(35, 32))
+#define KVM_PMU_MASKED_ENTRY_UMASK_MASK                (__GENMASK_ULL(63, 56))
+#define KVM_PMU_MASKED_ENTRY_UMASK_MATCH       (__GENMASK_ULL(15, 8))
+#define KVM_PMU_MASKED_ENTRY_EXCLUDE           (_BITULL(55))
 #define KVM_PMU_MASKED_ENTRY_UMASK_MASK_SHIFT  (56)
 
 /* for KVM_{GET,SET,HAS}_DEVICE_ATTR */
@@ -560,7 +852,7 @@ struct kvm_pmu_event_filter {
 #define   KVM_VCPU_TSC_OFFSET 0 /* attribute for the TSC offset */
 
 /* x86-specific KVM_EXIT_HYPERCALL flags. */
-#define KVM_EXIT_HYPERCALL_LONG_MODE   BIT(0)
+#define KVM_EXIT_HYPERCALL_LONG_MODE   _BITULL(0)
 
 #define KVM_X86_DEFAULT_VM     0
 #define KVM_X86_SW_PROTECTED_VM        1
index 03f721a8a2b1993734e458399a68848637112c87..54ccccf96e21eaad9cf4a681d304ad8ac689f371 100644 (file)
@@ -5,12 +5,12 @@
 #include <asm/types.h>
 
 /**
- * __fls - find last (most-significant) set bit in a long word
+ * generic___fls - find last (most-significant) set bit in a long word
  * @word: the word to search
  *
  * Undefined if no set bit exists, so code should check against 0 first.
  */
-static __always_inline unsigned long __fls(unsigned long word)
+static __always_inline unsigned long generic___fls(unsigned long word)
 {
        int num = BITS_PER_LONG - 1;
 
@@ -41,4 +41,8 @@ static __always_inline unsigned long __fls(unsigned long word)
        return num;
 }
 
+#ifndef __HAVE_ARCH___FLS
+#define __fls(word) generic___fls(word)
+#endif
+
 #endif /* _ASM_GENERIC_BITOPS___FLS_H_ */
index b168bb10e1be17bb6394e749c238da3940ea3a01..26f3ce1dd6e44872000d7066d4b3e37325e915fa 100644 (file)
@@ -3,14 +3,14 @@
 #define _ASM_GENERIC_BITOPS_FLS_H_
 
 /**
- * fls - find last (most-significant) bit set
+ * generic_fls - find last (most-significant) bit set
  * @x: the word to search
  *
  * This is defined the same way as ffs.
  * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
  */
 
-static __always_inline int fls(unsigned int x)
+static __always_inline int generic_fls(unsigned int x)
 {
        int r = 32;
 
@@ -39,4 +39,8 @@ static __always_inline int fls(unsigned int x)
        return r;
 }
 
+#ifndef __HAVE_ARCH_FLS
+#define fls(x) generic_fls(x)
+#endif
+
 #endif /* _ASM_GENERIC_BITOPS_FLS_H_ */
index fd4f9574d177a269b2cdbe5a36b3b30f2addbc94..2ee338860b7e08c80fb9f0a65702dc1b18456b6b 100644 (file)
@@ -3013,6 +3013,7 @@ struct drm_i915_query_item {
         *  - %DRM_I915_QUERY_MEMORY_REGIONS (see struct drm_i915_query_memory_regions)
         *  - %DRM_I915_QUERY_HWCONFIG_BLOB (see `GuC HWCONFIG blob uAPI`)
         *  - %DRM_I915_QUERY_GEOMETRY_SUBSLICES (see struct drm_i915_query_topology_info)
+        *  - %DRM_I915_QUERY_GUC_SUBMISSION_VERSION (see struct drm_i915_query_guc_submission_version)
         */
        __u64 query_id;
 #define DRM_I915_QUERY_TOPOLOGY_INFO           1
@@ -3021,6 +3022,7 @@ struct drm_i915_query_item {
 #define DRM_I915_QUERY_MEMORY_REGIONS          4
 #define DRM_I915_QUERY_HWCONFIG_BLOB           5
 #define DRM_I915_QUERY_GEOMETRY_SUBSLICES      6
+#define DRM_I915_QUERY_GUC_SUBMISSION_VERSION  7
 /* Must be kept compact -- no holes and well documented */
 
        /**
@@ -3566,6 +3568,20 @@ struct drm_i915_query_memory_regions {
        struct drm_i915_memory_region_info regions[];
 };
 
+/**
+ * struct drm_i915_query_guc_submission_version - query GuC submission interface version
+ */
+struct drm_i915_query_guc_submission_version {
+       /** @branch: Firmware branch version. */
+       __u32 branch;
+       /** @major: Firmware major version. */
+       __u32 major;
+       /** @minor: Firmware minor version. */
+       __u32 minor;
+       /** @patch: Firmware patch version. */
+       __u32 patch;
+};
+
 /**
  * DOC: GuC HWCONFIG blob uAPI
  *
index 48ad69f7722e1ae51ae5871a06482b6aa45dfc18..45e4e64fd6643ce3a83711cb295c711dd67ca511 100644 (file)
@@ -64,6 +64,24 @@ struct fstrim_range {
        __u64 minlen;
 };
 
+/*
+ * We include a length field because some filesystems (vfat) have an identifier
+ * that we do want to expose as a UUID, but doesn't have the standard length.
+ *
+ * We use a fixed size buffer beacuse this interface will, by fiat, never
+ * support "UUIDs" longer than 16 bytes; we don't want to force all downstream
+ * users to have to deal with that.
+ */
+struct fsuuid2 {
+       __u8    len;
+       __u8    uuid[16];
+};
+
+struct fs_sysfs_path {
+       __u8                    len;
+       __u8                    name[128];
+};
+
 /* extent-same (dedupe) ioctls; these MUST match the btrfs ioctl definitions */
 #define FILE_DEDUPE_RANGE_SAME         0
 #define FILE_DEDUPE_RANGE_DIFFERS      1
@@ -215,6 +233,13 @@ struct fsxattr {
 #define FS_IOC_FSSETXATTR              _IOW('X', 32, struct fsxattr)
 #define FS_IOC_GETFSLABEL              _IOR(0x94, 49, char[FSLABEL_MAX])
 #define FS_IOC_SETFSLABEL              _IOW(0x94, 50, char[FSLABEL_MAX])
+/* Returns the external filesystem UUID, the same one blkid returns */
+#define FS_IOC_GETFSUUID               _IOR(0x15, 0, struct fsuuid2)
+/*
+ * Returns the path component under /sys/fs/ that refers to this filesystem;
+ * also /sys/kernel/debug/ for filesystems with debugfs exports
+ */
+#define FS_IOC_GETFSSYSFSPATH          _IOR(0x15, 1, struct fs_sysfs_path)
 
 /*
  * Inode flags (FS_IOC_GETFLAGS / FS_IOC_SETFLAGS)
@@ -301,9 +326,12 @@ typedef int __bitwise __kernel_rwf_t;
 /* per-IO O_APPEND */
 #define RWF_APPEND     ((__force __kernel_rwf_t)0x00000010)
 
+/* per-IO negation of O_APPEND */
+#define RWF_NOAPPEND   ((__force __kernel_rwf_t)0x00000020)
+
 /* mask of flags supported by the kernel */
 #define RWF_SUPPORTED  (RWF_HIPRI | RWF_DSYNC | RWF_SYNC | RWF_NOWAIT |\
-                        RWF_APPEND)
+                        RWF_APPEND | RWF_NOAPPEND)
 
 /* Pagemap ioctl */
 #define PAGEMAP_SCAN   _IOWR('f', 16, struct pm_scan_arg)
index c3308536482bdb2bfb1279279325faf5430a3356..2190adbe30027cec3bd88bdf7c4366cd7c424b82 100644 (file)
 
 #define KVM_API_VERSION 12
 
+/*
+ * Backwards-compatible definitions.
+ */
+#define __KVM_HAVE_GUEST_DEBUG
+
 /* for KVM_SET_USER_MEMORY_REGION */
 struct kvm_userspace_memory_region {
        __u32 slot;
@@ -85,43 +90,6 @@ struct kvm_pit_config {
 
 #define KVM_PIT_SPEAKER_DUMMY     1
 
-struct kvm_s390_skeys {
-       __u64 start_gfn;
-       __u64 count;
-       __u64 skeydata_addr;
-       __u32 flags;
-       __u32 reserved[9];
-};
-
-#define KVM_S390_CMMA_PEEK (1 << 0)
-
-/**
- * kvm_s390_cmma_log - Used for CMMA migration.
- *
- * Used both for input and output.
- *
- * @start_gfn: Guest page number to start from.
- * @count: Size of the result buffer.
- * @flags: Control operation mode via KVM_S390_CMMA_* flags
- * @remaining: Used with KVM_S390_GET_CMMA_BITS. Indicates how many dirty
- *             pages are still remaining.
- * @mask: Used with KVM_S390_SET_CMMA_BITS. Bitmap of bits to actually set
- *        in the PGSTE.
- * @values: Pointer to the values buffer.
- *
- * Used in KVM_S390_{G,S}ET_CMMA_BITS ioctls.
- */
-struct kvm_s390_cmma_log {
-       __u64 start_gfn;
-       __u32 count;
-       __u32 flags;
-       union {
-               __u64 remaining;
-               __u64 mask;
-       };
-       __u64 values;
-};
-
 struct kvm_hyperv_exit {
 #define KVM_EXIT_HYPERV_SYNIC          1
 #define KVM_EXIT_HYPERV_HCALL          2
@@ -315,11 +283,6 @@ struct kvm_run {
                        __u32 ipb;
                } s390_sieic;
                /* KVM_EXIT_S390_RESET */
-#define KVM_S390_RESET_POR       1
-#define KVM_S390_RESET_CLEAR     2
-#define KVM_S390_RESET_SUBSYSTEM 4
-#define KVM_S390_RESET_CPU_INIT  8
-#define KVM_S390_RESET_IPL       16
                __u64 s390_reset_flags;
                /* KVM_EXIT_S390_UCONTROL */
                struct {
@@ -536,43 +499,6 @@ struct kvm_translation {
        __u8  pad[5];
 };
 
-/* for KVM_S390_MEM_OP */
-struct kvm_s390_mem_op {
-       /* in */
-       __u64 gaddr;            /* the guest address */
-       __u64 flags;            /* flags */
-       __u32 size;             /* amount of bytes */
-       __u32 op;               /* type of operation */
-       __u64 buf;              /* buffer in userspace */
-       union {
-               struct {
-                       __u8 ar;        /* the access register number */
-                       __u8 key;       /* access key, ignored if flag unset */
-                       __u8 pad1[6];   /* ignored */
-                       __u64 old_addr; /* ignored if cmpxchg flag unset */
-               };
-               __u32 sida_offset; /* offset into the sida */
-               __u8 reserved[32]; /* ignored */
-       };
-};
-/* types for kvm_s390_mem_op->op */
-#define KVM_S390_MEMOP_LOGICAL_READ    0
-#define KVM_S390_MEMOP_LOGICAL_WRITE   1
-#define KVM_S390_MEMOP_SIDA_READ       2
-#define KVM_S390_MEMOP_SIDA_WRITE      3
-#define KVM_S390_MEMOP_ABSOLUTE_READ   4
-#define KVM_S390_MEMOP_ABSOLUTE_WRITE  5
-#define KVM_S390_MEMOP_ABSOLUTE_CMPXCHG        6
-
-/* flags for kvm_s390_mem_op->flags */
-#define KVM_S390_MEMOP_F_CHECK_ONLY            (1ULL << 0)
-#define KVM_S390_MEMOP_F_INJECT_EXCEPTION      (1ULL << 1)
-#define KVM_S390_MEMOP_F_SKEY_PROTECTION       (1ULL << 2)
-
-/* flags specifying extension support via KVM_CAP_S390_MEM_OP_EXTENSION */
-#define KVM_S390_MEMOP_EXTENSION_CAP_BASE      (1 << 0)
-#define KVM_S390_MEMOP_EXTENSION_CAP_CMPXCHG   (1 << 1)
-
 /* for KVM_INTERRUPT */
 struct kvm_interrupt {
        /* in */
@@ -637,124 +563,6 @@ struct kvm_mp_state {
        __u32 mp_state;
 };
 
-struct kvm_s390_psw {
-       __u64 mask;
-       __u64 addr;
-};
-
-/* valid values for type in kvm_s390_interrupt */
-#define KVM_S390_SIGP_STOP             0xfffe0000u
-#define KVM_S390_PROGRAM_INT           0xfffe0001u
-#define KVM_S390_SIGP_SET_PREFIX       0xfffe0002u
-#define KVM_S390_RESTART               0xfffe0003u
-#define KVM_S390_INT_PFAULT_INIT       0xfffe0004u
-#define KVM_S390_INT_PFAULT_DONE       0xfffe0005u
-#define KVM_S390_MCHK                  0xfffe1000u
-#define KVM_S390_INT_CLOCK_COMP                0xffff1004u
-#define KVM_S390_INT_CPU_TIMER         0xffff1005u
-#define KVM_S390_INT_VIRTIO            0xffff2603u
-#define KVM_S390_INT_SERVICE           0xffff2401u
-#define KVM_S390_INT_EMERGENCY         0xffff1201u
-#define KVM_S390_INT_EXTERNAL_CALL     0xffff1202u
-/* Anything below 0xfffe0000u is taken by INT_IO */
-#define KVM_S390_INT_IO(ai,cssid,ssid,schid)   \
-       (((schid)) |                           \
-        ((ssid) << 16) |                      \
-        ((cssid) << 18) |                     \
-        ((ai) << 26))
-#define KVM_S390_INT_IO_MIN            0x00000000u
-#define KVM_S390_INT_IO_MAX            0xfffdffffu
-#define KVM_S390_INT_IO_AI_MASK                0x04000000u
-
-
-struct kvm_s390_interrupt {
-       __u32 type;
-       __u32 parm;
-       __u64 parm64;
-};
-
-struct kvm_s390_io_info {
-       __u16 subchannel_id;
-       __u16 subchannel_nr;
-       __u32 io_int_parm;
-       __u32 io_int_word;
-};
-
-struct kvm_s390_ext_info {
-       __u32 ext_params;
-       __u32 pad;
-       __u64 ext_params2;
-};
-
-struct kvm_s390_pgm_info {
-       __u64 trans_exc_code;
-       __u64 mon_code;
-       __u64 per_address;
-       __u32 data_exc_code;
-       __u16 code;
-       __u16 mon_class_nr;
-       __u8 per_code;
-       __u8 per_atmid;
-       __u8 exc_access_id;
-       __u8 per_access_id;
-       __u8 op_access_id;
-#define KVM_S390_PGM_FLAGS_ILC_VALID   0x01
-#define KVM_S390_PGM_FLAGS_ILC_0       0x02
-#define KVM_S390_PGM_FLAGS_ILC_1       0x04
-#define KVM_S390_PGM_FLAGS_ILC_MASK    0x06
-#define KVM_S390_PGM_FLAGS_NO_REWIND   0x08
-       __u8 flags;
-       __u8 pad[2];
-};
-
-struct kvm_s390_prefix_info {
-       __u32 address;
-};
-
-struct kvm_s390_extcall_info {
-       __u16 code;
-};
-
-struct kvm_s390_emerg_info {
-       __u16 code;
-};
-
-#define KVM_S390_STOP_FLAG_STORE_STATUS        0x01
-struct kvm_s390_stop_info {
-       __u32 flags;
-};
-
-struct kvm_s390_mchk_info {
-       __u64 cr14;
-       __u64 mcic;
-       __u64 failing_storage_address;
-       __u32 ext_damage_code;
-       __u32 pad;
-       __u8 fixed_logout[16];
-};
-
-struct kvm_s390_irq {
-       __u64 type;
-       union {
-               struct kvm_s390_io_info io;
-               struct kvm_s390_ext_info ext;
-               struct kvm_s390_pgm_info pgm;
-               struct kvm_s390_emerg_info emerg;
-               struct kvm_s390_extcall_info extcall;
-               struct kvm_s390_prefix_info prefix;
-               struct kvm_s390_stop_info stop;
-               struct kvm_s390_mchk_info mchk;
-               char reserved[64];
-       } u;
-};
-
-struct kvm_s390_irq_state {
-       __u64 buf;
-       __u32 flags;        /* will stay unused for compatibility reasons */
-       __u32 len;
-       __u32 reserved[4];  /* will stay unused for compatibility reasons */
-};
-
 /* for KVM_SET_GUEST_DEBUG */
 
 #define KVM_GUESTDBG_ENABLE            0x00000001
@@ -810,50 +618,6 @@ struct kvm_enable_cap {
        __u8  pad[64];
 };
 
-/* for KVM_PPC_GET_PVINFO */
-
-#define KVM_PPC_PVINFO_FLAGS_EV_IDLE   (1<<0)
-
-struct kvm_ppc_pvinfo {
-       /* out */
-       __u32 flags;
-       __u32 hcall[4];
-       __u8  pad[108];
-};
-
-/* for KVM_PPC_GET_SMMU_INFO */
-#define KVM_PPC_PAGE_SIZES_MAX_SZ      8
-
-struct kvm_ppc_one_page_size {
-       __u32 page_shift;       /* Page shift (or 0) */
-       __u32 pte_enc;          /* Encoding in the HPTE (>>12) */
-};
-
-struct kvm_ppc_one_seg_page_size {
-       __u32 page_shift;       /* Base page shift of segment (or 0) */
-       __u32 slb_enc;          /* SLB encoding for BookS */
-       struct kvm_ppc_one_page_size enc[KVM_PPC_PAGE_SIZES_MAX_SZ];
-};
-
-#define KVM_PPC_PAGE_SIZES_REAL                0x00000001
-#define KVM_PPC_1T_SEGMENTS            0x00000002
-#define KVM_PPC_NO_HASH                        0x00000004
-
-struct kvm_ppc_smmu_info {
-       __u64 flags;
-       __u32 slb_size;
-       __u16 data_keys;        /* # storage keys supported for data */
-       __u16 instr_keys;       /* # storage keys supported for instructions */
-       struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
-};
-
-/* for KVM_PPC_RESIZE_HPT_{PREPARE,COMMIT} */
-struct kvm_ppc_resize_hpt {
-       __u64 flags;
-       __u32 shift;
-       __u32 pad;
-};
-
 #define KVMIO 0xAE
 
 /* machine type bits, to be used as argument to KVM_CREATE_VM */
@@ -923,9 +687,7 @@ struct kvm_ppc_resize_hpt {
 /* Bug in KVM_SET_USER_MEMORY_REGION fixed: */
 #define KVM_CAP_DESTROY_MEMORY_REGION_WORKS 21
 #define KVM_CAP_USER_NMI 22
-#ifdef __KVM_HAVE_GUEST_DEBUG
 #define KVM_CAP_SET_GUEST_DEBUG 23
-#endif
 #ifdef __KVM_HAVE_PIT
 #define KVM_CAP_REINJECT_CONTROL 24
 #endif
@@ -1156,8 +918,6 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_GUEST_MEMFD 234
 #define KVM_CAP_VM_TYPES 235
 
-#ifdef KVM_CAP_IRQ_ROUTING
-
 struct kvm_irq_routing_irqchip {
        __u32 irqchip;
        __u32 pin;
@@ -1222,42 +982,6 @@ struct kvm_irq_routing {
        struct kvm_irq_routing_entry entries[];
 };
 
-#endif
-
-#ifdef KVM_CAP_MCE
-/* x86 MCE */
-struct kvm_x86_mce {
-       __u64 status;
-       __u64 addr;
-       __u64 misc;
-       __u64 mcg_status;
-       __u8 bank;
-       __u8 pad1[7];
-       __u64 pad2[3];
-};
-#endif
-
-#ifdef KVM_CAP_XEN_HVM
-#define KVM_XEN_HVM_CONFIG_HYPERCALL_MSR       (1 << 0)
-#define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL     (1 << 1)
-#define KVM_XEN_HVM_CONFIG_SHARED_INFO         (1 << 2)
-#define KVM_XEN_HVM_CONFIG_RUNSTATE            (1 << 3)
-#define KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL       (1 << 4)
-#define KVM_XEN_HVM_CONFIG_EVTCHN_SEND         (1 << 5)
-#define KVM_XEN_HVM_CONFIG_RUNSTATE_UPDATE_FLAG        (1 << 6)
-#define KVM_XEN_HVM_CONFIG_PVCLOCK_TSC_UNSTABLE        (1 << 7)
-
-struct kvm_xen_hvm_config {
-       __u32 flags;
-       __u32 msr;
-       __u64 blob_addr_32;
-       __u64 blob_addr_64;
-       __u8 blob_size_32;
-       __u8 blob_size_64;
-       __u8 pad2[30];
-};
-#endif
-
 #define KVM_IRQFD_FLAG_DEASSIGN (1 << 0)
 /*
  * Available with KVM_CAP_IRQFD_RESAMPLE
@@ -1442,11 +1166,6 @@ struct kvm_vfio_spapr_tce {
                                         struct kvm_userspace_memory_region2)
 
 /* enable ucontrol for s390 */
-struct kvm_s390_ucas_mapping {
-       __u64 user_addr;
-       __u64 vcpu_addr;
-       __u64 length;
-};
 #define KVM_S390_UCAS_MAP        _IOW(KVMIO, 0x50, struct kvm_s390_ucas_mapping)
 #define KVM_S390_UCAS_UNMAP      _IOW(KVMIO, 0x51, struct kvm_s390_ucas_mapping)
 #define KVM_S390_VCPU_FAULT     _IOW(KVMIO, 0x52, unsigned long)
@@ -1641,89 +1360,6 @@ struct kvm_enc_region {
 #define KVM_S390_NORMAL_RESET  _IO(KVMIO,   0xc3)
 #define KVM_S390_CLEAR_RESET   _IO(KVMIO,   0xc4)
 
-struct kvm_s390_pv_sec_parm {
-       __u64 origin;
-       __u64 length;
-};
-
-struct kvm_s390_pv_unp {
-       __u64 addr;
-       __u64 size;
-       __u64 tweak;
-};
-
-enum pv_cmd_dmp_id {
-       KVM_PV_DUMP_INIT,
-       KVM_PV_DUMP_CONFIG_STOR_STATE,
-       KVM_PV_DUMP_COMPLETE,
-       KVM_PV_DUMP_CPU,
-};
-
-struct kvm_s390_pv_dmp {
-       __u64 subcmd;
-       __u64 buff_addr;
-       __u64 buff_len;
-       __u64 gaddr;            /* For dump storage state */
-       __u64 reserved[4];
-};
-
-enum pv_cmd_info_id {
-       KVM_PV_INFO_VM,
-       KVM_PV_INFO_DUMP,
-};
-
-struct kvm_s390_pv_info_dump {
-       __u64 dump_cpu_buffer_len;
-       __u64 dump_config_mem_buffer_per_1m;
-       __u64 dump_config_finalize_len;
-};
-
-struct kvm_s390_pv_info_vm {
-       __u64 inst_calls_list[4];
-       __u64 max_cpus;
-       __u64 max_guests;
-       __u64 max_guest_addr;
-       __u64 feature_indication;
-};
-
-struct kvm_s390_pv_info_header {
-       __u32 id;
-       __u32 len_max;
-       __u32 len_written;
-       __u32 reserved;
-};
-
-struct kvm_s390_pv_info {
-       struct kvm_s390_pv_info_header header;
-       union {
-               struct kvm_s390_pv_info_dump dump;
-               struct kvm_s390_pv_info_vm vm;
-       };
-};
-
-enum pv_cmd_id {
-       KVM_PV_ENABLE,
-       KVM_PV_DISABLE,
-       KVM_PV_SET_SEC_PARMS,
-       KVM_PV_UNPACK,
-       KVM_PV_VERIFY,
-       KVM_PV_PREP_RESET,
-       KVM_PV_UNSHARE_ALL,
-       KVM_PV_INFO,
-       KVM_PV_DUMP,
-       KVM_PV_ASYNC_CLEANUP_PREPARE,
-       KVM_PV_ASYNC_CLEANUP_PERFORM,
-};
-
-struct kvm_pv_cmd {
-       __u32 cmd;      /* Command to be executed */
-       __u16 rc;       /* Ultravisor return code */
-       __u16 rrc;      /* Ultravisor return reason code */
-       __u64 data;     /* Data or address */
-       __u32 flags;    /* flags for future extensions. Must be 0 for now */
-       __u32 reserved[3];
-};
-
 /* Available with KVM_CAP_S390_PROTECTED */
 #define KVM_S390_PV_COMMAND            _IOWR(KVMIO, 0xc5, struct kvm_pv_cmd)
 
@@ -1737,58 +1373,6 @@ struct kvm_pv_cmd {
 #define KVM_XEN_HVM_GET_ATTR   _IOWR(KVMIO, 0xc8, struct kvm_xen_hvm_attr)
 #define KVM_XEN_HVM_SET_ATTR   _IOW(KVMIO,  0xc9, struct kvm_xen_hvm_attr)
 
-struct kvm_xen_hvm_attr {
-       __u16 type;
-       __u16 pad[3];
-       union {
-               __u8 long_mode;
-               __u8 vector;
-               __u8 runstate_update_flag;
-               struct {
-                       __u64 gfn;
-#define KVM_XEN_INVALID_GFN ((__u64)-1)
-               } shared_info;
-               struct {
-                       __u32 send_port;
-                       __u32 type; /* EVTCHNSTAT_ipi / EVTCHNSTAT_interdomain */
-                       __u32 flags;
-#define KVM_XEN_EVTCHN_DEASSIGN                (1 << 0)
-#define KVM_XEN_EVTCHN_UPDATE          (1 << 1)
-#define KVM_XEN_EVTCHN_RESET           (1 << 2)
-                       /*
-                        * Events sent by the guest are either looped back to
-                        * the guest itself (potentially on a different port#)
-                        * or signalled via an eventfd.
-                        */
-                       union {
-                               struct {
-                                       __u32 port;
-                                       __u32 vcpu;
-                                       __u32 priority;
-                               } port;
-                               struct {
-                                       __u32 port; /* Zero for eventfd */
-                                       __s32 fd;
-                               } eventfd;
-                               __u32 padding[4];
-                       } deliver;
-               } evtchn;
-               __u32 xen_version;
-               __u64 pad[8];
-       } u;
-};
-
-
-/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO */
-#define KVM_XEN_ATTR_TYPE_LONG_MODE            0x0
-#define KVM_XEN_ATTR_TYPE_SHARED_INFO          0x1
-#define KVM_XEN_ATTR_TYPE_UPCALL_VECTOR                0x2
-/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_EVTCHN_SEND */
-#define KVM_XEN_ATTR_TYPE_EVTCHN               0x3
-#define KVM_XEN_ATTR_TYPE_XEN_VERSION          0x4
-/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_RUNSTATE_UPDATE_FLAG */
-#define KVM_XEN_ATTR_TYPE_RUNSTATE_UPDATE_FLAG 0x5
-
 /* Per-vCPU Xen attributes */
 #define KVM_XEN_VCPU_GET_ATTR  _IOWR(KVMIO, 0xca, struct kvm_xen_vcpu_attr)
 #define KVM_XEN_VCPU_SET_ATTR  _IOW(KVMIO,  0xcb, struct kvm_xen_vcpu_attr)
@@ -1799,242 +1383,6 @@ struct kvm_xen_hvm_attr {
 #define KVM_GET_SREGS2             _IOR(KVMIO,  0xcc, struct kvm_sregs2)
 #define KVM_SET_SREGS2             _IOW(KVMIO,  0xcd, struct kvm_sregs2)
 
-struct kvm_xen_vcpu_attr {
-       __u16 type;
-       __u16 pad[3];
-       union {
-               __u64 gpa;
-#define KVM_XEN_INVALID_GPA ((__u64)-1)
-               __u64 pad[8];
-               struct {
-                       __u64 state;
-                       __u64 state_entry_time;
-                       __u64 time_running;
-                       __u64 time_runnable;
-                       __u64 time_blocked;
-                       __u64 time_offline;
-               } runstate;
-               __u32 vcpu_id;
-               struct {
-                       __u32 port;
-                       __u32 priority;
-                       __u64 expires_ns;
-               } timer;
-               __u8 vector;
-       } u;
-};
-
-/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO */
-#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO       0x0
-#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO  0x1
-#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADDR   0x2
-#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_CURRENT        0x3
-#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_DATA   0x4
-#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST 0x5
-/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_EVTCHN_SEND */
-#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_ID         0x6
-#define KVM_XEN_VCPU_ATTR_TYPE_TIMER           0x7
-#define KVM_XEN_VCPU_ATTR_TYPE_UPCALL_VECTOR   0x8
-
-/* Secure Encrypted Virtualization command */
-enum sev_cmd_id {
-       /* Guest initialization commands */
-       KVM_SEV_INIT = 0,
-       KVM_SEV_ES_INIT,
-       /* Guest launch commands */
-       KVM_SEV_LAUNCH_START,
-       KVM_SEV_LAUNCH_UPDATE_DATA,
-       KVM_SEV_LAUNCH_UPDATE_VMSA,
-       KVM_SEV_LAUNCH_SECRET,
-       KVM_SEV_LAUNCH_MEASURE,
-       KVM_SEV_LAUNCH_FINISH,
-       /* Guest migration commands (outgoing) */
-       KVM_SEV_SEND_START,
-       KVM_SEV_SEND_UPDATE_DATA,
-       KVM_SEV_SEND_UPDATE_VMSA,
-       KVM_SEV_SEND_FINISH,
-       /* Guest migration commands (incoming) */
-       KVM_SEV_RECEIVE_START,
-       KVM_SEV_RECEIVE_UPDATE_DATA,
-       KVM_SEV_RECEIVE_UPDATE_VMSA,
-       KVM_SEV_RECEIVE_FINISH,
-       /* Guest status and debug commands */
-       KVM_SEV_GUEST_STATUS,
-       KVM_SEV_DBG_DECRYPT,
-       KVM_SEV_DBG_ENCRYPT,
-       /* Guest certificates commands */
-       KVM_SEV_CERT_EXPORT,
-       /* Attestation report */
-       KVM_SEV_GET_ATTESTATION_REPORT,
-       /* Guest Migration Extension */
-       KVM_SEV_SEND_CANCEL,
-
-       KVM_SEV_NR_MAX,
-};
-
-struct kvm_sev_cmd {
-       __u32 id;
-       __u64 data;
-       __u32 error;
-       __u32 sev_fd;
-};
-
-struct kvm_sev_launch_start {
-       __u32 handle;
-       __u32 policy;
-       __u64 dh_uaddr;
-       __u32 dh_len;
-       __u64 session_uaddr;
-       __u32 session_len;
-};
-
-struct kvm_sev_launch_update_data {
-       __u64 uaddr;
-       __u32 len;
-};
-
-
-struct kvm_sev_launch_secret {
-       __u64 hdr_uaddr;
-       __u32 hdr_len;
-       __u64 guest_uaddr;
-       __u32 guest_len;
-       __u64 trans_uaddr;
-       __u32 trans_len;
-};
-
-struct kvm_sev_launch_measure {
-       __u64 uaddr;
-       __u32 len;
-};
-
-struct kvm_sev_guest_status {
-       __u32 handle;
-       __u32 policy;
-       __u32 state;
-};
-
-struct kvm_sev_dbg {
-       __u64 src_uaddr;
-       __u64 dst_uaddr;
-       __u32 len;
-};
-
-struct kvm_sev_attestation_report {
-       __u8 mnonce[16];
-       __u64 uaddr;
-       __u32 len;
-};
-
-struct kvm_sev_send_start {
-       __u32 policy;
-       __u64 pdh_cert_uaddr;
-       __u32 pdh_cert_len;
-       __u64 plat_certs_uaddr;
-       __u32 plat_certs_len;
-       __u64 amd_certs_uaddr;
-       __u32 amd_certs_len;
-       __u64 session_uaddr;
-       __u32 session_len;
-};
-
-struct kvm_sev_send_update_data {
-       __u64 hdr_uaddr;
-       __u32 hdr_len;
-       __u64 guest_uaddr;
-       __u32 guest_len;
-       __u64 trans_uaddr;
-       __u32 trans_len;
-};
-
-struct kvm_sev_receive_start {
-       __u32 handle;
-       __u32 policy;
-       __u64 pdh_uaddr;
-       __u32 pdh_len;
-       __u64 session_uaddr;
-       __u32 session_len;
-};
-
-struct kvm_sev_receive_update_data {
-       __u64 hdr_uaddr;
-       __u32 hdr_len;
-       __u64 guest_uaddr;
-       __u32 guest_len;
-       __u64 trans_uaddr;
-       __u32 trans_len;
-};
-
-#define KVM_DEV_ASSIGN_ENABLE_IOMMU    (1 << 0)
-#define KVM_DEV_ASSIGN_PCI_2_3         (1 << 1)
-#define KVM_DEV_ASSIGN_MASK_INTX       (1 << 2)
-
-struct kvm_assigned_pci_dev {
-       __u32 assigned_dev_id;
-       __u32 busnr;
-       __u32 devfn;
-       __u32 flags;
-       __u32 segnr;
-       union {
-               __u32 reserved[11];
-       };
-};
-
-#define KVM_DEV_IRQ_HOST_INTX    (1 << 0)
-#define KVM_DEV_IRQ_HOST_MSI     (1 << 1)
-#define KVM_DEV_IRQ_HOST_MSIX    (1 << 2)
-
-#define KVM_DEV_IRQ_GUEST_INTX   (1 << 8)
-#define KVM_DEV_IRQ_GUEST_MSI    (1 << 9)
-#define KVM_DEV_IRQ_GUEST_MSIX   (1 << 10)
-
-#define KVM_DEV_IRQ_HOST_MASK   0x00ff
-#define KVM_DEV_IRQ_GUEST_MASK   0xff00
-
-struct kvm_assigned_irq {
-       __u32 assigned_dev_id;
-       __u32 host_irq; /* ignored (legacy field) */
-       __u32 guest_irq;
-       __u32 flags;
-       union {
-               __u32 reserved[12];
-       };
-};
-
-struct kvm_assigned_msix_nr {
-       __u32 assigned_dev_id;
-       __u16 entry_nr;
-       __u16 padding;
-};
-
-#define KVM_MAX_MSIX_PER_DEV           256
-struct kvm_assigned_msix_entry {
-       __u32 assigned_dev_id;
-       __u32 gsi;
-       __u16 entry; /* The index of entry in the MSI-X table */
-       __u16 padding[3];
-};
-
-#define KVM_X2APIC_API_USE_32BIT_IDS            (1ULL << 0)
-#define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK  (1ULL << 1)
-
-/* Available with KVM_CAP_ARM_USER_IRQ */
-
-/* Bits for run->s.regs.device_irq_level */
-#define KVM_ARM_DEV_EL1_VTIMER         (1 << 0)
-#define KVM_ARM_DEV_EL1_PTIMER         (1 << 1)
-#define KVM_ARM_DEV_PMU                        (1 << 2)
-
-struct kvm_hyperv_eventfd {
-       __u32 conn_id;
-       __s32 fd;
-       __u32 flags;
-       __u32 padding[3];
-};
-
-#define KVM_HYPERV_CONN_ID_MASK                0x00ffffff
-#define KVM_HYPERV_EVENTFD_DEASSIGN    (1 << 0)
-
 #define KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE    (1 << 0)
 #define KVM_DIRTY_LOG_INITIALLY_SET            (1 << 1)
 
@@ -2180,33 +1528,6 @@ struct kvm_stats_desc {
 /* Available with KVM_CAP_S390_ZPCI_OP */
 #define KVM_S390_ZPCI_OP         _IOW(KVMIO,  0xd1, struct kvm_s390_zpci_op)
 
-struct kvm_s390_zpci_op {
-       /* in */
-       __u32 fh;               /* target device */
-       __u8  op;               /* operation to perform */
-       __u8  pad[3];
-       union {
-               /* for KVM_S390_ZPCIOP_REG_AEN */
-               struct {
-                       __u64 ibv;      /* Guest addr of interrupt bit vector */
-                       __u64 sb;       /* Guest addr of summary bit */
-                       __u32 flags;
-                       __u32 noi;      /* Number of interrupts */
-                       __u8 isc;       /* Guest interrupt subclass */
-                       __u8 sbo;       /* Offset of guest summary bit vector */
-                       __u16 pad;
-               } reg_aen;
-               __u64 reserved[8];
-       } u;
-};
-
-/* types for kvm_s390_zpci_op->op */
-#define KVM_S390_ZPCIOP_REG_AEN                0
-#define KVM_S390_ZPCIOP_DEREG_AEN      1
-
-/* flags for kvm_s390_zpci_op->u.reg_aen.flags */
-#define KVM_S390_ZPCIOP_REGAEN_HOST    (1 << 0)
-
 /* Available with KVM_CAP_MEMORY_ATTRIBUTES */
 #define KVM_SET_MEMORY_ATTRIBUTES              _IOW(KVMIO,  0xd2, struct kvm_memory_attributes)
 
index d5b9cfbd9ceac69323d0fe487cc49ab388a2e523..628d46a0da92eb0393dd592a38e987d08dcf6db0 100644 (file)
@@ -142,7 +142,7 @@ struct snd_hwdep_dsp_image {
  *                                                                           *
  *****************************************************************************/
 
-#define SNDRV_PCM_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 16)
+#define SNDRV_PCM_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 17)
 
 typedef unsigned long snd_pcm_uframes_t;
 typedef signed long snd_pcm_sframes_t;
@@ -416,7 +416,7 @@ struct snd_pcm_hw_params {
        unsigned int rmask;             /* W: requested masks */
        unsigned int cmask;             /* R: changed masks */
        unsigned int info;              /* R: Info flags for returned setup */
-       unsigned int msbits;            /* R: used most significant bits */
+       unsigned int msbits;            /* R: used most significant bits (in sample bit-width) */
        unsigned int rate_num;          /* R: rate numerator */
        unsigned int rate_den;          /* R: rate denominator */
        snd_pcm_uframes_t fifo_size;    /* R: chip FIFO size in frames */
index ec5e21932876038b99afbfa30560d856efd8afd5..4790c735599bdd97b62a39edd861230464abc5d8 100644 (file)
@@ -970,7 +970,7 @@ int symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel,
        if (dso->annotate_warned)
                return -1;
 
-       if (not_annotated) {
+       if (not_annotated || !sym->annotate2) {
                err = symbol__annotate2(ms, evsel, &browser.arch);
                if (err) {
                        char msg[BUFSIZ];
index ac002d907d81801c941876731e29acfc8dcf97b3..50ca92255ff62a61e2923179c1e7f4fb7e98ded5 100644 (file)
@@ -2461,6 +2461,9 @@ int symbol__annotate(struct map_symbol *ms, struct evsel *evsel,
        if (parch)
                *parch = arch;
 
+       if (!list_empty(&notes->src->source))
+               return 0;
+
        args.arch = arch;
        args.ms = *ms;
        if (annotate_opts.full_addr)
index fb54bd38e7d0947cd1e1acef59977d46b0082028..d931a898c434be0d430759db9e2c8572dcdb65b5 100644 (file)
@@ -284,6 +284,7 @@ static inline __u32 check_lock_type(__u64 lock, __u32 flags)
        struct task_struct *curr;
        struct mm_struct___old *mm_old;
        struct mm_struct___new *mm_new;
+       struct sighand_struct *sighand;
 
        switch (flags) {
        case LCB_F_READ:  /* rwsem */
@@ -305,7 +306,9 @@ static inline __u32 check_lock_type(__u64 lock, __u32 flags)
                break;
        case LCB_F_SPIN:  /* spinlock */
                curr = bpf_get_current_task_btf();
-               if (&curr->sighand->siglock == (void *)lock)
+               sighand = curr->sighand;
+
+               if (sighand && &sighand->siglock == (void *)lock)
                        return LCD_F_SIGHAND_LOCK;
                break;
        default:
index b1ede624986676a554514105936698fdd2b0a915..b7c8f29c09a978895c1176e1a39aeda8c97e8416 100644 (file)
@@ -18,7 +18,7 @@ echo 'sched:*' > set_event
 
 yield
 
-count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
+count=`head -n 100 trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
 if [ $count -lt 3 ]; then
     fail "at least fork, exec and exit events should be recorded"
 fi
@@ -29,7 +29,7 @@ echo 1 > events/sched/enable
 
 yield
 
-count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
+count=`head -n 100 trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
 if [ $count -lt 3 ]; then
     fail "at least fork, exec and exit events should be recorded"
 fi
@@ -40,7 +40,7 @@ echo 0 > events/sched/enable
 
 yield
 
-count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
+count=`head -n 100 trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
 if [ $count -ne 0 ]; then
     fail "any of scheduler events should not be recorded"
 fi
index 110d73917615d177d5d7a891f08d523619c404f3..02a2a1b267c1eae76f24011c64f9a0759d55032f 100644 (file)
@@ -1,3 +1,5 @@
 CONFIG_IOMMUFD=y
+CONFIG_FAULT_INJECTION_DEBUG_FS=y
 CONFIG_FAULT_INJECTION=y
 CONFIG_IOMMUFD_TEST=y
+CONFIG_FAILSLAB=y
index 7b89362da4bfd384efe49681451c276ecd78ee16..14bbab0cce13521abbcae9bbd3772a567239c77f 100644 (file)
@@ -292,15 +292,17 @@ void ksft_test_result_code(int exit_code, const char *test_name,
        }
 
        /* Docs seem to call for double space if directive is absent */
-       if (!directive[0] && msg[0])
+       if (!directive[0] && msg)
                directive = " #  ";
 
-       va_start(args, msg);
        printf("%s %u %s%s", tap_code, ksft_test_num(), test_name, directive);
        errno = saved_errno;
-       vprintf(msg, args);
+       if (msg) {
+               va_start(args, msg);
+               vprintf(msg, args);
+               va_end(args);
+       }
        printf("\n");
-       va_end(args);
 }
 
 static inline __noreturn int ksft_exit_pass(void)
index 4fd735e48ee7eea99702fcb3e27f539c887b15bc..ba3ddeda24bf527295acaf32159097c03ac52153 100644 (file)
                FIXTURE_DATA(fixture_name) self; \
                pid_t child = 1; \
                int status = 0; \
+               bool jmp = false; \
                memset(&self, 0, sizeof(FIXTURE_DATA(fixture_name))); \
                if (setjmp(_metadata->env) == 0) { \
                        /* Use the same _metadata. */ \
                                _metadata->exit_code = KSFT_FAIL; \
                        } \
                } \
+               else \
+                       jmp = true; \
                if (child == 0) { \
-                       if (_metadata->setup_completed && !_metadata->teardown_parent) \
+                       if (_metadata->setup_completed && !_metadata->teardown_parent && !jmp) \
                                fixture_name##_teardown(_metadata, &self, variant->data); \
                        _exit(0); \
                } \
@@ -1202,7 +1205,7 @@ void __run_test(struct __fixture_metadata *f,
                diagnostic = "unknown";
 
        ksft_test_result_code(t->exit_code, test_name,
-                             diagnostic ? "%s" : "", diagnostic);
+                             diagnostic ? "%s" : NULL, diagnostic);
 }
 
 static int test_harness_run(int argc, char **argv)
index 6628dc4dda89f3c12cefa7a459aed11687b91799..1a6da7389bf1f5b2d24295e6aed85ced77506349 100644 (file)
@@ -22,10 +22,11 @@ static void guest_code(uint64_t start_gpa, uint64_t end_gpa, uint64_t stride)
 {
        uint64_t gpa;
 
-       for (gpa = start_gpa; gpa < end_gpa; gpa += stride)
-               *((volatile uint64_t *)gpa) = gpa;
-
-       GUEST_DONE();
+       for (;;) {
+               for (gpa = start_gpa; gpa < end_gpa; gpa += stride)
+                       *((volatile uint64_t *)gpa) = gpa;
+               GUEST_SYNC(0);
+       }
 }
 
 struct vcpu_info {
@@ -55,7 +56,7 @@ static void rendezvous_with_boss(void)
 static void run_vcpu(struct kvm_vcpu *vcpu)
 {
        vcpu_run(vcpu);
-       TEST_ASSERT_EQ(get_ucall(vcpu, NULL), UCALL_DONE);
+       TEST_ASSERT_EQ(get_ucall(vcpu, NULL), UCALL_SYNC);
 }
 
 static void *vcpu_worker(void *data)
@@ -64,17 +65,13 @@ static void *vcpu_worker(void *data)
        struct kvm_vcpu *vcpu = info->vcpu;
        struct kvm_vm *vm = vcpu->vm;
        struct kvm_sregs sregs;
-       struct kvm_regs regs;
 
        vcpu_args_set(vcpu, 3, info->start_gpa, info->end_gpa, vm->page_size);
 
-       /* Snapshot regs before the first run. */
-       vcpu_regs_get(vcpu, &regs);
        rendezvous_with_boss();
 
        run_vcpu(vcpu);
        rendezvous_with_boss();
-       vcpu_regs_set(vcpu, &regs);
        vcpu_sregs_get(vcpu, &sregs);
 #ifdef __x86_64__
        /* Toggle CR0.WP to trigger a MMU context reset. */
index 06b43ed23580b67c060aeaadea11b06641a629c3..bd57d991e27d85acca0cd570981e240ed9f45e87 100644 (file)
@@ -333,7 +333,7 @@ static void test_invalid_memory_region_flags(void)
        struct kvm_vm *vm;
        int r, i;
 
-#if defined __aarch64__ || defined __x86_64__
+#if defined __aarch64__ || defined __riscv || defined __x86_64__
        supported_flags |= KVM_MEM_READONLY;
 #endif
 
index 29609b52f8fa0c58bfb38207ef29bf6283f43932..26c85815f7e983a33c025aa1daab6daa45c0f91b 100644 (file)
@@ -416,12 +416,30 @@ static void guest_rd_wr_counters(uint32_t base_msr, uint8_t nr_possible_counters
 
 static void guest_test_gp_counters(void)
 {
+       uint8_t pmu_version = guest_get_pmu_version();
        uint8_t nr_gp_counters = 0;
        uint32_t base_msr;
 
-       if (guest_get_pmu_version())
+       if (pmu_version)
                nr_gp_counters = this_cpu_property(X86_PROPERTY_PMU_NR_GP_COUNTERS);
 
+       /*
+        * For v2+ PMUs, PERF_GLOBAL_CTRL's architectural post-RESET value is
+        * "Sets bits n-1:0 and clears the upper bits", where 'n' is the number
+        * of GP counters.  If there are no GP counters, require KVM to leave
+        * PERF_GLOBAL_CTRL '0'.  This edge case isn't covered by the SDM, but
+        * follow the spirit of the architecture and only globally enable GP
+        * counters, of which there are none.
+        */
+       if (pmu_version > 1) {
+               uint64_t global_ctrl = rdmsr(MSR_CORE_PERF_GLOBAL_CTRL);
+
+               if (nr_gp_counters)
+                       GUEST_ASSERT_EQ(global_ctrl, GENMASK_ULL(nr_gp_counters - 1, 0));
+               else
+                       GUEST_ASSERT_EQ(global_ctrl, 0);
+       }
+
        if (this_cpu_has(X86_FEATURE_PDCM) &&
            rdmsr(MSR_IA32_PERF_CAPABILITIES) & PMU_CAP_FW_WRITES)
                base_msr = MSR_IA32_PMC0;
index 7f6f5f23fb9b67fcb186a0e9c9ad00aaced6d2d3..977948fd52e6b8cf7e71dfa84874d5e8af7d9c09 100644 (file)
 #define NESTED_TEST_MEM1               0xc0001000
 #define NESTED_TEST_MEM2               0xc0002000
 
-static void l2_guest_code(void)
+static void l2_guest_code(u64 *a, u64 *b)
 {
-       *(volatile uint64_t *)NESTED_TEST_MEM1;
-       *(volatile uint64_t *)NESTED_TEST_MEM1 = 1;
+       READ_ONCE(*a);
+       WRITE_ONCE(*a, 1);
        GUEST_SYNC(true);
        GUEST_SYNC(false);
 
-       *(volatile uint64_t *)NESTED_TEST_MEM2 = 1;
+       WRITE_ONCE(*b, 1);
        GUEST_SYNC(true);
-       *(volatile uint64_t *)NESTED_TEST_MEM2 = 1;
+       WRITE_ONCE(*b, 1);
        GUEST_SYNC(true);
        GUEST_SYNC(false);
 
@@ -45,17 +45,33 @@ static void l2_guest_code(void)
        vmcall();
 }
 
+static void l2_guest_code_ept_enabled(void)
+{
+       l2_guest_code((u64 *)NESTED_TEST_MEM1, (u64 *)NESTED_TEST_MEM2);
+}
+
+static void l2_guest_code_ept_disabled(void)
+{
+       /* Access the same L1 GPAs as l2_guest_code_ept_enabled() */
+       l2_guest_code((u64 *)GUEST_TEST_MEM, (u64 *)GUEST_TEST_MEM);
+}
+
 void l1_guest_code(struct vmx_pages *vmx)
 {
 #define L2_GUEST_STACK_SIZE 64
        unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE];
+       void *l2_rip;
 
        GUEST_ASSERT(vmx->vmcs_gpa);
        GUEST_ASSERT(prepare_for_vmx_operation(vmx));
        GUEST_ASSERT(load_vmcs(vmx));
 
-       prepare_vmcs(vmx, l2_guest_code,
-                    &l2_guest_stack[L2_GUEST_STACK_SIZE]);
+       if (vmx->eptp_gpa)
+               l2_rip = l2_guest_code_ept_enabled;
+       else
+               l2_rip = l2_guest_code_ept_disabled;
+
+       prepare_vmcs(vmx, l2_rip, &l2_guest_stack[L2_GUEST_STACK_SIZE]);
 
        GUEST_SYNC(false);
        GUEST_ASSERT(!vmlaunch());
@@ -64,7 +80,7 @@ void l1_guest_code(struct vmx_pages *vmx)
        GUEST_DONE();
 }
 
-int main(int argc, char *argv[])
+static void test_vmx_dirty_log(bool enable_ept)
 {
        vm_vaddr_t vmx_pages_gva = 0;
        struct vmx_pages *vmx;
@@ -76,8 +92,7 @@ int main(int argc, char *argv[])
        struct ucall uc;
        bool done = false;
 
-       TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX));
-       TEST_REQUIRE(kvm_cpu_has_ept());
+       pr_info("Nested EPT: %s\n", enable_ept ? "enabled" : "disabled");
 
        /* Create VM */
        vm = vm_create_with_one_vcpu(&vcpu, l1_guest_code);
@@ -103,11 +118,16 @@ int main(int argc, char *argv[])
         *
         * Note that prepare_eptp should be called only L1's GPA map is done,
         * meaning after the last call to virt_map.
+        *
+        * When EPT is disabled, the L2 guest code will still access the same L1
+        * GPAs as the EPT enabled case.
         */
-       prepare_eptp(vmx, vm, 0);
-       nested_map_memslot(vmx, vm, 0);
-       nested_map(vmx, vm, NESTED_TEST_MEM1, GUEST_TEST_MEM, 4096);
-       nested_map(vmx, vm, NESTED_TEST_MEM2, GUEST_TEST_MEM, 4096);
+       if (enable_ept) {
+               prepare_eptp(vmx, vm, 0);
+               nested_map_memslot(vmx, vm, 0);
+               nested_map(vmx, vm, NESTED_TEST_MEM1, GUEST_TEST_MEM, 4096);
+               nested_map(vmx, vm, NESTED_TEST_MEM2, GUEST_TEST_MEM, 4096);
+       }
 
        bmap = bitmap_zalloc(TEST_MEM_PAGES);
        host_test_mem = addr_gpa2hva(vm, GUEST_TEST_MEM);
@@ -148,3 +168,15 @@ int main(int argc, char *argv[])
                }
        }
 }
+
+int main(int argc, char *argv[])
+{
+       TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX));
+
+       test_vmx_dirty_log(/*enable_ept=*/false);
+
+       if (kvm_cpu_has_ept())
+               test_vmx_dirty_log(/*enable_ept=*/true);
+
+       return 0;
+}
index 2fb6dd8adba6945d0000c19fe90da1002d8c0dd4..8b984fa042869e595507368541504f0b04d42014 100644 (file)
@@ -86,7 +86,7 @@ static void netstat_read_type(FILE *fnetstat, struct netstat **dest, char *line)
 
        pos = strchr(line, ' ') + 1;
 
-       if (fscanf(fnetstat, type->header_name) == EOF)
+       if (fscanf(fnetstat, "%[^ :]", type->header_name) == EOF)
                test_error("fscanf(%s)", type->header_name);
        if (fread(&tmp, 1, 1, fnetstat) != 1 || tmp != ':')
                test_error("Unexpected netstat format (%c)", tmp);
index 92276f916f2f30d080ba3e1f5521c492192f8e98..e408b9243b2c5a5cf66785518fbfc16f2682b169 100644 (file)
@@ -17,37 +17,37 @@ static pthread_mutex_t ksft_print_lock = PTHREAD_MUTEX_INITIALIZER;
 void __test_msg(const char *buf)
 {
        pthread_mutex_lock(&ksft_print_lock);
-       ksft_print_msg(buf);
+       ksft_print_msg("%s", buf);
        pthread_mutex_unlock(&ksft_print_lock);
 }
 void __test_ok(const char *buf)
 {
        pthread_mutex_lock(&ksft_print_lock);
-       ksft_test_result_pass(buf);
+       ksft_test_result_pass("%s", buf);
        pthread_mutex_unlock(&ksft_print_lock);
 }
 void __test_fail(const char *buf)
 {
        pthread_mutex_lock(&ksft_print_lock);
-       ksft_test_result_fail(buf);
+       ksft_test_result_fail("%s", buf);
        pthread_mutex_unlock(&ksft_print_lock);
 }
 void __test_xfail(const char *buf)
 {
        pthread_mutex_lock(&ksft_print_lock);
-       ksft_test_result_xfail(buf);
+       ksft_test_result_xfail("%s", buf);
        pthread_mutex_unlock(&ksft_print_lock);
 }
 void __test_error(const char *buf)
 {
        pthread_mutex_lock(&ksft_print_lock);
-       ksft_test_result_error(buf);
+       ksft_test_result_error("%s", buf);
        pthread_mutex_unlock(&ksft_print_lock);
 }
 void __test_skip(const char *buf)
 {
        pthread_mutex_lock(&ksft_print_lock);
-       ksft_test_result_skip(buf);
+       ksft_test_result_skip("%s", buf);
        pthread_mutex_unlock(&ksft_print_lock);
 }
 
index 7df8b8700e39e96292f8eafdf105ee0314a65497..a2fe88d35ac06e4f534bd4d452670528d9f77219 100644 (file)
@@ -256,8 +256,6 @@ static int test_wait_fds(int sk[], size_t nr, bool is_writable[],
 
 static void test_client_active_rst(unsigned int port)
 {
-       /* one in queue, another accept()ed */
-       unsigned int wait_for = backlog + 2;
        int i, sk[3], err;
        bool is_writable[ARRAY_SIZE(sk)] = {false};
        unsigned int last = ARRAY_SIZE(sk) - 1;
@@ -275,16 +273,20 @@ static void test_client_active_rst(unsigned int port)
        for (i = 0; i < last; i++) {
                err = _test_connect_socket(sk[i], this_ip_dest, port,
                                               (i == 0) ? TEST_TIMEOUT_SEC : -1);
-
                if (err < 0)
                        test_error("failed to connect()");
        }
 
-       synchronize_threads(); /* 2: connection accept()ed, another queued */
-       err = test_wait_fds(sk, last, is_writable, wait_for, TEST_TIMEOUT_SEC);
+       synchronize_threads(); /* 2: two connections: one accept()ed, another queued */
+       err = test_wait_fds(sk, last, is_writable, last, TEST_TIMEOUT_SEC);
        if (err < 0)
                test_error("test_wait_fds(): %d", err);
 
+       /* async connect() with third sk to get into request_sock_queue */
+       err = _test_connect_socket(sk[last], this_ip_dest, port, -1);
+       if (err < 0)
+               test_error("failed to connect()");
+
        synchronize_threads(); /* 3: close listen socket */
        if (test_client_verify(sk[0], packet_sz, quota / packet_sz, TEST_TIMEOUT_SEC))
                test_fail("Failed to send data on connected socket");
@@ -292,13 +294,14 @@ static void test_client_active_rst(unsigned int port)
                test_ok("Verified established tcp connection");
 
        synchronize_threads(); /* 4: finishing up */
-       err = _test_connect_socket(sk[last], this_ip_dest, port, -1);
-       if (err < 0)
-               test_error("failed to connect()");
 
        synchronize_threads(); /* 5: closed active sk */
-       err = test_wait_fds(sk, ARRAY_SIZE(sk), NULL,
-                           wait_for, TEST_TIMEOUT_SEC);
+       /*
+        * Wait for 2 connections: one accepted, another in the accept queue,
+        * the one in request_sock_queue won't get fully established, so
+        * doesn't receive an active RST, see inet_csk_listen_stop().
+        */
+       err = test_wait_fds(sk, last, NULL, last, TEST_TIMEOUT_SEC);
        if (err < 0)
                test_error("select(): %d", err);
 
index 452de131fa3a9c720cd1fc4b9dc24438fd01d15d..517930f9721bd9b062d178def9fb296c17353119 100644 (file)
@@ -21,7 +21,7 @@ static void make_listen(int sk)
 static void test_vefify_ao_info(int sk, struct tcp_ao_info_opt *info,
                                const char *tst)
 {
-       struct tcp_ao_info_opt tmp;
+       struct tcp_ao_info_opt tmp = {};
        socklen_t len = sizeof(tmp);
 
        if (getsockopt(sk, IPPROTO_TCP, TCP_AO_INFO, &tmp, &len))
index 1d975bf52af33908593f61894233f9d8560cb16f..85b3baa3f7f34112ea95239c8819a2b1d834e22a 100644 (file)
@@ -34,7 +34,7 @@
 #endif
 
 #ifndef UDP_MAX_SEGMENTS
-#define UDP_MAX_SEGMENTS       (1 << 6UL)
+#define UDP_MAX_SEGMENTS       (1 << 7UL)
 #endif
 
 #define CONST_MTU_TEST 1500
index 505294da1b9fb5e7bd07aac4a119164900c8f2e6..d6f99eb9be659d3c9bb60b922e4f81102ac7f918 100644 (file)
@@ -154,7 +154,7 @@ static int dev_papr_vpd_null_handle(void)
 static int papr_vpd_close_handle_without_reading(void)
 {
        const int devfd = open(DEVPATH, O_RDONLY);
-       struct papr_location_code lc;
+       struct papr_location_code lc = { .str = "", };
        int fd;
 
        SKIP_IF_MSG(devfd < 0 && errno == ENOENT,
index fb49c2a602002ed30a5f426203fa0e30be2436b0..ff0a20565f9087e05e7e086f20025efd52c60819 100644 (file)
@@ -832,8 +832,7 @@ static int kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
         * mn_active_invalidate_count (see above) instead of
         * mmu_invalidate_in_progress.
         */
-       gfn_to_pfn_cache_invalidate_start(kvm, range->start, range->end,
-                                         hva_range.may_block);
+       gfn_to_pfn_cache_invalidate_start(kvm, range->start, range->end);
 
        /*
         * If one or more memslots were found and thus zapped, notify arch code
index ecefc7ec51af8516c14c13bf0ad68ad1bc369e77..715f19669d01f72912af9b7393ccd01f65c0527e 100644 (file)
@@ -26,13 +26,11 @@ kvm_pfn_t hva_to_pfn(unsigned long addr, bool atomic, bool interruptible,
 #ifdef CONFIG_HAVE_KVM_PFNCACHE
 void gfn_to_pfn_cache_invalidate_start(struct kvm *kvm,
                                       unsigned long start,
-                                      unsigned long end,
-                                      bool may_block);
+                                      unsigned long end);
 #else
 static inline void gfn_to_pfn_cache_invalidate_start(struct kvm *kvm,
                                                     unsigned long start,
-                                                    unsigned long end,
-                                                    bool may_block)
+                                                    unsigned long end)
 {
 }
 #endif /* HAVE_KVM_PFNCACHE */
index 4e07112a24c2f6d02f67ee22a7f7eaa15c5f098b..e3453e869e92c8f6546b7aa76ce8b3a2b486df4f 100644 (file)
@@ -23,7 +23,7 @@
  * MMU notifier 'invalidate_range_start' hook.
  */
 void gfn_to_pfn_cache_invalidate_start(struct kvm *kvm, unsigned long start,
-                                      unsigned long end, bool may_block)
+                                      unsigned long end)
 {
        struct gfn_to_pfn_cache *gpc;
 
@@ -57,6 +57,19 @@ void gfn_to_pfn_cache_invalidate_start(struct kvm *kvm, unsigned long start,
        spin_unlock(&kvm->gpc_lock);
 }
 
+static bool kvm_gpc_is_valid_len(gpa_t gpa, unsigned long uhva,
+                                unsigned long len)
+{
+       unsigned long offset = kvm_is_error_gpa(gpa) ? offset_in_page(uhva) :
+                                                      offset_in_page(gpa);
+
+       /*
+        * The cached access must fit within a single page. The 'len' argument
+        * to activate() and refresh() exists only to enforce that.
+        */
+       return offset + len <= PAGE_SIZE;
+}
+
 bool kvm_gpc_check(struct gfn_to_pfn_cache *gpc, unsigned long len)
 {
        struct kvm_memslots *slots = kvm_memslots(gpc->kvm);
@@ -74,7 +87,7 @@ bool kvm_gpc_check(struct gfn_to_pfn_cache *gpc, unsigned long len)
        if (kvm_is_error_hva(gpc->uhva))
                return false;
 
-       if (offset_in_page(gpc->uhva) + len > PAGE_SIZE)
+       if (!kvm_gpc_is_valid_len(gpc->gpa, gpc->uhva, len))
                return false;
 
        if (!gpc->valid)
@@ -232,8 +245,7 @@ out_error:
        return -EFAULT;
 }
 
-static int __kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned long uhva,
-                            unsigned long len)
+static int __kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned long uhva)
 {
        unsigned long page_offset;
        bool unmap_old = false;
@@ -247,15 +259,6 @@ static int __kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned l
        if (WARN_ON_ONCE(kvm_is_error_gpa(gpa) == kvm_is_error_hva(uhva)))
                return -EINVAL;
 
-       /*
-        * The cached acces must fit within a single page. The 'len' argument
-        * exists only to enforce that.
-        */
-       page_offset = kvm_is_error_gpa(gpa) ? offset_in_page(uhva) :
-                                             offset_in_page(gpa);
-       if (page_offset + len > PAGE_SIZE)
-               return -EINVAL;
-
        lockdep_assert_held(&gpc->refresh_lock);
 
        write_lock_irq(&gpc->lock);
@@ -270,6 +273,8 @@ static int __kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned l
        old_uhva = PAGE_ALIGN_DOWN(gpc->uhva);
 
        if (kvm_is_error_gpa(gpa)) {
+               page_offset = offset_in_page(uhva);
+
                gpc->gpa = INVALID_GPA;
                gpc->memslot = NULL;
                gpc->uhva = PAGE_ALIGN_DOWN(uhva);
@@ -279,6 +284,8 @@ static int __kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned l
        } else {
                struct kvm_memslots *slots = kvm_memslots(gpc->kvm);
 
+               page_offset = offset_in_page(gpa);
+
                if (gpc->gpa != gpa || gpc->generation != slots->generation ||
                    kvm_is_error_hva(gpc->uhva)) {
                        gfn_t gfn = gpa_to_gfn(gpa);
@@ -354,6 +361,9 @@ int kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, unsigned long len)
 
        guard(mutex)(&gpc->refresh_lock);
 
+       if (!kvm_gpc_is_valid_len(gpc->gpa, gpc->uhva, len))
+               return -EINVAL;
+
        /*
         * If the GPA is valid then ignore the HVA, as a cache can be GPA-based
         * or HVA-based, not both.  For GPA-based caches, the HVA will be
@@ -361,7 +371,7 @@ int kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, unsigned long len)
         */
        uhva = kvm_is_error_gpa(gpc->gpa) ? gpc->uhva : KVM_HVA_ERR_BAD;
 
-       return __kvm_gpc_refresh(gpc, gpc->gpa, uhva, len);
+       return __kvm_gpc_refresh(gpc, gpc->gpa, uhva);
 }
 
 void kvm_gpc_init(struct gfn_to_pfn_cache *gpc, struct kvm *kvm)
@@ -381,6 +391,9 @@ static int __kvm_gpc_activate(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned
 {
        struct kvm *kvm = gpc->kvm;
 
+       if (!kvm_gpc_is_valid_len(gpa, uhva, len))
+               return -EINVAL;
+
        guard(mutex)(&gpc->refresh_lock);
 
        if (!gpc->active) {
@@ -400,11 +413,18 @@ static int __kvm_gpc_activate(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned
                gpc->active = true;
                write_unlock_irq(&gpc->lock);
        }
-       return __kvm_gpc_refresh(gpc, gpa, uhva, len);
+       return __kvm_gpc_refresh(gpc, gpa, uhva);
 }
 
 int kvm_gpc_activate(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned long len)
 {
+       /*
+        * Explicitly disallow INVALID_GPA so that the magic value can be used
+        * by KVM to differentiate between GPA-based and HVA-based caches.
+        */
+       if (WARN_ON_ONCE(kvm_is_error_gpa(gpa)))
+               return -EINVAL;
+
        return __kvm_gpc_activate(gpc, gpa, KVM_HVA_ERR_BAD, len);
 }