]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.15
authorSasha Levin <sashal@kernel.org>
Fri, 4 Mar 2022 17:28:53 +0000 (12:28 -0500)
committerSasha Levin <sashal@kernel.org>
Fri, 4 Mar 2022 17:28:53 +0000 (12:28 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
94 files changed:
queue-5.15/bnxt_en-fix-occasional-ethtool-t-loopback-test-failu.patch [new file with mode: 0644]
queue-5.15/bpf-arm64-use-emit_addr_mov_i64-for-bpf_pseudo_func.patch [new file with mode: 0644]
queue-5.15/bpf-fix-possible-race-in-inc_misses_counter.patch [new file with mode: 0644]
queue-5.15/bpf-use-u64_stats_t-in-struct-bpf_prog_stats.patch [new file with mode: 0644]
queue-5.15/cifs-fix-confusing-unneeded-warning-message-on-smb2..patch [new file with mode: 0644]
queue-5.15/cifs-protect-session-channel-fields-with-chan_lock.patch [new file with mode: 0644]
queue-5.15/dma-buf-cma_heap-fix-mutex-locking-section.patch [new file with mode: 0644]
queue-5.15/drm-amd-display-fix-stream-link_enc-unassigned-durin.patch [new file with mode: 0644]
queue-5.15/drm-amd-display-for-vblank_disable_immediate-check-p.patch [new file with mode: 0644]
queue-5.15/drm-amd-display-move-fpu-associated-dcn301-code-to-d.patch [new file with mode: 0644]
queue-5.15/drm-amd-display-move-fpu-associated-dsc-code-to-dml-.patch [new file with mode: 0644]
queue-5.15/drm-amd-display-update-watermark-values-for-dcn301.patch [new file with mode: 0644]
queue-5.15/drm-amd-display-use-adjusted-dcn301-watermarks.patch [new file with mode: 0644]
queue-5.15/drm-amd-display-wrap-dcn301_calculate_wm_and_dlg-for.patch [new file with mode: 0644]
queue-5.15/drm-amdgpu-display-only-set-vblank_disable_immediate.patch [new file with mode: 0644]
queue-5.15/drm-amdgpu-filter-out-radeon-pci-device-ids.patch [new file with mode: 0644]
queue-5.15/drm-amdgpu-filter-out-radeon-secondary-ids-as-well.patch [new file with mode: 0644]
queue-5.15/drm-amdgpu-use-spin_lock_irqsave-to-avoid-deadlock-b.patch [new file with mode: 0644]
queue-5.15/drm-amdkfd-check-for-null-pointer-after-calling-kmem.patch [new file with mode: 0644]
queue-5.15/drm-atomic-check-new_crtc_state-active-to-determine-.patch [new file with mode: 0644]
queue-5.15/drm-i915-disable-drrs-on-ivb-hsw-port-a.patch [new file with mode: 0644]
queue-5.15/drm-i915-display-move-drrs-code-its-own-file.patch [new file with mode: 0644]
queue-5.15/drm-i915-display-split-out-dpt-out-of-intel_display..patch [new file with mode: 0644]
queue-5.15/drm-i915-don-t-call-free_mmap_offset-when-purging.patch [new file with mode: 0644]
queue-5.15/drm-i915-workaround-broken-bios-dbuf-configuration-o.patch [new file with mode: 0644]
queue-5.15/drm-mediatek-mtk_dsi-avoid-eprobe_defer-loop-with-ex.patch [new file with mode: 0644]
queue-5.15/drm-mediatek-mtk_dsi-reset-the-dsi0-hardware.patch [new file with mode: 0644]
queue-5.15/drm-mxsfb-fix-null-pointer-dereference.patch [new file with mode: 0644]
queue-5.15/drm-mxsfb-set-fallback-bus-format-when-the-bridge-do.patch [new file with mode: 0644]
queue-5.15/drm-sun4i-dw-hdmi-fix-missing-put_device-call-in-sun.patch [new file with mode: 0644]
queue-5.15/ethtool-fix-link-extended-state-for-big-endian.patch [new file with mode: 0644]
queue-5.15/gve-recording-rx-queue-before-sending-to-napi.patch [new file with mode: 0644]
queue-5.15/hugetlbfs-fix-off-by-one-error-in-hugetlb_vmdelete_l.patch [new file with mode: 0644]
queue-5.15/i3c-fix-incorrect-address-slot-lookup-on-64-bit.patch [new file with mode: 0644]
queue-5.15/i3c-master-dw-check-return-of-dw_i3c_master_get_free.patch [new file with mode: 0644]
queue-5.15/i3c-master-mipi-i3c-hci-fix-a-potentially-infinite-l.patch [new file with mode: 0644]
queue-5.15/ibmvnic-don-t-release-napi-in-__ibmvnic_open.patch [new file with mode: 0644]
queue-5.15/input-ti_am335x_tsc-fix-stepconfig-setup-for-z2.patch [new file with mode: 0644]
queue-5.15/input-ti_am335x_tsc-set-adcrefm-for-x-configuration.patch [new file with mode: 0644]
queue-5.15/io_uring-fix-no-lock-protection-for-ctx-cq_extra.patch [new file with mode: 0644]
queue-5.15/kasan-fix-quarantine-conflicting-with-init_on_free.patch [new file with mode: 0644]
queue-5.15/kvm-s390-ensure-kvm_arch_no_poll-is-read-once-when-b.patch [new file with mode: 0644]
queue-5.15/kvm-vmx-don-t-unblock-vcpu-w-posted-irq-if-irqs-are-.patch [new file with mode: 0644]
queue-5.15/kvm-vmx-read-posted-interrupt-control-exactly-once-p.patch [new file with mode: 0644]
queue-5.15/kvm-x86-ensure-that-dirty-pdptrs-are-loaded.patch [new file with mode: 0644]
queue-5.15/kvm-x86-exit-to-userspace-if-emulation-prepared-a-co.patch [new file with mode: 0644]
queue-5.15/kvm-x86-handle-32-bit-wrap-of-eip-for-emultype_skip-.patch [new file with mode: 0644]
queue-5.15/mips-fix-local_-add-sub-_return-on-mips64.patch [new file with mode: 0644]
queue-5.15/mm-defer-kmemleak-object-creation-of-module_alloc.patch [new file with mode: 0644]
queue-5.15/mtd-spi-nor-fix-mtd-size-for-s3an-flashes.patch [new file with mode: 0644]
queue-5.15/net-dsa-ocelot-seville-utilize-of_mdiobus_register.patch [new file with mode: 0644]
queue-5.15/net-dsa-seville-register-the-mdiobus-under-devres.patch [new file with mode: 0644]
queue-5.15/net-ethernet-litex-add-the-dependency-on-has_iomem.patch [new file with mode: 0644]
queue-5.15/net-mlx5e-ipsec-fix-crypto-offload-for-non-tcp-udp-e.patch [new file with mode: 0644]
queue-5.15/net-mlx5e-ipsec-refactor-checksum-code-in-tx-data-pa.patch [new file with mode: 0644]
queue-5.15/nfsd-fix-crash-on-copy_notify-with-special-stateid.patch [new file with mode: 0644]
queue-5.15/nfsd-fix-verifier-returned-in-stable-writes.patch [new file with mode: 0644]
queue-5.15/nfsd-fix-zero-length-nfsv3-writes.patch [new file with mode: 0644]
queue-5.15/nfsd-have-legacy-nfsd-write-decoders-use-xdr_stream_.patch [new file with mode: 0644]
queue-5.15/ntb_hw_switchtec-fix-bug-with-more-than-32-partition.patch [new file with mode: 0644]
queue-5.15/ntb_hw_switchtec-fix-pff-ioread-to-read-into-mmio_pa.patch [new file with mode: 0644]
queue-5.15/octeontx2-af-add-kpu-changes-to-parse-ngio-as-separa.patch [new file with mode: 0644]
queue-5.15/octeontx2-af-adjust-la-pointer-for-cpt-parse-header.patch [new file with mode: 0644]
queue-5.15/octeontx2-af-cn10k-rpm-hardware-timestamp-configurat.patch [new file with mode: 0644]
queue-5.15/octeontx2-af-cn10k-use-appropriate-register-for-lmac.patch [new file with mode: 0644]
queue-5.15/octeontx2-af-optimize-kpu1-processing-for-variable-l.patch [new file with mode: 0644]
queue-5.15/octeontx2-af-reset-ptp-config-in-flr-handler.patch [new file with mode: 0644]
queue-5.15/of-net-move-of_net-under-net.patch [new file with mode: 0644]
queue-5.15/pci-aardvark-fix-checking-for-mem-resource-type.patch [new file with mode: 0644]
queue-5.15/pci-dwc-do-not-remap-invalid-res.patch [new file with mode: 0644]
queue-5.15/pci-mediatek-gen3-disable-dvfsrc-voltage-request.patch [new file with mode: 0644]
queue-5.15/pci-mvebu-check-for-errors-from-pci_bridge_emul_init.patch [new file with mode: 0644]
queue-5.15/pci-mvebu-do-not-modify-pci-io-type-bits-in-conf_wri.patch [new file with mode: 0644]
queue-5.15/pci-mvebu-fix-configuring-secondary-bus-of-pcie-root.patch [new file with mode: 0644]
queue-5.15/pci-mvebu-fix-device-enumeration-regression.patch [new file with mode: 0644]
queue-5.15/pci-mvebu-fix-support-for-bus-mastering-and-pci_comm.patch [new file with mode: 0644]
queue-5.15/pci-mvebu-fix-support-for-devcap2-devctl2-and-lnkctl.patch [new file with mode: 0644]
queue-5.15/pci-mvebu-fix-support-for-pci_bridge_ctl_bus_reset-o.patch [new file with mode: 0644]
queue-5.15/pci-mvebu-fix-support-for-pci_exp_devctl-on-emulated.patch [new file with mode: 0644]
queue-5.15/pci-mvebu-fix-support-for-pci_exp_rtsta-on-emulated-.patch [new file with mode: 0644]
queue-5.15/pci-mvebu-setup-pcie-controller-to-root-complex-mode.patch [new file with mode: 0644]
queue-5.15/pci-rcar-check-if-device-is-runtime-suspended-instea.patch [new file with mode: 0644]
queue-5.15/revert-nfsd-skip-some-unnecessary-stats-in-the-v4-ca.patch [new file with mode: 0644]
queue-5.15/riscv-mm-add-xip_fixup-for-phys_ram_base.patch [new file with mode: 0644]
queue-5.15/selftests-vm-make-charge_reserved_hugetlb.sh-work-wi.patch [new file with mode: 0644]
queue-5.15/series
queue-5.15/signal-in-get_signal-test-for-signal_group_exit-ever.patch [new file with mode: 0644]
queue-5.15/sunrpc-fix-sockaddr-handling-in-svcsock_accept_class.patch [new file with mode: 0644]
queue-5.15/sunrpc-fix-sockaddr-handling-in-the-svc_xprt_create_.patch [new file with mode: 0644]
queue-5.15/tools-resolve_btf_ids-close-elf-file-on-error.patch [new file with mode: 0644]
queue-5.15/tracing-do-not-let-synth_events-block-other-dyn_even.patch [new file with mode: 0644]
queue-5.15/tracing-probes-check-the-return-value-of-kstrndup-fo.patch [new file with mode: 0644]
queue-5.15/tracing-uprobes-check-the-return-value-of-kstrdup-fo.patch [new file with mode: 0644]
queue-5.15/x86-hyperv-properly-deal-with-empty-cpumasks-in-hype.patch [new file with mode: 0644]

diff --git a/queue-5.15/bnxt_en-fix-occasional-ethtool-t-loopback-test-failu.patch b/queue-5.15/bnxt_en-fix-occasional-ethtool-t-loopback-test-failu.patch
new file mode 100644 (file)
index 0000000..9252f52
--- /dev/null
@@ -0,0 +1,102 @@
+From c2bbc85ba720286c3caf92054a5600a91377b2cf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 20 Feb 2022 04:05:49 -0500
+Subject: bnxt_en: Fix occasional ethtool -t loopback test failures
+
+From: Michael Chan <michael.chan@broadcom.com>
+
+[ Upstream commit cfcab3b3b61584a02bb523ffa99564eafa761dfe ]
+
+In the current code, we setup the port to PHY or MAC loopback mode
+and then transmit a test broadcast packet for the loopback test.  This
+scheme fails sometime if the port is shared with management firmware
+that can also send packets.  The driver may receive the management
+firmware's packet and the test will fail when the contents don't
+match the test packet.
+
+Change the test packet to use it's own MAC address as the destination
+and setup the port to only receive it's own MAC address.  This should
+filter out other packets sent by management firmware.
+
+Fixes: 91725d89b97a ("bnxt_en: Add PHY loopback to ethtool self-test.")
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Reviewed-by: Edwin Peer <edwin.peer@broadcom.com>
+Reviewed-by: Andy Gospodarek <gospo@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c         | 7 +++++++
+ drivers/net/ethernet/broadcom/bnxt/bnxt.h         | 1 +
+ drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 2 +-
+ 3 files changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index f92bea4faa019..ce36ee5a250fb 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -8617,6 +8617,9 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init)
+       vnic->uc_filter_count = 1;
+       vnic->rx_mask = 0;
++      if (test_bit(BNXT_STATE_HALF_OPEN, &bp->state))
++              goto skip_rx_mask;
++
+       if (bp->dev->flags & IFF_BROADCAST)
+               vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_BCAST;
+@@ -8637,6 +8640,7 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init)
+       if (rc)
+               goto err_out;
++skip_rx_mask:
+       rc = bnxt_hwrm_set_coal(bp);
+       if (rc)
+               netdev_warn(bp->dev, "HWRM set coalescing failure rc: %x\n",
+@@ -10302,8 +10306,10 @@ int bnxt_half_open_nic(struct bnxt *bp)
+               netdev_err(bp->dev, "bnxt_alloc_mem err: %x\n", rc);
+               goto half_open_err;
+       }
++      set_bit(BNXT_STATE_HALF_OPEN, &bp->state);
+       rc = bnxt_init_nic(bp, true);
+       if (rc) {
++              clear_bit(BNXT_STATE_HALF_OPEN, &bp->state);
+               netdev_err(bp->dev, "bnxt_init_nic err: %x\n", rc);
+               goto half_open_err;
+       }
+@@ -10324,6 +10330,7 @@ void bnxt_half_close_nic(struct bnxt *bp)
+       bnxt_hwrm_resource_free(bp, false, true);
+       bnxt_free_skbs(bp);
+       bnxt_free_mem(bp, true);
++      clear_bit(BNXT_STATE_HALF_OPEN, &bp->state);
+ }
+ static void bnxt_reenable_sriov(struct bnxt *bp)
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+index 0a5137c1f6d4e..ca6fdf03e5865 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+@@ -1840,6 +1840,7 @@ struct bnxt {
+ #define BNXT_STATE_DRV_REGISTERED     7
+ #define BNXT_STATE_PCI_CHANNEL_IO_FROZEN      8
+ #define BNXT_STATE_NAPI_DISABLED      9
++#define BNXT_STATE_HALF_OPEN          15      /* For offline ethtool tests */
+ #define BNXT_NO_FW_ACCESS(bp)                                 \
+       (test_bit(BNXT_STATE_FW_FATAL_COND, &(bp)->state) ||    \
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+index da3ee22e8a16f..af7de9ee66cf2 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+@@ -3409,7 +3409,7 @@ static int bnxt_run_loopback(struct bnxt *bp)
+       if (!skb)
+               return -ENOMEM;
+       data = skb_put(skb, pkt_size);
+-      eth_broadcast_addr(data);
++      ether_addr_copy(&data[i], bp->dev->dev_addr);
+       i += ETH_ALEN;
+       ether_addr_copy(&data[i], bp->dev->dev_addr);
+       i += ETH_ALEN;
+-- 
+2.34.1
+
diff --git a/queue-5.15/bpf-arm64-use-emit_addr_mov_i64-for-bpf_pseudo_func.patch b/queue-5.15/bpf-arm64-use-emit_addr_mov_i64-for-bpf_pseudo_func.patch
new file mode 100644 (file)
index 0000000..bf00298
--- /dev/null
@@ -0,0 +1,59 @@
+From 53a9337e96db2364cceb9f409f78256373b83800 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Dec 2021 23:10:18 +0800
+Subject: bpf, arm64: Use emit_addr_mov_i64() for BPF_PSEUDO_FUNC
+
+From: Hou Tao <houtao1@huawei.com>
+
+[ Upstream commit e4a41c2c1fa916547e63440c73a51a5eb06247af ]
+
+The following error is reported when running "./test_progs -t for_each"
+under arm64:
+
+  bpf_jit: multi-func JIT bug 58 != 56
+  [...]
+  JIT doesn't support bpf-to-bpf calls
+
+The root cause is the size of BPF_PSEUDO_FUNC instruction increases
+from 2 to 3 after the address of called bpf-function is settled and
+there are two bpf-to-bpf calls in test_pkt_access. The generated
+instructions are shown below:
+
+  0x48:  21 00 C0 D2    movz x1, #0x1, lsl #32
+  0x4c:  21 00 80 F2    movk x1, #0x1
+
+  0x48:  E1 3F C0 92    movn x1, #0x1ff, lsl #32
+  0x4c:  41 FE A2 F2    movk x1, #0x17f2, lsl #16
+  0x50:  81 70 9F F2    movk x1, #0xfb84
+
+Fixing it by using emit_addr_mov_i64() for BPF_PSEUDO_FUNC, so
+the size of jited image will not change.
+
+Fixes: 69c087ba6225 ("bpf: Add bpf_for_each_map_elem() helper")
+Signed-off-by: Hou Tao <houtao1@huawei.com>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Link: https://lore.kernel.org/bpf/20211231151018.3781550-1-houtao1@huawei.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/net/bpf_jit_comp.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
+index 465c44d0c72fc..3d7381ffc1712 100644
+--- a/arch/arm64/net/bpf_jit_comp.c
++++ b/arch/arm64/net/bpf_jit_comp.c
+@@ -788,7 +788,10 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
+               u64 imm64;
+               imm64 = (u64)insn1.imm << 32 | (u32)imm;
+-              emit_a64_mov_i64(dst, imm64, ctx);
++              if (bpf_pseudo_func(insn))
++                      emit_addr_mov_i64(dst, imm64, ctx);
++              else
++                      emit_a64_mov_i64(dst, imm64, ctx);
+               return 1;
+       }
+-- 
+2.34.1
+
diff --git a/queue-5.15/bpf-fix-possible-race-in-inc_misses_counter.patch b/queue-5.15/bpf-fix-possible-race-in-inc_misses_counter.patch
new file mode 100644 (file)
index 0000000..3a02ffd
--- /dev/null
@@ -0,0 +1,47 @@
+From 9a45c44573ba9428f978d99230092ae474f16045 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 22 Jan 2022 10:29:36 +0000
+Subject: bpf: Fix possible race in inc_misses_counter
+
+From: He Fengqing <hefengqing@huawei.com>
+
+[ Upstream commit 0e3135d3bfa5dfb658145238d2bc723a8e30c3a3 ]
+
+It seems inc_misses_counter() suffers from same issue fixed in
+the commit d979617aa84d ("bpf: Fixes possible race in update_prog_stats()
+for 32bit arches"):
+As it can run while interrupts are enabled, it could
+be re-entered and the u64_stats syncp could be mangled.
+
+Fixes: 9ed9e9ba2337 ("bpf: Count the number of times recursion was prevented")
+Signed-off-by: He Fengqing <hefengqing@huawei.com>
+Acked-by: John Fastabend <john.fastabend@gmail.com>
+Link: https://lore.kernel.org/r/20220122102936.1219518-1-hefengqing@huawei.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/trampoline.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
+index 6933a9bfee637..2660fbced9ad4 100644
+--- a/kernel/bpf/trampoline.c
++++ b/kernel/bpf/trampoline.c
+@@ -541,11 +541,12 @@ static u64 notrace bpf_prog_start_time(void)
+ static void notrace inc_misses_counter(struct bpf_prog *prog)
+ {
+       struct bpf_prog_stats *stats;
++      unsigned int flags;
+       stats = this_cpu_ptr(prog->stats);
+-      u64_stats_update_begin(&stats->syncp);
++      flags = u64_stats_update_begin_irqsave(&stats->syncp);
+       u64_stats_inc(&stats->misses);
+-      u64_stats_update_end(&stats->syncp);
++      u64_stats_update_end_irqrestore(&stats->syncp, flags);
+ }
+ /* The logic is similar to bpf_prog_run(), but with an explicit
+-- 
+2.34.1
+
diff --git a/queue-5.15/bpf-use-u64_stats_t-in-struct-bpf_prog_stats.patch b/queue-5.15/bpf-use-u64_stats_t-in-struct-bpf_prog_stats.patch
new file mode 100644 (file)
index 0000000..be75c51
--- /dev/null
@@ -0,0 +1,139 @@
+From f3c6b4d11bc60342817719fa79759c3512196d38 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Oct 2021 14:41:33 -0700
+Subject: bpf: Use u64_stats_t in struct bpf_prog_stats
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 61a0abaee2092eee69e44fe60336aa2f5b578938 ]
+
+Commit 316580b69d0a ("u64_stats: provide u64_stats_t type")
+fixed possible load/store tearing on 64bit arches.
+
+For instance the following C code
+
+stats->nsecs += sched_clock() - start;
+
+Could be rightfully implemented like this by a compiler,
+confusing concurrent readers a lot:
+
+stats->nsecs += sched_clock();
+// arbitrary delay
+stats->nsecs -= start;
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Link: https://lore.kernel.org/bpf/20211026214133.3114279-4-eric.dumazet@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/filter.h  | 10 +++++-----
+ kernel/bpf/syscall.c    | 18 ++++++++++++------
+ kernel/bpf/trampoline.c |  6 +++---
+ 3 files changed, 20 insertions(+), 14 deletions(-)
+
+diff --git a/include/linux/filter.h b/include/linux/filter.h
+index 1611dc9d44207..a9956b681f090 100644
+--- a/include/linux/filter.h
++++ b/include/linux/filter.h
+@@ -554,9 +554,9 @@ struct bpf_binary_header {
+ };
+ struct bpf_prog_stats {
+-      u64 cnt;
+-      u64 nsecs;
+-      u64 misses;
++      u64_stats_t cnt;
++      u64_stats_t nsecs;
++      u64_stats_t misses;
+       struct u64_stats_sync syncp;
+ } __aligned(2 * sizeof(u64));
+@@ -618,8 +618,8 @@ static __always_inline u32 __bpf_prog_run(const struct bpf_prog *prog,
+               ret = dfunc(ctx, prog->insnsi, prog->bpf_func);
+               stats = this_cpu_ptr(prog->stats);
+               flags = u64_stats_update_begin_irqsave(&stats->syncp);
+-              stats->cnt++;
+-              stats->nsecs += sched_clock() - start;
++              u64_stats_inc(&stats->cnt);
++              u64_stats_add(&stats->nsecs, sched_clock() - start);
+               u64_stats_update_end_irqrestore(&stats->syncp, flags);
+       } else {
+               ret = dfunc(ctx, prog->insnsi, prog->bpf_func);
+diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
+index 53384622e8dac..42490c39dfbf5 100644
+--- a/kernel/bpf/syscall.c
++++ b/kernel/bpf/syscall.c
+@@ -1824,8 +1824,14 @@ static int bpf_prog_release(struct inode *inode, struct file *filp)
+       return 0;
+ }
++struct bpf_prog_kstats {
++      u64 nsecs;
++      u64 cnt;
++      u64 misses;
++};
++
+ static void bpf_prog_get_stats(const struct bpf_prog *prog,
+-                             struct bpf_prog_stats *stats)
++                             struct bpf_prog_kstats *stats)
+ {
+       u64 nsecs = 0, cnt = 0, misses = 0;
+       int cpu;
+@@ -1838,9 +1844,9 @@ static void bpf_prog_get_stats(const struct bpf_prog *prog,
+               st = per_cpu_ptr(prog->stats, cpu);
+               do {
+                       start = u64_stats_fetch_begin_irq(&st->syncp);
+-                      tnsecs = st->nsecs;
+-                      tcnt = st->cnt;
+-                      tmisses = st->misses;
++                      tnsecs = u64_stats_read(&st->nsecs);
++                      tcnt = u64_stats_read(&st->cnt);
++                      tmisses = u64_stats_read(&st->misses);
+               } while (u64_stats_fetch_retry_irq(&st->syncp, start));
+               nsecs += tnsecs;
+               cnt += tcnt;
+@@ -1856,7 +1862,7 @@ static void bpf_prog_show_fdinfo(struct seq_file *m, struct file *filp)
+ {
+       const struct bpf_prog *prog = filp->private_data;
+       char prog_tag[sizeof(prog->tag) * 2 + 1] = { };
+-      struct bpf_prog_stats stats;
++      struct bpf_prog_kstats stats;
+       bpf_prog_get_stats(prog, &stats);
+       bin2hex(prog_tag, prog->tag, sizeof(prog->tag));
+@@ -3595,7 +3601,7 @@ static int bpf_prog_get_info_by_fd(struct file *file,
+       struct bpf_prog_info __user *uinfo = u64_to_user_ptr(attr->info.info);
+       struct bpf_prog_info info;
+       u32 info_len = attr->info.info_len;
+-      struct bpf_prog_stats stats;
++      struct bpf_prog_kstats stats;
+       char __user *uinsns;
+       u32 ulen;
+       int err;
+diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
+index d3a307a8c42b9..6933a9bfee637 100644
+--- a/kernel/bpf/trampoline.c
++++ b/kernel/bpf/trampoline.c
+@@ -544,7 +544,7 @@ static void notrace inc_misses_counter(struct bpf_prog *prog)
+       stats = this_cpu_ptr(prog->stats);
+       u64_stats_update_begin(&stats->syncp);
+-      stats->misses++;
++      u64_stats_inc(&stats->misses);
+       u64_stats_update_end(&stats->syncp);
+ }
+@@ -589,8 +589,8 @@ static void notrace update_prog_stats(struct bpf_prog *prog,
+               stats = this_cpu_ptr(prog->stats);
+               flags = u64_stats_update_begin_irqsave(&stats->syncp);
+-              stats->cnt++;
+-              stats->nsecs += sched_clock() - start;
++              u64_stats_inc(&stats->cnt);
++              u64_stats_add(&stats->nsecs, sched_clock() - start);
+               u64_stats_update_end_irqrestore(&stats->syncp, flags);
+       }
+ }
+-- 
+2.34.1
+
diff --git a/queue-5.15/cifs-fix-confusing-unneeded-warning-message-on-smb2..patch b/queue-5.15/cifs-fix-confusing-unneeded-warning-message-on-smb2..patch
new file mode 100644 (file)
index 0000000..e981cce
--- /dev/null
@@ -0,0 +1,58 @@
+From d448d6efbea220fbff7b81afa09ba55e8dc7ec51 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 16 Feb 2022 13:23:53 -0600
+Subject: cifs: fix confusing unneeded warning message on smb2.1 and earlier
+
+From: Steve French <stfrench@microsoft.com>
+
+[ Upstream commit 53923e0fe2098f90f339510aeaa0e1413ae99a16 ]
+
+When mounting with SMB2.1 or earlier, even with nomultichannel, we
+log the confusing warning message:
+  "CIFS: VFS: multichannel is not supported on this protocol version, use 3.0 or above"
+
+Fix this so that we don't log this unless they really are trying
+to mount with multichannel.
+
+BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=215608
+Reported-by: Kim Scarborough <kim@scarborough.kim>
+Cc: stable@vger.kernel.org # 5.11+
+Reviewed-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/cifs/sess.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
+index a1e688113645f..5500ea7837845 100644
+--- a/fs/cifs/sess.c
++++ b/fs/cifs/sess.c
+@@ -76,11 +76,6 @@ int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
+       struct cifs_server_iface *ifaces = NULL;
+       size_t iface_count;
+-      if (ses->server->dialect < SMB30_PROT_ID) {
+-              cifs_dbg(VFS, "multichannel is not supported on this protocol version, use 3.0 or above\n");
+-              return 0;
+-      }
+-
+       spin_lock(&ses->chan_lock);
+       new_chan_count = old_chan_count = ses->chan_count;
+@@ -94,6 +89,12 @@ int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
+               return 0;
+       }
++      if (ses->server->dialect < SMB30_PROT_ID) {
++              spin_unlock(&ses->chan_lock);
++              cifs_dbg(VFS, "multichannel is not supported on this protocol version, use 3.0 or above\n");
++              return 0;
++      }
++
+       if (!(ses->server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) {
+               cifs_dbg(VFS, "server %s does not support multichannel\n", ses->server->hostname);
+               ses->chan_max = 1;
+-- 
+2.34.1
+
diff --git a/queue-5.15/cifs-protect-session-channel-fields-with-chan_lock.patch b/queue-5.15/cifs-protect-session-channel-fields-with-chan_lock.patch
new file mode 100644 (file)
index 0000000..4e81f3b
--- /dev/null
@@ -0,0 +1,317 @@
+From 9a8cb59074661248bac0c9c34b676b3263808952 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 19 Jul 2021 10:54:46 +0000
+Subject: cifs: protect session channel fields with chan_lock
+
+From: Shyam Prasad N <sprasad@microsoft.com>
+
+[ Upstream commit 724244cdb3828522109c88e56a0242537aefabe9 ]
+
+Introducing a new spin lock to protect all the channel related
+fields in a cifs_ses struct. This lock should be taken
+whenever dealing with the channel fields, and should be held
+only for very short intervals which will not sleep.
+
+Currently, all channel related fields in cifs_ses structure
+are protected by session_mutex. However, this mutex is held for
+long periods (sometimes while waiting for a reply from server).
+This makes the codepath quite tricky to change.
+
+Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
+Reviewed-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/cifs/cifs_debug.c |  2 ++
+ fs/cifs/cifsglob.h   |  5 +++++
+ fs/cifs/connect.c    | 25 +++++++++++++++++++---
+ fs/cifs/misc.c       |  1 +
+ fs/cifs/sess.c       | 50 +++++++++++++++++++++++++++++++++-----------
+ fs/cifs/transport.c  |  3 +++
+ 6 files changed, 71 insertions(+), 15 deletions(-)
+
+diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
+index 905a901f7f80b..248a8f973cf9c 100644
+--- a/fs/cifs/cifs_debug.c
++++ b/fs/cifs/cifs_debug.c
+@@ -414,12 +414,14 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
+                                  from_kuid(&init_user_ns, ses->linux_uid),
+                                  from_kuid(&init_user_ns, ses->cred_uid));
++                      spin_lock(&ses->chan_lock);
+                       if (ses->chan_count > 1) {
+                               seq_printf(m, "\n\n\tExtra Channels: %zu ",
+                                          ses->chan_count-1);
+                               for (j = 1; j < ses->chan_count; j++)
+                                       cifs_dump_channel(m, j, &ses->chans[j]);
+                       }
++                      spin_unlock(&ses->chan_lock);
+                       seq_puts(m, "\n\n\tShares: ");
+                       j = 0;
+diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
+index 3e5b8e177cfa7..b33835b2943e9 100644
+--- a/fs/cifs/cifsglob.h
++++ b/fs/cifs/cifsglob.h
+@@ -934,16 +934,21 @@ struct cifs_ses {
+        * iface_lock should be taken when accessing any of these fields
+        */
+       spinlock_t iface_lock;
++      /* ========= begin: protected by iface_lock ======== */
+       struct cifs_server_iface *iface_list;
+       size_t iface_count;
+       unsigned long iface_last_update; /* jiffies */
++      /* ========= end: protected by iface_lock ======== */
++      spinlock_t chan_lock;
++      /* ========= begin: protected by chan_lock ======== */
+ #define CIFS_MAX_CHANNELS 16
+       struct cifs_chan chans[CIFS_MAX_CHANNELS];
+       struct cifs_chan *binding_chan;
+       size_t chan_count;
+       size_t chan_max;
+       atomic_t chan_seq; /* round robin state */
++      /* ========= end: protected by chan_lock ======== */
+ };
+ /*
+diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
+index 439f02f1886c1..70da1d27be3db 100644
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -1526,8 +1526,12 @@ static int match_session(struct cifs_ses *ses, struct smb3_fs_context *ctx)
+        * If an existing session is limited to less channels than
+        * requested, it should not be reused
+        */
+-      if (ses->chan_max < ctx->max_channels)
++      spin_lock(&ses->chan_lock);
++      if (ses->chan_max < ctx->max_channels) {
++              spin_unlock(&ses->chan_lock);
+               return 0;
++      }
++      spin_unlock(&ses->chan_lock);
+       switch (ses->sectype) {
+       case Kerberos:
+@@ -1662,6 +1666,7 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
+ void cifs_put_smb_ses(struct cifs_ses *ses)
+ {
+       unsigned int rc, xid;
++      unsigned int chan_count;
+       struct TCP_Server_Info *server = ses->server;
+       cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
+@@ -1703,12 +1708,24 @@ void cifs_put_smb_ses(struct cifs_ses *ses)
+       list_del_init(&ses->smb_ses_list);
+       spin_unlock(&cifs_tcp_ses_lock);
++      spin_lock(&ses->chan_lock);
++      chan_count = ses->chan_count;
++      spin_unlock(&ses->chan_lock);
++
+       /* close any extra channels */
+-      if (ses->chan_count > 1) {
++      if (chan_count > 1) {
+               int i;
+-              for (i = 1; i < ses->chan_count; i++)
++              for (i = 1; i < chan_count; i++) {
++                      /*
++                       * note: for now, we're okay accessing ses->chans
++                       * without chan_lock. But when chans can go away, we'll
++                       * need to introduce ref counting to make sure that chan
++                       * is not freed from under us.
++                       */
+                       cifs_put_tcp_session(ses->chans[i].server, 0);
++                      ses->chans[i].server = NULL;
++              }
+       }
+       sesInfoFree(ses);
+@@ -1959,9 +1976,11 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
+       mutex_lock(&ses->session_mutex);
+       /* add server as first channel */
++      spin_lock(&ses->chan_lock);
+       ses->chans[0].server = server;
+       ses->chan_count = 1;
+       ses->chan_max = ctx->multichannel ? ctx->max_channels:1;
++      spin_unlock(&ses->chan_lock);
+       rc = cifs_negotiate_protocol(xid, ses);
+       if (!rc)
+diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
+index bb1185fff8cc4..0a0d0724c4294 100644
+--- a/fs/cifs/misc.c
++++ b/fs/cifs/misc.c
+@@ -75,6 +75,7 @@ sesInfoAlloc(void)
+               INIT_LIST_HEAD(&ret_buf->tcon_list);
+               mutex_init(&ret_buf->session_mutex);
+               spin_lock_init(&ret_buf->iface_lock);
++              spin_lock_init(&ret_buf->chan_lock);
+       }
+       return ret_buf;
+ }
+diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
+index 23e02db7923f6..a1e688113645f 100644
+--- a/fs/cifs/sess.c
++++ b/fs/cifs/sess.c
+@@ -54,41 +54,53 @@ bool is_ses_using_iface(struct cifs_ses *ses, struct cifs_server_iface *iface)
+ {
+       int i;
++      spin_lock(&ses->chan_lock);
+       for (i = 0; i < ses->chan_count; i++) {
+-              if (is_server_using_iface(ses->chans[i].server, iface))
++              if (is_server_using_iface(ses->chans[i].server, iface)) {
++                      spin_unlock(&ses->chan_lock);
+                       return true;
++              }
+       }
++      spin_unlock(&ses->chan_lock);
+       return false;
+ }
+ /* returns number of channels added */
+ int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
+ {
+-      int old_chan_count = ses->chan_count;
+-      int left = ses->chan_max - ses->chan_count;
++      int old_chan_count, new_chan_count;
++      int left;
+       int i = 0;
+       int rc = 0;
+       int tries = 0;
+       struct cifs_server_iface *ifaces = NULL;
+       size_t iface_count;
++      if (ses->server->dialect < SMB30_PROT_ID) {
++              cifs_dbg(VFS, "multichannel is not supported on this protocol version, use 3.0 or above\n");
++              return 0;
++      }
++
++      spin_lock(&ses->chan_lock);
++
++      new_chan_count = old_chan_count = ses->chan_count;
++      left = ses->chan_max - ses->chan_count;
++
+       if (left <= 0) {
+               cifs_dbg(FYI,
+                        "ses already at max_channels (%zu), nothing to open\n",
+                        ses->chan_max);
+-              return 0;
+-      }
+-
+-      if (ses->server->dialect < SMB30_PROT_ID) {
+-              cifs_dbg(VFS, "multichannel is not supported on this protocol version, use 3.0 or above\n");
++              spin_unlock(&ses->chan_lock);
+               return 0;
+       }
+       if (!(ses->server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) {
+               cifs_dbg(VFS, "server %s does not support multichannel\n", ses->server->hostname);
+               ses->chan_max = 1;
++              spin_unlock(&ses->chan_lock);
+               return 0;
+       }
++      spin_unlock(&ses->chan_lock);
+       /*
+        * Make a copy of the iface list at the time and use that
+@@ -142,10 +154,11 @@ int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
+               cifs_dbg(FYI, "successfully opened new channel on iface#%d\n",
+                        i);
+               left--;
++              new_chan_count++;
+       }
+       kfree(ifaces);
+-      return ses->chan_count - old_chan_count;
++      return new_chan_count - old_chan_count;
+ }
+ /*
+@@ -157,10 +170,14 @@ cifs_ses_find_chan(struct cifs_ses *ses, struct TCP_Server_Info *server)
+ {
+       int i;
++      spin_lock(&ses->chan_lock);
+       for (i = 0; i < ses->chan_count; i++) {
+-              if (ses->chans[i].server == server)
++              if (ses->chans[i].server == server) {
++                      spin_unlock(&ses->chan_lock);
+                       return &ses->chans[i];
++              }
+       }
++      spin_unlock(&ses->chan_lock);
+       return NULL;
+ }
+@@ -168,6 +185,7 @@ static int
+ cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
+                    struct cifs_server_iface *iface)
+ {
++      struct TCP_Server_Info *chan_server;
+       struct cifs_chan *chan;
+       struct smb3_fs_context ctx = {NULL};
+       static const char unc_fmt[] = "\\%s\\foo";
+@@ -240,15 +258,20 @@ cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
+              SMB2_CLIENT_GUID_SIZE);
+       ctx.use_client_guid = true;
+-      mutex_lock(&ses->session_mutex);
++      chan_server = cifs_get_tcp_session(&ctx);
++      mutex_lock(&ses->session_mutex);
++      spin_lock(&ses->chan_lock);
+       chan = ses->binding_chan = &ses->chans[ses->chan_count];
+-      chan->server = cifs_get_tcp_session(&ctx);
++      chan->server = chan_server;
+       if (IS_ERR(chan->server)) {
+               rc = PTR_ERR(chan->server);
+               chan->server = NULL;
++              spin_unlock(&ses->chan_lock);
+               goto out;
+       }
++      spin_unlock(&ses->chan_lock);
++
+       spin_lock(&cifs_tcp_ses_lock);
+       chan->server->is_channel = true;
+       spin_unlock(&cifs_tcp_ses_lock);
+@@ -283,8 +306,11 @@ cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
+        * ses to the new server.
+        */
++      spin_lock(&ses->chan_lock);
+       ses->chan_count++;
+       atomic_set(&ses->chan_seq, 0);
++      spin_unlock(&ses->chan_lock);
++
+ out:
+       ses->binding = false;
+       ses->binding_chan = NULL;
+diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
+index b7379329b741c..61ea3d3f95b4a 100644
+--- a/fs/cifs/transport.c
++++ b/fs/cifs/transport.c
+@@ -1044,14 +1044,17 @@ struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses)
+       if (!ses)
+               return NULL;
++      spin_lock(&ses->chan_lock);
+       if (!ses->binding) {
+               /* round robin */
+               if (ses->chan_count > 1) {
+                       index = (uint)atomic_inc_return(&ses->chan_seq);
+                       index %= ses->chan_count;
+               }
++              spin_unlock(&ses->chan_lock);
+               return ses->chans[index].server;
+       } else {
++              spin_unlock(&ses->chan_lock);
+               return cifs_ses_server(ses);
+       }
+ }
+-- 
+2.34.1
+
diff --git a/queue-5.15/dma-buf-cma_heap-fix-mutex-locking-section.patch b/queue-5.15/dma-buf-cma_heap-fix-mutex-locking-section.patch
new file mode 100644 (file)
index 0000000..1bb84d1
--- /dev/null
@@ -0,0 +1,55 @@
+From 2b557880b5c68916a65eb9f2c908842782dd6c0f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Jan 2022 15:35:45 +0800
+Subject: dma-buf: cma_heap: Fix mutex locking section
+
+From: Weizhao Ouyang <o451686892@gmail.com>
+
+[ Upstream commit 54329e6f7beea6af56c1230da293acc97d6a6ee7 ]
+
+Fix cma_heap_buffer mutex locking critical section to protect vmap_cnt
+and vaddr.
+
+Fixes: a5d2d29e24be ("dma-buf: heaps: Move heap-helper logic into the cma_heap implementation")
+Signed-off-by: Weizhao Ouyang <o451686892@gmail.com>
+Acked-by: John Stultz <john.stultz@linaro.org>
+Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220104073545.124244-1-o451686892@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/dma-buf/heaps/cma_heap.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c
+index 0c05b79870f96..83f02bd51dda6 100644
+--- a/drivers/dma-buf/heaps/cma_heap.c
++++ b/drivers/dma-buf/heaps/cma_heap.c
+@@ -124,10 +124,11 @@ static int cma_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
+       struct cma_heap_buffer *buffer = dmabuf->priv;
+       struct dma_heap_attachment *a;
++      mutex_lock(&buffer->lock);
++
+       if (buffer->vmap_cnt)
+               invalidate_kernel_vmap_range(buffer->vaddr, buffer->len);
+-      mutex_lock(&buffer->lock);
+       list_for_each_entry(a, &buffer->attachments, list) {
+               if (!a->mapped)
+                       continue;
+@@ -144,10 +145,11 @@ static int cma_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
+       struct cma_heap_buffer *buffer = dmabuf->priv;
+       struct dma_heap_attachment *a;
++      mutex_lock(&buffer->lock);
++
+       if (buffer->vmap_cnt)
+               flush_kernel_vmap_range(buffer->vaddr, buffer->len);
+-      mutex_lock(&buffer->lock);
+       list_for_each_entry(a, &buffer->attachments, list) {
+               if (!a->mapped)
+                       continue;
+-- 
+2.34.1
+
diff --git a/queue-5.15/drm-amd-display-fix-stream-link_enc-unassigned-durin.patch b/queue-5.15/drm-amd-display-fix-stream-link_enc-unassigned-durin.patch
new file mode 100644 (file)
index 0000000..3e8b36c
--- /dev/null
@@ -0,0 +1,53 @@
+From 6a6f972d42808d8883ea363e57aa4fd60bbd92a7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Jan 2022 12:04:34 -0500
+Subject: drm/amd/display: Fix stream->link_enc unassigned during stream
+ removal
+
+From: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+
+[ Upstream commit 3743e7f6fcb938b7d8b7967e6a9442805e269b3d ]
+
+[Why]
+Found when running igt@kms_atomic.
+
+Userspace attempts to do a TEST_COMMIT when 0 streams which calls
+dc_remove_stream_from_ctx. This in turn calls link_enc_unassign
+which ends up modifying stream->link = NULL directly, causing the
+global link_enc to be removed preventing further link activity
+and future link validation from passing.
+
+[How]
+We take care of link_enc unassignment at the start of
+link_enc_cfg_link_encs_assign so this call is no longer necessary.
+
+Fixes global state from being modified while unlocked.
+
+Reviewed-by: Jimmy Kizito <Jimmy.Kizito@amd.com>
+Acked-by: Jasdeep Dhillon <jdhillon@amd.com>
+Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+index e94546187cf15..7ae409f7dcf8d 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+@@ -1799,9 +1799,6 @@ enum dc_status dc_remove_stream_from_ctx(
+                               dc->res_pool,
+                       del_pipe->stream_res.stream_enc,
+                       false);
+-      /* Release link encoder from stream in new dc_state. */
+-      if (dc->res_pool->funcs->link_enc_unassign)
+-              dc->res_pool->funcs->link_enc_unassign(new_ctx, del_pipe->stream);
+       if (del_pipe->stream_res.audio)
+               update_audio_usage(
+-- 
+2.34.1
+
diff --git a/queue-5.15/drm-amd-display-for-vblank_disable_immediate-check-p.patch b/queue-5.15/drm-amd-display-for-vblank_disable_immediate-check-p.patch
new file mode 100644 (file)
index 0000000..cb323d6
--- /dev/null
@@ -0,0 +1,68 @@
+From c2d45bade27051c302ce27c37a2b42f1aba9ab83 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Feb 2022 19:53:37 +0100
+Subject: drm/amd/display: For vblank_disable_immediate, check PSR is really
+ used
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Michel Dänzer <mdaenzer@redhat.com>
+
+[ Upstream commit 4d22336f903930eb94588b939c310743a3640276 ]
+
+Even if PSR is allowed for a present GPU, there might be no eDP link
+which supports PSR.
+
+Fixes: 708978487304 ("drm/amdgpu/display: Only set vblank_disable_immediate when PSR is not enabled")
+Reviewed-by: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Michel Dänzer <mdaenzer@redhat.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c   | 17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 76967adc51606..cd611444ad177 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -3812,6 +3812,9 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
+       }
+ #endif
++      /* Disable vblank IRQs aggressively for power-saving. */
++      adev_to_drm(adev)->vblank_disable_immediate = true;
++
+       /* loops over all connectors on the board */
+       for (i = 0; i < link_cnt; i++) {
+               struct dc_link *link = NULL;
+@@ -3858,19 +3861,17 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
+                               update_connector_ext_caps(aconnector);
+                       if (amdgpu_dc_feature_mask & DC_PSR_MASK)
+                               amdgpu_dm_set_psr_caps(link);
++
++                      /* TODO: Fix vblank control helpers to delay PSR entry to allow this when
++                       * PSR is also supported.
++                       */
++                      if (link->psr_settings.psr_feature_enabled)
++                              adev_to_drm(adev)->vblank_disable_immediate = false;
+               }
+       }
+-      /*
+-       * Disable vblank IRQs aggressively for power-saving.
+-       *
+-       * TODO: Fix vblank control helpers to delay PSR entry to allow this when PSR
+-       * is also supported.
+-       */
+-      adev_to_drm(adev)->vblank_disable_immediate = !psr_feature_enabled;
+-
+       /* Software is initialized. Now we can register interrupt handlers. */
+       switch (adev->asic_type) {
+ #if defined(CONFIG_DRM_AMD_DC_SI)
+-- 
+2.34.1
+
diff --git a/queue-5.15/drm-amd-display-move-fpu-associated-dcn301-code-to-d.patch b/queue-5.15/drm-amd-display-move-fpu-associated-dcn301-code-to-d.patch
new file mode 100644 (file)
index 0000000..6ae93a1
--- /dev/null
@@ -0,0 +1,986 @@
+From 3c4a40ea8abaa5a00b4fd3006835c6f10e98dc13 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Oct 2021 17:56:55 +0800
+Subject: drm/amd/display: move FPU associated DCN301 code to DML folder
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Qingqing Zhuo <Qingqing.Zhuo@amd.com>
+
+[ Upstream commit 31484207feb23e6cdb12827560442ab294855923 ]
+
+[Why & How]
+As part of the FPU isolation work documented in
+https://patchwork.freedesktop.org/series/93042/, isolate
+code that uses FPU in DCN301 to DML, where all FPU code
+should locate.
+
+Cc: Christian König <christian.koenig@amd.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Tested-by: Zhan Liu <Zhan.Liu@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Qingqing Zhuo <Qingqing.Zhuo@amd.com>
+Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../drm/amd/display/dc/dcn30/dcn30_resource.c |   2 +
+ .../gpu/drm/amd/display/dc/dcn301/Makefile    |  26 --
+ .../amd/display/dc/dcn301/dcn301_resource.c   | 349 +---------------
+ .../amd/display/dc/dcn301/dcn301_resource.h   |   3 +
+ drivers/gpu/drm/amd/display/dc/dml/Makefile   |   3 +
+ .../amd/display/dc/dml/dcn301/dcn301_fpu.c    | 390 ++++++++++++++++++
+ .../amd/display/dc/dml/dcn301/dcn301_fpu.h    |  42 ++
+ 7 files changed, 450 insertions(+), 365 deletions(-)
+ create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c
+ create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.h
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
+index 0294d0cc47595..db4a9d2760cd1 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
+@@ -2319,7 +2319,9 @@ bool dcn30_validate_bandwidth(struct dc *dc,
+               goto validate_out;
+       }
++      DC_FP_START();
+       dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel);
++      DC_FP_END();
+       BW_VAL_TRACE_END_WATERMARKS();
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/Makefile b/drivers/gpu/drm/amd/display/dc/dcn301/Makefile
+index 09264716d1dc9..7aa628c219734 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn301/Makefile
++++ b/drivers/gpu/drm/amd/display/dc/dcn301/Makefile
+@@ -13,32 +13,6 @@
+ DCN301 = dcn301_init.o dcn301_resource.o dcn301_dccg.o \
+               dcn301_dio_link_encoder.o dcn301_hwseq.o dcn301_panel_cntl.o dcn301_hubbub.o
+-ifdef CONFIG_X86
+-CFLAGS_$(AMDDALPATH)/dc/dcn301/dcn301_resource.o := -msse
+-endif
+-
+-ifdef CONFIG_PPC64
+-CFLAGS_$(AMDDALPATH)/dc/dcn301/dcn301_resource.o := -mhard-float -maltivec
+-endif
+-
+-ifdef CONFIG_CC_IS_GCC
+-ifeq ($(call cc-ifversion, -lt, 0701, y), y)
+-IS_OLD_GCC = 1
+-endif
+-CFLAGS_$(AMDDALPATH)/dc/dcn301/dcn301_resource.o += -mhard-float
+-endif
+-
+-ifdef CONFIG_X86
+-ifdef IS_OLD_GCC
+-# Stack alignment mismatch, proceed with caution.
+-# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
+-# (8B stack alignment).
+-CFLAGS_$(AMDDALPATH)/dc/dcn301/dcn301_resource.o += -mpreferred-stack-boundary=4
+-else
+-CFLAGS_$(AMDDALPATH)/dc/dcn301/dcn301_resource.o += -msse2
+-endif
+-endif
+-
+ AMD_DAL_DCN301 = $(addprefix $(AMDDALPATH)/dc/dcn301/,$(DCN301))
+ AMD_DISPLAY_FILES += $(AMD_DAL_DCN301)
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
+index dea358b01791c..d17994bb318f7 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
+@@ -82,6 +82,7 @@
+ #include "dce/dce_i2c.h"
+ #include "dml/dcn30/display_mode_vba_30.h"
++#include "dml/dcn301/dcn301_fpu.h"
+ #include "vm_helper.h"
+ #include "dcn20/dcn20_vmid.h"
+ #include "amdgpu_socbb.h"
+@@ -91,184 +92,6 @@
+ #define DC_LOGGER_INIT(logger)
+-struct _vcs_dpi_ip_params_st dcn3_01_ip = {
+-      .odm_capable = 1,
+-      .gpuvm_enable = 1,
+-      .hostvm_enable = 1,
+-      .gpuvm_max_page_table_levels = 1,
+-      .hostvm_max_page_table_levels = 2,
+-      .hostvm_cached_page_table_levels = 0,
+-      .pte_group_size_bytes = 2048,
+-      .num_dsc = 3,
+-      .rob_buffer_size_kbytes = 184,
+-      .det_buffer_size_kbytes = 184,
+-      .dpte_buffer_size_in_pte_reqs_luma = 64,
+-      .dpte_buffer_size_in_pte_reqs_chroma = 32,
+-      .pde_proc_buffer_size_64k_reqs = 48,
+-      .dpp_output_buffer_pixels = 2560,
+-      .opp_output_buffer_lines = 1,
+-      .pixel_chunk_size_kbytes = 8,
+-      .meta_chunk_size_kbytes = 2,
+-      .writeback_chunk_size_kbytes = 8,
+-      .line_buffer_size_bits = 789504,
+-      .is_line_buffer_bpp_fixed = 0,  // ?
+-      .line_buffer_fixed_bpp = 48,     // ?
+-      .dcc_supported = true,
+-      .writeback_interface_buffer_size_kbytes = 90,
+-      .writeback_line_buffer_buffer_size = 656640,
+-      .max_line_buffer_lines = 12,
+-      .writeback_luma_buffer_size_kbytes = 12,  // writeback_line_buffer_buffer_size = 656640
+-      .writeback_chroma_buffer_size_kbytes = 8,
+-      .writeback_chroma_line_buffer_width_pixels = 4,
+-      .writeback_max_hscl_ratio = 1,
+-      .writeback_max_vscl_ratio = 1,
+-      .writeback_min_hscl_ratio = 1,
+-      .writeback_min_vscl_ratio = 1,
+-      .writeback_max_hscl_taps = 1,
+-      .writeback_max_vscl_taps = 1,
+-      .writeback_line_buffer_luma_buffer_size = 0,
+-      .writeback_line_buffer_chroma_buffer_size = 14643,
+-      .cursor_buffer_size = 8,
+-      .cursor_chunk_size = 2,
+-      .max_num_otg = 4,
+-      .max_num_dpp = 4,
+-      .max_num_wb = 1,
+-      .max_dchub_pscl_bw_pix_per_clk = 4,
+-      .max_pscl_lb_bw_pix_per_clk = 2,
+-      .max_lb_vscl_bw_pix_per_clk = 4,
+-      .max_vscl_hscl_bw_pix_per_clk = 4,
+-      .max_hscl_ratio = 6,
+-      .max_vscl_ratio = 6,
+-      .hscl_mults = 4,
+-      .vscl_mults = 4,
+-      .max_hscl_taps = 8,
+-      .max_vscl_taps = 8,
+-      .dispclk_ramp_margin_percent = 1,
+-      .underscan_factor = 1.11,
+-      .min_vblank_lines = 32,
+-      .dppclk_delay_subtotal = 46,
+-      .dynamic_metadata_vm_enabled = true,
+-      .dppclk_delay_scl_lb_only = 16,
+-      .dppclk_delay_scl = 50,
+-      .dppclk_delay_cnvc_formatter = 27,
+-      .dppclk_delay_cnvc_cursor = 6,
+-      .dispclk_delay_subtotal = 119,
+-      .dcfclk_cstate_latency = 5.2, // SRExitTime
+-      .max_inter_dcn_tile_repeaters = 8,
+-      .max_num_hdmi_frl_outputs = 0,
+-      .odm_combine_4to1_supported = true,
+-
+-      .xfc_supported = false,
+-      .xfc_fill_bw_overhead_percent = 10.0,
+-      .xfc_fill_constant_bytes = 0,
+-      .gfx7_compat_tiling_supported = 0,
+-      .number_of_cursors = 1,
+-};
+-
+-struct _vcs_dpi_soc_bounding_box_st dcn3_01_soc = {
+-      .clock_limits = {
+-                      {
+-                              .state = 0,
+-                              .dram_speed_mts = 2400.0,
+-                              .fabricclk_mhz = 600,
+-                              .socclk_mhz = 278.0,
+-                              .dcfclk_mhz = 400.0,
+-                              .dscclk_mhz = 206.0,
+-                              .dppclk_mhz = 1015.0,
+-                              .dispclk_mhz = 1015.0,
+-                              .phyclk_mhz = 600.0,
+-                      },
+-                      {
+-                              .state = 1,
+-                              .dram_speed_mts = 2400.0,
+-                              .fabricclk_mhz = 688,
+-                              .socclk_mhz = 278.0,
+-                              .dcfclk_mhz = 400.0,
+-                              .dscclk_mhz = 206.0,
+-                              .dppclk_mhz = 1015.0,
+-                              .dispclk_mhz = 1015.0,
+-                              .phyclk_mhz = 600.0,
+-                      },
+-                      {
+-                              .state = 2,
+-                              .dram_speed_mts = 4267.0,
+-                              .fabricclk_mhz = 1067,
+-                              .socclk_mhz = 278.0,
+-                              .dcfclk_mhz = 608.0,
+-                              .dscclk_mhz = 296.0,
+-                              .dppclk_mhz = 1015.0,
+-                              .dispclk_mhz = 1015.0,
+-                              .phyclk_mhz = 810.0,
+-                      },
+-
+-                      {
+-                              .state = 3,
+-                              .dram_speed_mts = 4267.0,
+-                              .fabricclk_mhz = 1067,
+-                              .socclk_mhz = 715.0,
+-                              .dcfclk_mhz = 676.0,
+-                              .dscclk_mhz = 338.0,
+-                              .dppclk_mhz = 1015.0,
+-                              .dispclk_mhz = 1015.0,
+-                              .phyclk_mhz = 810.0,
+-                      },
+-
+-                      {
+-                              .state = 4,
+-                              .dram_speed_mts = 4267.0,
+-                              .fabricclk_mhz = 1067,
+-                              .socclk_mhz = 953.0,
+-                              .dcfclk_mhz = 810.0,
+-                              .dscclk_mhz = 338.0,
+-                              .dppclk_mhz = 1015.0,
+-                              .dispclk_mhz = 1015.0,
+-                              .phyclk_mhz = 810.0,
+-                      },
+-              },
+-
+-      .sr_exit_time_us = 9.0,
+-      .sr_enter_plus_exit_time_us = 11.0,
+-      .urgent_latency_us = 4.0,
+-      .urgent_latency_pixel_data_only_us = 4.0,
+-      .urgent_latency_pixel_mixed_with_vm_data_us = 4.0,
+-      .urgent_latency_vm_data_only_us = 4.0,
+-      .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096,
+-      .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096,
+-      .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096,
+-      .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 80.0,
+-      .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 75.0,
+-      .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0,
+-      .max_avg_sdp_bw_use_normal_percent = 60.0,
+-      .max_avg_dram_bw_use_normal_percent = 60.0,
+-      .writeback_latency_us = 12.0,
+-      .max_request_size_bytes = 256,
+-      .dram_channel_width_bytes = 4,
+-      .fabric_datapath_to_dcn_data_return_bytes = 32,
+-      .dcn_downspread_percent = 0.5,
+-      .downspread_percent = 0.38,
+-      .dram_page_open_time_ns = 50.0,
+-      .dram_rw_turnaround_time_ns = 17.5,
+-      .dram_return_buffer_per_channel_bytes = 8192,
+-      .round_trip_ping_latency_dcfclk_cycles = 191,
+-      .urgent_out_of_order_return_per_channel_bytes = 4096,
+-      .channel_interleave_bytes = 256,
+-      .num_banks = 8,
+-      .num_chans = 4,
+-      .gpuvm_min_page_size_bytes = 4096,
+-      .hostvm_min_page_size_bytes = 4096,
+-      .dram_clock_change_latency_us = 23.84,
+-      .writeback_dram_clock_change_latency_us = 23.0,
+-      .return_bus_width_bytes = 64,
+-      .dispclk_dppclk_vco_speed_mhz = 3550,
+-      .xfc_bus_transport_time_us = 20,      // ?
+-      .xfc_xbuf_latency_tolerance_us = 4,  // ?
+-      .use_urgent_burst_bw = 1,            // ?
+-      .num_states = 5,
+-      .do_urgent_latency_adjustment = false,
+-      .urgent_latency_adjustment_fabric_clock_component_us = 0,
+-      .urgent_latency_adjustment_fabric_clock_reference_mhz = 0,
+-};
+-
+ enum dcn301_clk_src_array_id {
+       DCN301_CLK_SRC_PLL0,
+       DCN301_CLK_SRC_PLL1,
+@@ -1476,8 +1299,6 @@ static struct dc_cap_funcs cap_funcs = {
+       .get_dcc_compression_cap = dcn20_get_dcc_compression_cap
+ };
+-#define fixed16_to_double(x) (((double) x) / ((double) (1 << 16)))
+-#define fixed16_to_double_to_cpu(x) fixed16_to_double(le32_to_cpu(x))
+ static bool is_soc_bounding_box_valid(struct dc *dc)
+ {
+@@ -1504,26 +1325,24 @@ static bool init_soc_bounding_box(struct dc *dc,
+       loaded_ip->max_num_otg = pool->base.res_cap->num_timing_generator;
+       loaded_ip->max_num_dpp = pool->base.pipe_count;
++      DC_FP_START();
+       dcn20_patch_bounding_box(dc, loaded_bb);
++      DC_FP_END();
+       if (dc->ctx->dc_bios->funcs->get_soc_bb_info) {
+               struct bp_soc_bb_info bb_info = {0};
+               if (dc->ctx->dc_bios->funcs->get_soc_bb_info(dc->ctx->dc_bios, &bb_info) == BP_RESULT_OK) {
+-                      if (bb_info.dram_clock_change_latency_100ns > 0)
+-                              dcn3_01_soc.dram_clock_change_latency_us = bb_info.dram_clock_change_latency_100ns * 10;
+-
+-                      if (bb_info.dram_sr_enter_exit_latency_100ns > 0)
+-                              dcn3_01_soc.sr_enter_plus_exit_time_us = bb_info.dram_sr_enter_exit_latency_100ns * 10;
+-
+-                      if (bb_info.dram_sr_exit_latency_100ns > 0)
+-                              dcn3_01_soc.sr_exit_time_us = bb_info.dram_sr_exit_latency_100ns * 10;
++                      DC_FP_START();
++                      dcn301_fpu_init_soc_bounding_box(bb_info);
++                      DC_FP_END();
+               }
+       }
+       return true;
+ }
++
+ static void set_wm_ranges(
+               struct pp_smu_funcs *pp_smu,
+               struct _vcs_dpi_soc_bounding_box_st *loaded_bb)
+@@ -1546,9 +1365,9 @@ static void set_wm_ranges(
+                       ranges.reader_wm_sets[i].wm_inst = i;
+                       ranges.reader_wm_sets[i].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
+                       ranges.reader_wm_sets[i].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
+-                      ranges.reader_wm_sets[i].min_fill_clk_mhz = (i > 0) ? (loaded_bb->clock_limits[i - 1].dram_speed_mts / 16) + 1 : 0;
+-                      ranges.reader_wm_sets[i].max_fill_clk_mhz = loaded_bb->clock_limits[i].dram_speed_mts / 16;
+-
++                      DC_FP_START();
++                      dcn301_fpu_set_wm_ranges(i, &ranges, loaded_bb);
++                      DC_FP_END();
+                       ranges.num_reader_wm_sets = i + 1;
+               }
+@@ -1568,154 +1387,6 @@ static void set_wm_ranges(
+       pp_smu->nv_funcs.set_wm_ranges(&pp_smu->nv_funcs.pp_smu, &ranges);
+ }
+-static void dcn301_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
+-{
+-      struct dcn301_resource_pool *pool = TO_DCN301_RES_POOL(dc->res_pool);
+-      struct clk_limit_table *clk_table = &bw_params->clk_table;
+-      struct _vcs_dpi_voltage_scaling_st clock_limits[DC__VOLTAGE_STATES];
+-      unsigned int i, closest_clk_lvl;
+-      int j;
+-
+-      // Default clock levels are used for diags, which may lead to overclocking.
+-      if (!IS_DIAG_DC(dc->ctx->dce_environment)) {
+-              dcn3_01_ip.max_num_otg = pool->base.res_cap->num_timing_generator;
+-              dcn3_01_ip.max_num_dpp = pool->base.pipe_count;
+-              dcn3_01_soc.num_chans = bw_params->num_channels;
+-
+-              ASSERT(clk_table->num_entries);
+-              for (i = 0; i < clk_table->num_entries; i++) {
+-                      /* loop backwards*/
+-                      for (closest_clk_lvl = 0, j = dcn3_01_soc.num_states - 1; j >= 0; j--) {
+-                              if ((unsigned int) dcn3_01_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) {
+-                                      closest_clk_lvl = j;
+-                                      break;
+-                              }
+-                      }
+-
+-                      clock_limits[i].state = i;
+-                      clock_limits[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz;
+-                      clock_limits[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz;
+-                      clock_limits[i].socclk_mhz = clk_table->entries[i].socclk_mhz;
+-                      clock_limits[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2;
+-
+-                      clock_limits[i].dispclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dispclk_mhz;
+-                      clock_limits[i].dppclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dppclk_mhz;
+-                      clock_limits[i].dram_bw_per_chan_gbps = dcn3_01_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps;
+-                      clock_limits[i].dscclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dscclk_mhz;
+-                      clock_limits[i].dtbclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dtbclk_mhz;
+-                      clock_limits[i].phyclk_d18_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz;
+-                      clock_limits[i].phyclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].phyclk_mhz;
+-              }
+-              for (i = 0; i < clk_table->num_entries; i++)
+-                      dcn3_01_soc.clock_limits[i] = clock_limits[i];
+-              if (clk_table->num_entries) {
+-                      dcn3_01_soc.num_states = clk_table->num_entries;
+-                      /* duplicate last level */
+-                      dcn3_01_soc.clock_limits[dcn3_01_soc.num_states] = dcn3_01_soc.clock_limits[dcn3_01_soc.num_states - 1];
+-                      dcn3_01_soc.clock_limits[dcn3_01_soc.num_states].state = dcn3_01_soc.num_states;
+-              }
+-      }
+-
+-      dcn3_01_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
+-      dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
+-
+-      dml_init_instance(&dc->dml, &dcn3_01_soc, &dcn3_01_ip, DML_PROJECT_DCN30);
+-}
+-
+-static void calculate_wm_set_for_vlevel(
+-              int vlevel,
+-              struct wm_range_table_entry *table_entry,
+-              struct dcn_watermarks *wm_set,
+-              struct display_mode_lib *dml,
+-              display_e2e_pipe_params_st *pipes,
+-              int pipe_cnt)
+-{
+-      double dram_clock_change_latency_cached = dml->soc.dram_clock_change_latency_us;
+-
+-      ASSERT(vlevel < dml->soc.num_states);
+-      /* only pipe 0 is read for voltage and dcf/soc clocks */
+-      pipes[0].clks_cfg.voltage = vlevel;
+-      pipes[0].clks_cfg.dcfclk_mhz = dml->soc.clock_limits[vlevel].dcfclk_mhz;
+-      pipes[0].clks_cfg.socclk_mhz = dml->soc.clock_limits[vlevel].socclk_mhz;
+-
+-      dml->soc.dram_clock_change_latency_us = table_entry->pstate_latency_us;
+-      dml->soc.sr_exit_time_us = table_entry->sr_exit_time_us;
+-      dml->soc.sr_enter_plus_exit_time_us = table_entry->sr_enter_plus_exit_time_us;
+-
+-      wm_set->urgent_ns = get_wm_urgent(dml, pipes, pipe_cnt) * 1000;
+-      wm_set->cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(dml, pipes, pipe_cnt) * 1000;
+-      wm_set->cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(dml, pipes, pipe_cnt) * 1000;
+-      wm_set->cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(dml, pipes, pipe_cnt) * 1000;
+-      wm_set->pte_meta_urgent_ns = get_wm_memory_trip(dml, pipes, pipe_cnt) * 1000;
+-      wm_set->frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(dml, pipes, pipe_cnt) * 1000;
+-      wm_set->frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(dml, pipes, pipe_cnt) * 1000;
+-      wm_set->urgent_latency_ns = get_urgent_latency(dml, pipes, pipe_cnt) * 1000;
+-      dml->soc.dram_clock_change_latency_us = dram_clock_change_latency_cached;
+-
+-}
+-
+-static void dcn301_calculate_wm_and_dlg(
+-              struct dc *dc, struct dc_state *context,
+-              display_e2e_pipe_params_st *pipes,
+-              int pipe_cnt,
+-              int vlevel_req)
+-{
+-      int i, pipe_idx;
+-      int vlevel, vlevel_max;
+-      struct wm_range_table_entry *table_entry;
+-      struct clk_bw_params *bw_params = dc->clk_mgr->bw_params;
+-
+-      ASSERT(bw_params);
+-
+-      vlevel_max = bw_params->clk_table.num_entries - 1;
+-
+-      /* WM Set D */
+-      table_entry = &bw_params->wm_table.entries[WM_D];
+-      if (table_entry->wm_type == WM_TYPE_RETRAINING)
+-              vlevel = 0;
+-      else
+-              vlevel = vlevel_max;
+-      calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.d,
+-                                              &context->bw_ctx.dml, pipes, pipe_cnt);
+-      /* WM Set C */
+-      table_entry = &bw_params->wm_table.entries[WM_C];
+-      vlevel = min(max(vlevel_req, 2), vlevel_max);
+-      calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.c,
+-                                              &context->bw_ctx.dml, pipes, pipe_cnt);
+-      /* WM Set B */
+-      table_entry = &bw_params->wm_table.entries[WM_B];
+-      vlevel = min(max(vlevel_req, 1), vlevel_max);
+-      calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.b,
+-                                              &context->bw_ctx.dml, pipes, pipe_cnt);
+-
+-      /* WM Set A */
+-      table_entry = &bw_params->wm_table.entries[WM_A];
+-      vlevel = min(vlevel_req, vlevel_max);
+-      calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.a,
+-                                              &context->bw_ctx.dml, pipes, pipe_cnt);
+-
+-      for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
+-              if (!context->res_ctx.pipe_ctx[i].stream)
+-                      continue;
+-
+-              pipes[pipe_idx].clks_cfg.dispclk_mhz = get_dispclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt);
+-              pipes[pipe_idx].clks_cfg.dppclk_mhz = get_dppclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
+-
+-              if (dc->config.forced_clocks) {
+-                      pipes[pipe_idx].clks_cfg.dispclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dispclk_mhz;
+-                      pipes[pipe_idx].clks_cfg.dppclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dppclk_mhz;
+-              }
+-              if (dc->debug.min_disp_clk_khz > pipes[pipe_idx].clks_cfg.dispclk_mhz * 1000)
+-                      pipes[pipe_idx].clks_cfg.dispclk_mhz = dc->debug.min_disp_clk_khz / 1000.0;
+-              if (dc->debug.min_dpp_clk_khz > pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000)
+-                      pipes[pipe_idx].clks_cfg.dppclk_mhz = dc->debug.min_dpp_clk_khz / 1000.0;
+-
+-              pipe_idx++;
+-      }
+-
+-      dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel);
+-}
+-
+ static struct resource_funcs dcn301_res_pool_funcs = {
+       .destroy = dcn301_destroy_resource_pool,
+       .link_enc_create = dcn301_link_encoder_create,
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.h b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.h
+index 17e4e91ff4b8e..ae8672680cdd1 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.h
++++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.h
+@@ -32,6 +32,9 @@ struct dc;
+ struct resource_pool;
+ struct _vcs_dpi_display_pipe_params_st;
++extern struct _vcs_dpi_ip_params_st dcn3_01_ip;
++extern struct _vcs_dpi_soc_bounding_box_st dcn3_01_soc;
++
+ struct dcn301_resource_pool {
+       struct resource_pool base;
+ };
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile
+index 9009b92490f34..069f0cf113f30 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/Makefile
++++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile
+@@ -70,6 +70,7 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_mode_vba_30.o := $(dml_ccflags) $(fram
+ CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_rq_dlg_calc_30.o := $(dml_ccflags)
+ CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_mode_vba_31.o := $(dml_ccflags) $(frame_warn_flag)
+ CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_rq_dlg_calc_31.o := $(dml_ccflags)
++CFLAGS_$(AMDDALPATH)/dc/dml/dcn301/dcn301_fpu.o := $(dml_ccflags)
+ CFLAGS_$(AMDDALPATH)/dc/dml/dsc/rc_calc_fpu.o := $(dml_ccflags)
+ CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags)
+ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_rcflags)
+@@ -84,6 +85,7 @@ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn30/display_mode_vba_30.o := $(dml_rcflags)
+ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn30/display_rq_dlg_calc_30.o := $(dml_rcflags)
+ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn31/display_mode_vba_31.o := $(dml_rcflags)
+ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn31/display_rq_dlg_calc_31.o := $(dml_rcflags)
++CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn301/dcn301_fpu.o := $(dml_rcflags)
+ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_rcflags)
+ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dsc/rc_calc_fpu.o  := $(dml_rcflags)
+ endif
+@@ -101,6 +103,7 @@ DML += dcn20/display_rq_dlg_calc_20v2.o dcn20/display_mode_vba_20v2.o
+ DML += dcn21/display_rq_dlg_calc_21.o dcn21/display_mode_vba_21.o
+ DML += dcn30/display_mode_vba_30.o dcn30/display_rq_dlg_calc_30.o
+ DML += dcn31/display_mode_vba_31.o dcn31/display_rq_dlg_calc_31.o
++DML += dcn301/dcn301_fpu.o
+ DML += dsc/rc_calc_fpu.o
+ endif
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c
+new file mode 100644
+index 0000000000000..94c32832a0e7b
+--- /dev/null
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c
+@@ -0,0 +1,390 @@
++/*
++ * Copyright 2019-2021 Advanced Micro Devices, Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * Authors: AMD
++ *
++ */
++#include "resource.h"
++#include "clk_mgr.h"
++#include "dcn20/dcn20_resource.h"
++#include "dcn301/dcn301_resource.h"
++
++#include "dml/dcn20/dcn20_fpu.h"
++#include "dcn301_fpu.h"
++
++#define TO_DCN301_RES_POOL(pool)\
++      container_of(pool, struct dcn301_resource_pool, base)
++
++/* Based on: //vidip/dc/dcn3/doc/architecture/DCN3x_Display_Mode.xlsm#83 */
++struct _vcs_dpi_ip_params_st dcn3_01_ip = {
++      .odm_capable = 1,
++      .gpuvm_enable = 1,
++      .hostvm_enable = 1,
++      .gpuvm_max_page_table_levels = 1,
++      .hostvm_max_page_table_levels = 2,
++      .hostvm_cached_page_table_levels = 0,
++      .pte_group_size_bytes = 2048,
++      .num_dsc = 3,
++      .rob_buffer_size_kbytes = 184,
++      .det_buffer_size_kbytes = 184,
++      .dpte_buffer_size_in_pte_reqs_luma = 64,
++      .dpte_buffer_size_in_pte_reqs_chroma = 32,
++      .pde_proc_buffer_size_64k_reqs = 48,
++      .dpp_output_buffer_pixels = 2560,
++      .opp_output_buffer_lines = 1,
++      .pixel_chunk_size_kbytes = 8,
++      .meta_chunk_size_kbytes = 2,
++      .writeback_chunk_size_kbytes = 8,
++      .line_buffer_size_bits = 789504,
++      .is_line_buffer_bpp_fixed = 0,  // ?
++      .line_buffer_fixed_bpp = 48,     // ?
++      .dcc_supported = true,
++      .writeback_interface_buffer_size_kbytes = 90,
++      .writeback_line_buffer_buffer_size = 656640,
++      .max_line_buffer_lines = 12,
++      .writeback_luma_buffer_size_kbytes = 12,  // writeback_line_buffer_buffer_size = 656640
++      .writeback_chroma_buffer_size_kbytes = 8,
++      .writeback_chroma_line_buffer_width_pixels = 4,
++      .writeback_max_hscl_ratio = 1,
++      .writeback_max_vscl_ratio = 1,
++      .writeback_min_hscl_ratio = 1,
++      .writeback_min_vscl_ratio = 1,
++      .writeback_max_hscl_taps = 1,
++      .writeback_max_vscl_taps = 1,
++      .writeback_line_buffer_luma_buffer_size = 0,
++      .writeback_line_buffer_chroma_buffer_size = 14643,
++      .cursor_buffer_size = 8,
++      .cursor_chunk_size = 2,
++      .max_num_otg = 4,
++      .max_num_dpp = 4,
++      .max_num_wb = 1,
++      .max_dchub_pscl_bw_pix_per_clk = 4,
++      .max_pscl_lb_bw_pix_per_clk = 2,
++      .max_lb_vscl_bw_pix_per_clk = 4,
++      .max_vscl_hscl_bw_pix_per_clk = 4,
++      .max_hscl_ratio = 6,
++      .max_vscl_ratio = 6,
++      .hscl_mults = 4,
++      .vscl_mults = 4,
++      .max_hscl_taps = 8,
++      .max_vscl_taps = 8,
++      .dispclk_ramp_margin_percent = 1,
++      .underscan_factor = 1.11,
++      .min_vblank_lines = 32,
++      .dppclk_delay_subtotal = 46,
++      .dynamic_metadata_vm_enabled = true,
++      .dppclk_delay_scl_lb_only = 16,
++      .dppclk_delay_scl = 50,
++      .dppclk_delay_cnvc_formatter = 27,
++      .dppclk_delay_cnvc_cursor = 6,
++      .dispclk_delay_subtotal = 119,
++      .dcfclk_cstate_latency = 5.2, // SRExitTime
++      .max_inter_dcn_tile_repeaters = 8,
++      .max_num_hdmi_frl_outputs = 0,
++      .odm_combine_4to1_supported = true,
++
++      .xfc_supported = false,
++      .xfc_fill_bw_overhead_percent = 10.0,
++      .xfc_fill_constant_bytes = 0,
++      .gfx7_compat_tiling_supported = 0,
++      .number_of_cursors = 1,
++};
++
++struct _vcs_dpi_soc_bounding_box_st dcn3_01_soc = {
++      .clock_limits = {
++              {
++                      .state = 0,
++                      .dram_speed_mts = 2400.0,
++                      .fabricclk_mhz = 600,
++                      .socclk_mhz = 278.0,
++                      .dcfclk_mhz = 400.0,
++                      .dscclk_mhz = 206.0,
++                      .dppclk_mhz = 1015.0,
++                      .dispclk_mhz = 1015.0,
++                      .phyclk_mhz = 600.0,
++              },
++
++              {
++                      .state = 1,
++                      .dram_speed_mts = 2400.0,
++                      .fabricclk_mhz = 688,
++                      .socclk_mhz = 278.0,
++                      .dcfclk_mhz = 400.0,
++                      .dscclk_mhz = 206.0,
++                      .dppclk_mhz = 1015.0,
++                      .dispclk_mhz = 1015.0,
++                      .phyclk_mhz = 600.0,
++              },
++
++              {
++                      .state = 2,
++                      .dram_speed_mts = 4267.0,
++                      .fabricclk_mhz = 1067,
++                      .socclk_mhz = 278.0,
++                      .dcfclk_mhz = 608.0,
++                      .dscclk_mhz = 296.0,
++                      .dppclk_mhz = 1015.0,
++                      .dispclk_mhz = 1015.0,
++                      .phyclk_mhz = 810.0,
++              },
++
++              {
++                      .state = 3,
++                      .dram_speed_mts = 4267.0,
++                      .fabricclk_mhz = 1067,
++                      .socclk_mhz = 715.0,
++                      .dcfclk_mhz = 676.0,
++                      .dscclk_mhz = 338.0,
++                      .dppclk_mhz = 1015.0,
++                      .dispclk_mhz = 1015.0,
++                      .phyclk_mhz = 810.0,
++              },
++
++              {
++                      .state = 4,
++                      .dram_speed_mts = 4267.0,
++                      .fabricclk_mhz = 1067,
++                      .socclk_mhz = 953.0,
++                      .dcfclk_mhz = 810.0,
++                      .dscclk_mhz = 338.0,
++                      .dppclk_mhz = 1015.0,
++                      .dispclk_mhz = 1015.0,
++                      .phyclk_mhz = 810.0,
++              },
++      },
++
++      .sr_exit_time_us = 9.0,
++      .sr_enter_plus_exit_time_us = 11.0,
++      .urgent_latency_us = 4.0,
++      .urgent_latency_pixel_data_only_us = 4.0,
++      .urgent_latency_pixel_mixed_with_vm_data_us = 4.0,
++      .urgent_latency_vm_data_only_us = 4.0,
++      .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096,
++      .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096,
++      .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096,
++      .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 80.0,
++      .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 75.0,
++      .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0,
++      .max_avg_sdp_bw_use_normal_percent = 60.0,
++      .max_avg_dram_bw_use_normal_percent = 60.0,
++      .writeback_latency_us = 12.0,
++      .max_request_size_bytes = 256,
++      .dram_channel_width_bytes = 4,
++      .fabric_datapath_to_dcn_data_return_bytes = 32,
++      .dcn_downspread_percent = 0.5,
++      .downspread_percent = 0.38,
++      .dram_page_open_time_ns = 50.0,
++      .dram_rw_turnaround_time_ns = 17.5,
++      .dram_return_buffer_per_channel_bytes = 8192,
++      .round_trip_ping_latency_dcfclk_cycles = 191,
++      .urgent_out_of_order_return_per_channel_bytes = 4096,
++      .channel_interleave_bytes = 256,
++      .num_banks = 8,
++      .num_chans = 4,
++      .gpuvm_min_page_size_bytes = 4096,
++      .hostvm_min_page_size_bytes = 4096,
++      .dram_clock_change_latency_us = 23.84,
++      .writeback_dram_clock_change_latency_us = 23.0,
++      .return_bus_width_bytes = 64,
++      .dispclk_dppclk_vco_speed_mhz = 3550,
++      .xfc_bus_transport_time_us = 20,      // ?
++      .xfc_xbuf_latency_tolerance_us = 4,  // ?
++      .use_urgent_burst_bw = 1,            // ?
++      .num_states = 5,
++      .do_urgent_latency_adjustment = false,
++      .urgent_latency_adjustment_fabric_clock_component_us = 0,
++      .urgent_latency_adjustment_fabric_clock_reference_mhz = 0,
++};
++
++static void calculate_wm_set_for_vlevel(int vlevel,
++              struct wm_range_table_entry *table_entry,
++              struct dcn_watermarks *wm_set,
++              struct display_mode_lib *dml,
++              display_e2e_pipe_params_st *pipes,
++              int pipe_cnt)
++{
++      double dram_clock_change_latency_cached = dml->soc.dram_clock_change_latency_us;
++
++      ASSERT(vlevel < dml->soc.num_states);
++      /* only pipe 0 is read for voltage and dcf/soc clocks */
++      pipes[0].clks_cfg.voltage = vlevel;
++      pipes[0].clks_cfg.dcfclk_mhz = dml->soc.clock_limits[vlevel].dcfclk_mhz;
++      pipes[0].clks_cfg.socclk_mhz = dml->soc.clock_limits[vlevel].socclk_mhz;
++
++      dml->soc.dram_clock_change_latency_us = table_entry->pstate_latency_us;
++      dml->soc.sr_exit_time_us = table_entry->sr_exit_time_us;
++      dml->soc.sr_enter_plus_exit_time_us = table_entry->sr_enter_plus_exit_time_us;
++
++      wm_set->urgent_ns = get_wm_urgent(dml, pipes, pipe_cnt) * 1000;
++      wm_set->cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(dml, pipes, pipe_cnt) * 1000;
++      wm_set->cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(dml, pipes, pipe_cnt) * 1000;
++      wm_set->cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(dml, pipes, pipe_cnt) * 1000;
++      wm_set->pte_meta_urgent_ns = get_wm_memory_trip(dml, pipes, pipe_cnt) * 1000;
++      wm_set->frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(dml, pipes, pipe_cnt) * 1000;
++      wm_set->frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(dml, pipes, pipe_cnt) * 1000;
++      wm_set->urgent_latency_ns = get_urgent_latency(dml, pipes, pipe_cnt) * 1000;
++      dml->soc.dram_clock_change_latency_us = dram_clock_change_latency_cached;
++
++}
++
++void dcn301_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
++{
++      struct dcn301_resource_pool *pool = TO_DCN301_RES_POOL(dc->res_pool);
++      struct clk_limit_table *clk_table = &bw_params->clk_table;
++      struct _vcs_dpi_voltage_scaling_st clock_limits[DC__VOLTAGE_STATES];
++      unsigned int i, closest_clk_lvl;
++      int j;
++
++      dc_assert_fp_enabled();
++
++      /* Default clock levels are used for diags, which may lead to overclocking. */
++      if (!IS_DIAG_DC(dc->ctx->dce_environment)) {
++              dcn3_01_ip.max_num_otg = pool->base.res_cap->num_timing_generator;
++              dcn3_01_ip.max_num_dpp = pool->base.pipe_count;
++              dcn3_01_soc.num_chans = bw_params->num_channels;
++
++              ASSERT(clk_table->num_entries);
++              for (i = 0; i < clk_table->num_entries; i++) {
++                      /* loop backwards*/
++                      for (closest_clk_lvl = 0, j = dcn3_01_soc.num_states - 1; j >= 0; j--) {
++                              if ((unsigned int) dcn3_01_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) {
++                                      closest_clk_lvl = j;
++                                      break;
++                              }
++                      }
++
++                      clock_limits[i].state = i;
++                      clock_limits[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz;
++                      clock_limits[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz;
++                      clock_limits[i].socclk_mhz = clk_table->entries[i].socclk_mhz;
++                      clock_limits[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2;
++
++                      clock_limits[i].dispclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dispclk_mhz;
++                      clock_limits[i].dppclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dppclk_mhz;
++                      clock_limits[i].dram_bw_per_chan_gbps = dcn3_01_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps;
++                      clock_limits[i].dscclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dscclk_mhz;
++                      clock_limits[i].dtbclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dtbclk_mhz;
++                      clock_limits[i].phyclk_d18_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz;
++                      clock_limits[i].phyclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].phyclk_mhz;
++              }
++
++              for (i = 0; i < clk_table->num_entries; i++)
++                      dcn3_01_soc.clock_limits[i] = clock_limits[i];
++
++              if (clk_table->num_entries) {
++                      dcn3_01_soc.num_states = clk_table->num_entries;
++                      /* duplicate last level */
++                      dcn3_01_soc.clock_limits[dcn3_01_soc.num_states] = dcn3_01_soc.clock_limits[dcn3_01_soc.num_states - 1];
++                      dcn3_01_soc.clock_limits[dcn3_01_soc.num_states].state = dcn3_01_soc.num_states;
++              }
++      }
++
++      dcn3_01_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
++      dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
++
++      dml_init_instance(&dc->dml, &dcn3_01_soc, &dcn3_01_ip, DML_PROJECT_DCN30);
++}
++
++void dcn301_fpu_set_wm_ranges(int i,
++      struct pp_smu_wm_range_sets *ranges,
++      struct _vcs_dpi_soc_bounding_box_st *loaded_bb)
++{
++      dc_assert_fp_enabled();
++
++      ranges->reader_wm_sets[i].min_fill_clk_mhz = (i > 0) ? (loaded_bb->clock_limits[i - 1].dram_speed_mts / 16) + 1 : 0;
++      ranges->reader_wm_sets[i].max_fill_clk_mhz = loaded_bb->clock_limits[i].dram_speed_mts / 16;
++}
++
++void dcn301_fpu_init_soc_bounding_box(struct bp_soc_bb_info bb_info)
++{
++      dc_assert_fp_enabled();
++
++      if (bb_info.dram_clock_change_latency_100ns > 0)
++              dcn3_01_soc.dram_clock_change_latency_us = bb_info.dram_clock_change_latency_100ns * 10;
++
++      if (bb_info.dram_sr_enter_exit_latency_100ns > 0)
++              dcn3_01_soc.sr_enter_plus_exit_time_us = bb_info.dram_sr_enter_exit_latency_100ns * 10;
++
++      if (bb_info.dram_sr_exit_latency_100ns > 0)
++              dcn3_01_soc.sr_exit_time_us = bb_info.dram_sr_exit_latency_100ns * 10;
++}
++
++void dcn301_calculate_wm_and_dlg(struct dc *dc,
++              struct dc_state *context,
++              display_e2e_pipe_params_st *pipes,
++              int pipe_cnt,
++              int vlevel_req)
++{
++      int i, pipe_idx;
++      int vlevel, vlevel_max;
++      struct wm_range_table_entry *table_entry;
++      struct clk_bw_params *bw_params = dc->clk_mgr->bw_params;
++
++      ASSERT(bw_params);
++      dc_assert_fp_enabled();
++
++      vlevel_max = bw_params->clk_table.num_entries - 1;
++
++      /* WM Set D */
++      table_entry = &bw_params->wm_table.entries[WM_D];
++      if (table_entry->wm_type == WM_TYPE_RETRAINING)
++              vlevel = 0;
++      else
++              vlevel = vlevel_max;
++      calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.d,
++                                              &context->bw_ctx.dml, pipes, pipe_cnt);
++      /* WM Set C */
++      table_entry = &bw_params->wm_table.entries[WM_C];
++      vlevel = min(max(vlevel_req, 2), vlevel_max);
++      calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.c,
++                                              &context->bw_ctx.dml, pipes, pipe_cnt);
++      /* WM Set B */
++      table_entry = &bw_params->wm_table.entries[WM_B];
++      vlevel = min(max(vlevel_req, 1), vlevel_max);
++      calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.b,
++                                              &context->bw_ctx.dml, pipes, pipe_cnt);
++
++      /* WM Set A */
++      table_entry = &bw_params->wm_table.entries[WM_A];
++      vlevel = min(vlevel_req, vlevel_max);
++      calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.a,
++                                              &context->bw_ctx.dml, pipes, pipe_cnt);
++
++      for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
++              if (!context->res_ctx.pipe_ctx[i].stream)
++                      continue;
++
++              pipes[pipe_idx].clks_cfg.dispclk_mhz = get_dispclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt);
++              pipes[pipe_idx].clks_cfg.dppclk_mhz = get_dppclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
++
++              if (dc->config.forced_clocks) {
++                      pipes[pipe_idx].clks_cfg.dispclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dispclk_mhz;
++                      pipes[pipe_idx].clks_cfg.dppclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dppclk_mhz;
++              }
++              if (dc->debug.min_disp_clk_khz > pipes[pipe_idx].clks_cfg.dispclk_mhz * 1000)
++                      pipes[pipe_idx].clks_cfg.dispclk_mhz = dc->debug.min_disp_clk_khz / 1000.0;
++              if (dc->debug.min_dpp_clk_khz > pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000)
++                      pipes[pipe_idx].clks_cfg.dppclk_mhz = dc->debug.min_dpp_clk_khz / 1000.0;
++              pipe_idx++;
++      }
++
++      dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel);
++}
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.h
+new file mode 100644
+index 0000000000000..fc7065d178422
+--- /dev/null
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.h
+@@ -0,0 +1,42 @@
++/*
++ * Copyright 2019-2021 Advanced Micro Devices, Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * Authors: AMD
++ *
++ */
++
++#ifndef __DCN301_FPU_H__
++#define __DCN301_FPU_H__
++
++void dcn301_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params);
++
++void dcn301_fpu_set_wm_ranges(int i,
++      struct pp_smu_wm_range_sets *ranges,
++      struct _vcs_dpi_soc_bounding_box_st *loaded_bb);
++
++void dcn301_fpu_init_soc_bounding_box(struct bp_soc_bb_info bb_info);
++
++void dcn301_calculate_wm_and_dlg(struct dc *dc,
++              struct dc_state *context,
++              display_e2e_pipe_params_st *pipes,
++              int pipe_cnt,
++              int vlevel_req);
++#endif /* __DCN301_FPU_H__*/
+-- 
+2.34.1
+
diff --git a/queue-5.15/drm-amd-display-move-fpu-associated-dsc-code-to-dml-.patch b/queue-5.15/drm-amd-display-move-fpu-associated-dsc-code-to-dml-.patch
new file mode 100644 (file)
index 0000000..98e013c
--- /dev/null
@@ -0,0 +1,861 @@
+From 1c628a8f04ea79bfa944cc534be3215c8cde902e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 31 Aug 2021 07:52:24 -0400
+Subject: drm/amd/display: move FPU associated DSC code to DML folder
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Qingqing Zhuo <qingqing.zhuo@amd.com>
+
+[ Upstream commit d738db6883df3e3c513f9e777c842262693f951b ]
+
+[Why & How]
+As part of the FPU isolation work documented in
+https://patchwork.freedesktop.org/series/93042/, isolate code that uses
+FPU in DSC to DML, where all FPU code should locate.
+
+This change does not refactor any functions but move code around.
+
+Cc: Christian König <christian.koenig@amd.com>
+Cc: Hersen Wu <hersenxs.wu@amd.com>
+Cc: Anson Jacob <Anson.Jacob@amd.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Acked-by: Agustin Gutierrez <agustin.gutierrez@amd.com>
+Tested-by: Anson Jacob <Anson.Jacob@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Qingqing Zhuo <qingqing.zhuo@amd.com>
+Acked-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/dml/Makefile   |   3 +
+ .../amd/display/dc/{ => dml}/dsc/qp_tables.h  |   0
+ .../drm/amd/display/dc/dml/dsc/rc_calc_fpu.c  | 291 ++++++++++++++++++
+ .../drm/amd/display/dc/dml/dsc/rc_calc_fpu.h  |  94 ++++++
+ drivers/gpu/drm/amd/display/dc/dsc/Makefile   |  29 --
+ drivers/gpu/drm/amd/display/dc/dsc/rc_calc.c  | 259 ----------------
+ drivers/gpu/drm/amd/display/dc/dsc/rc_calc.h  |  50 +--
+ .../gpu/drm/amd/display/dc/dsc/rc_calc_dpi.c  |   1 -
+ 8 files changed, 389 insertions(+), 338 deletions(-)
+ rename drivers/gpu/drm/amd/display/dc/{ => dml}/dsc/qp_tables.h (100%)
+ create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.c
+ create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.h
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile
+index 56055df2e8d2e..9009b92490f34 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/Makefile
++++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile
+@@ -70,6 +70,7 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_mode_vba_30.o := $(dml_ccflags) $(fram
+ CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_rq_dlg_calc_30.o := $(dml_ccflags)
+ CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_mode_vba_31.o := $(dml_ccflags) $(frame_warn_flag)
+ CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_rq_dlg_calc_31.o := $(dml_ccflags)
++CFLAGS_$(AMDDALPATH)/dc/dml/dsc/rc_calc_fpu.o := $(dml_ccflags)
+ CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags)
+ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_rcflags)
+ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn2x/dcn2x.o := $(dml_rcflags)
+@@ -84,6 +85,7 @@ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn30/display_rq_dlg_calc_30.o := $(dml_rcfla
+ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn31/display_mode_vba_31.o := $(dml_rcflags)
+ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn31/display_rq_dlg_calc_31.o := $(dml_rcflags)
+ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_rcflags)
++CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dsc/rc_calc_fpu.o  := $(dml_rcflags)
+ endif
+ CFLAGS_$(AMDDALPATH)/dc/dml/dml1_display_rq_dlg_calc.o := $(dml_ccflags)
+ CFLAGS_$(AMDDALPATH)/dc/dml/display_rq_dlg_helpers.o := $(dml_ccflags)
+@@ -99,6 +101,7 @@ DML += dcn20/display_rq_dlg_calc_20v2.o dcn20/display_mode_vba_20v2.o
+ DML += dcn21/display_rq_dlg_calc_21.o dcn21/display_mode_vba_21.o
+ DML += dcn30/display_mode_vba_30.o dcn30/display_rq_dlg_calc_30.o
+ DML += dcn31/display_mode_vba_31.o dcn31/display_rq_dlg_calc_31.o
++DML += dsc/rc_calc_fpu.o
+ endif
+ AMD_DAL_DML = $(addprefix $(AMDDALPATH)/dc/dml/,$(DML))
+diff --git a/drivers/gpu/drm/amd/display/dc/dsc/qp_tables.h b/drivers/gpu/drm/amd/display/dc/dml/dsc/qp_tables.h
+similarity index 100%
+rename from drivers/gpu/drm/amd/display/dc/dsc/qp_tables.h
+rename to drivers/gpu/drm/amd/display/dc/dml/dsc/qp_tables.h
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.c
+new file mode 100644
+index 0000000000000..3ee858f311d12
+--- /dev/null
++++ b/drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.c
+@@ -0,0 +1,291 @@
++/*
++ * Copyright 2021 Advanced Micro Devices, Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * Authors: AMD
++ *
++ */
++
++#include "rc_calc_fpu.h"
++
++#include "qp_tables.h"
++#include "amdgpu_dm/dc_fpu.h"
++
++#define table_hash(mode, bpc, max_min) ((mode << 16) | (bpc << 8) | max_min)
++
++#define MODE_SELECT(val444, val422, val420) \
++      (cm == CM_444 || cm == CM_RGB) ? (val444) : (cm == CM_422 ? (val422) : (val420))
++
++
++#define TABLE_CASE(mode, bpc, max)   case (table_hash(mode, BPC_##bpc, max)): \
++      table = qp_table_##mode##_##bpc##bpc_##max; \
++      table_size = sizeof(qp_table_##mode##_##bpc##bpc_##max)/sizeof(*qp_table_##mode##_##bpc##bpc_##max); \
++      break
++
++static int median3(int a, int b, int c)
++{
++      if (a > b)
++              swap(a, b);
++      if (b > c)
++              swap(b, c);
++      if (a > b)
++              swap(b, c);
++
++      return b;
++}
++
++static double dsc_roundf(double num)
++{
++      if (num < 0.0)
++              num = num - 0.5;
++      else
++              num = num + 0.5;
++
++      return (int)(num);
++}
++
++static double dsc_ceil(double num)
++{
++      double retval = (int)num;
++
++      if (retval != num && num > 0)
++              retval = num + 1;
++
++      return (int)retval;
++}
++
++static void get_qp_set(qp_set qps, enum colour_mode cm, enum bits_per_comp bpc,
++                     enum max_min max_min, float bpp)
++{
++      int mode = MODE_SELECT(444, 422, 420);
++      int sel = table_hash(mode, bpc, max_min);
++      int table_size = 0;
++      int index;
++      const struct qp_entry *table = 0L;
++
++      // alias enum
++      enum { min = DAL_MM_MIN, max = DAL_MM_MAX };
++      switch (sel) {
++              TABLE_CASE(444,  8, max);
++              TABLE_CASE(444,  8, min);
++              TABLE_CASE(444, 10, max);
++              TABLE_CASE(444, 10, min);
++              TABLE_CASE(444, 12, max);
++              TABLE_CASE(444, 12, min);
++              TABLE_CASE(422,  8, max);
++              TABLE_CASE(422,  8, min);
++              TABLE_CASE(422, 10, max);
++              TABLE_CASE(422, 10, min);
++              TABLE_CASE(422, 12, max);
++              TABLE_CASE(422, 12, min);
++              TABLE_CASE(420,  8, max);
++              TABLE_CASE(420,  8, min);
++              TABLE_CASE(420, 10, max);
++              TABLE_CASE(420, 10, min);
++              TABLE_CASE(420, 12, max);
++              TABLE_CASE(420, 12, min);
++      }
++
++      if (table == 0)
++              return;
++
++      index = (bpp - table[0].bpp) * 2;
++
++      /* requested size is bigger than the table */
++      if (index >= table_size) {
++              dm_error("ERROR: Requested rc_calc to find a bpp entry that exceeds the table size\n");
++              return;
++      }
++
++      memcpy(qps, table[index].qps, sizeof(qp_set));
++}
++
++static void get_ofs_set(qp_set ofs, enum colour_mode mode, float bpp)
++{
++      int   *p = ofs;
++
++      if (mode == CM_444 || mode == CM_RGB) {
++              *p++ = (bpp <=  6) ? (0) : ((((bpp >=  8) && (bpp <= 12))) ? (2) : ((bpp >= 15) ? (10) : ((((bpp > 6) && (bpp < 8))) ? (0 + dsc_roundf((bpp -  6) * (2 / 2.0))) : (2 + dsc_roundf((bpp - 12) * (8 / 3.0))))));
++              *p++ = (bpp <=  6) ? (-2) : ((((bpp >=  8) && (bpp <= 12))) ? (0) : ((bpp >= 15) ? (8) : ((((bpp > 6) && (bpp < 8))) ? (-2 + dsc_roundf((bpp -  6) * (2 / 2.0))) : (0 + dsc_roundf((bpp - 12) * (8 / 3.0))))));
++              *p++ = (bpp <=  6) ? (-2) : ((((bpp >=  8) && (bpp <= 12))) ? (0) : ((bpp >= 15) ? (6) : ((((bpp > 6) && (bpp < 8))) ? (-2 + dsc_roundf((bpp -  6) * (2 / 2.0))) : (0 + dsc_roundf((bpp - 12) * (6 / 3.0))))));
++              *p++ = (bpp <=  6) ? (-4) : ((((bpp >=  8) && (bpp <= 12))) ? (-2) : ((bpp >= 15) ? (4) : ((((bpp > 6) && (bpp < 8))) ? (-4 + dsc_roundf((bpp -  6) * (2 / 2.0))) : (-2 + dsc_roundf((bpp - 12) * (6 / 3.0))))));
++              *p++ = (bpp <=  6) ? (-6) : ((((bpp >=  8) && (bpp <= 12))) ? (-4) : ((bpp >= 15) ? (2) : ((((bpp > 6) && (bpp < 8))) ? (-6 + dsc_roundf((bpp -  6) * (2 / 2.0))) : (-4 + dsc_roundf((bpp - 12) * (6 / 3.0))))));
++              *p++ = (bpp <= 12) ? (-6) : ((bpp >= 15) ? (0) : (-6 + dsc_roundf((bpp - 12) * (6 / 3.0))));
++              *p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-2) : (-8 + dsc_roundf((bpp - 12) * (6 / 3.0))));
++              *p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-4) : (-8 + dsc_roundf((bpp - 12) * (4 / 3.0))));
++              *p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-6) : (-8 + dsc_roundf((bpp - 12) * (2 / 3.0))));
++              *p++ = (bpp <= 12) ? (-10) : ((bpp >= 15) ? (-8) : (-10 + dsc_roundf((bpp - 12) * (2 / 3.0))));
++              *p++ = -10;
++              *p++ = (bpp <=  6) ? (-12) : ((bpp >=  8) ? (-10) : (-12 + dsc_roundf((bpp -  6) * (2 / 2.0))));
++              *p++ = -12;
++              *p++ = -12;
++              *p++ = -12;
++      } else if (mode == CM_422) {
++              *p++ = (bpp <=  8) ? (2) : ((bpp >= 10) ? (10) : (2 + dsc_roundf((bpp -  8) * (8 / 2.0))));
++              *p++ = (bpp <=  8) ? (0) : ((bpp >= 10) ? (8) : (0 + dsc_roundf((bpp -  8) * (8 / 2.0))));
++              *p++ = (bpp <=  8) ? (0) : ((bpp >= 10) ? (6) : (0 + dsc_roundf((bpp -  8) * (6 / 2.0))));
++              *p++ = (bpp <=  8) ? (-2) : ((bpp >= 10) ? (4) : (-2 + dsc_roundf((bpp -  8) * (6 / 2.0))));
++              *p++ = (bpp <=  8) ? (-4) : ((bpp >= 10) ? (2) : (-4 + dsc_roundf((bpp -  8) * (6 / 2.0))));
++              *p++ = (bpp <=  8) ? (-6) : ((bpp >= 10) ? (0) : (-6 + dsc_roundf((bpp -  8) * (6 / 2.0))));
++              *p++ = (bpp <=  8) ? (-8) : ((bpp >= 10) ? (-2) : (-8 + dsc_roundf((bpp -  8) * (6 / 2.0))));
++              *p++ = (bpp <=  8) ? (-8) : ((bpp >= 10) ? (-4) : (-8 + dsc_roundf((bpp -  8) * (4 / 2.0))));
++              *p++ = (bpp <=  8) ? (-8) : ((bpp >= 10) ? (-6) : (-8 + dsc_roundf((bpp -  8) * (2 / 2.0))));
++              *p++ = (bpp <=  8) ? (-10) : ((bpp >= 10) ? (-8) : (-10 + dsc_roundf((bpp -  8) * (2 / 2.0))));
++              *p++ = -10;
++              *p++ = (bpp <=  6) ? (-12) : ((bpp >= 7) ? (-10) : (-12 + dsc_roundf((bpp -  6) * (2.0 / 1))));
++              *p++ = -12;
++              *p++ = -12;
++              *p++ = -12;
++      } else {
++              *p++ = (bpp <=  6) ? (2) : ((bpp >=  8) ? (10) : (2 + dsc_roundf((bpp -  6) * (8 / 2.0))));
++              *p++ = (bpp <=  6) ? (0) : ((bpp >=  8) ? (8) : (0 + dsc_roundf((bpp -  6) * (8 / 2.0))));
++              *p++ = (bpp <=  6) ? (0) : ((bpp >=  8) ? (6) : (0 + dsc_roundf((bpp -  6) * (6 / 2.0))));
++              *p++ = (bpp <=  6) ? (-2) : ((bpp >=  8) ? (4) : (-2 + dsc_roundf((bpp -  6) * (6 / 2.0))));
++              *p++ = (bpp <=  6) ? (-4) : ((bpp >=  8) ? (2) : (-4 + dsc_roundf((bpp -  6) * (6 / 2.0))));
++              *p++ = (bpp <=  6) ? (-6) : ((bpp >=  8) ? (0) : (-6 + dsc_roundf((bpp -  6) * (6 / 2.0))));
++              *p++ = (bpp <=  6) ? (-8) : ((bpp >=  8) ? (-2) : (-8 + dsc_roundf((bpp -  6) * (6 / 2.0))));
++              *p++ = (bpp <=  6) ? (-8) : ((bpp >=  8) ? (-4) : (-8 + dsc_roundf((bpp -  6) * (4 / 2.0))));
++              *p++ = (bpp <=  6) ? (-8) : ((bpp >=  8) ? (-6) : (-8 + dsc_roundf((bpp -  6) * (2 / 2.0))));
++              *p++ = (bpp <=  6) ? (-10) : ((bpp >=  8) ? (-8) : (-10 + dsc_roundf((bpp -  6) * (2 / 2.0))));
++              *p++ = -10;
++              *p++ = (bpp <=  4) ? (-12) : ((bpp >=  5) ? (-10) : (-12 + dsc_roundf((bpp -  4) * (2 / 1.0))));
++              *p++ = -12;
++              *p++ = -12;
++              *p++ = -12;
++      }
++}
++
++void _do_calc_rc_params(struct rc_params *rc,
++              enum colour_mode cm,
++              enum bits_per_comp bpc,
++              u16 drm_bpp,
++              bool is_navite_422_or_420,
++              int slice_width,
++              int slice_height,
++              int minor_version)
++{
++      float bpp;
++      float bpp_group;
++      float initial_xmit_delay_factor;
++      int padding_pixels;
++      int i;
++
++      dc_assert_fp_enabled();
++
++      bpp = ((float)drm_bpp / 16.0);
++      /* in native_422 or native_420 modes, the bits_per_pixel is double the
++       * target bpp (the latter is what calc_rc_params expects)
++       */
++      if (is_navite_422_or_420)
++              bpp /= 2.0;
++
++      rc->rc_quant_incr_limit0 = ((bpc == BPC_8) ? 11 : (bpc == BPC_10 ? 15 : 19)) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
++      rc->rc_quant_incr_limit1 = ((bpc == BPC_8) ? 11 : (bpc == BPC_10 ? 15 : 19)) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
++
++      bpp_group = MODE_SELECT(bpp, bpp * 2.0, bpp * 2.0);
++
++      switch (cm) {
++      case CM_420:
++              rc->initial_fullness_offset = (bpp >=  6) ? (2048) : ((bpp <=  4) ? (6144) : ((((bpp >  4) && (bpp <=  5))) ? (6144 - dsc_roundf((bpp - 4) * (512))) : (5632 - dsc_roundf((bpp -  5) * (3584)))));
++              rc->first_line_bpg_offset   = median3(0, (12 + (int) (0.09 *  min(34, slice_height - 8))), (int)((3 * bpc * 3) - (3 * bpp_group)));
++              rc->second_line_bpg_offset  = median3(0, 12, (int)((3 * bpc * 3) - (3 * bpp_group)));
++              break;
++      case CM_422:
++              rc->initial_fullness_offset = (bpp >=  8) ? (2048) : ((bpp <=  7) ? (5632) : (5632 - dsc_roundf((bpp - 7) * (3584))));
++              rc->first_line_bpg_offset   = median3(0, (12 + (int) (0.09 *  min(34, slice_height - 8))), (int)((3 * bpc * 4) - (3 * bpp_group)));
++              rc->second_line_bpg_offset  = 0;
++              break;
++      case CM_444:
++      case CM_RGB:
++              rc->initial_fullness_offset = (bpp >= 12) ? (2048) : ((bpp <=  8) ? (6144) : ((((bpp >  8) && (bpp <= 10))) ? (6144 - dsc_roundf((bpp - 8) * (512 / 2))) : (5632 - dsc_roundf((bpp - 10) * (3584 / 2)))));
++              rc->first_line_bpg_offset   = median3(0, (12 + (int) (0.09 *  min(34, slice_height - 8))), (int)(((3 * bpc + (cm == CM_444 ? 0 : 2)) * 3) - (3 * bpp_group)));
++              rc->second_line_bpg_offset  = 0;
++              break;
++      }
++
++      initial_xmit_delay_factor = (cm == CM_444 || cm == CM_RGB) ? 1.0 : 2.0;
++      rc->initial_xmit_delay = dsc_roundf(8192.0/2.0/bpp/initial_xmit_delay_factor);
++
++      if (cm == CM_422 || cm == CM_420)
++              slice_width /= 2;
++
++      padding_pixels = ((slice_width % 3) != 0) ? (3 - (slice_width % 3)) * (rc->initial_xmit_delay / slice_width) : 0;
++      if (3 * bpp_group >= (((rc->initial_xmit_delay + 2) / 3) * (3 + (cm == CM_422)))) {
++              if ((rc->initial_xmit_delay + padding_pixels) % 3 == 1)
++                      rc->initial_xmit_delay++;
++      }
++
++      rc->flatness_min_qp     = ((bpc == BPC_8) ?  (3) : ((bpc == BPC_10) ? (7)  : (11))) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
++      rc->flatness_max_qp     = ((bpc == BPC_8) ? (12) : ((bpc == BPC_10) ? (16) : (20))) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
++      rc->flatness_det_thresh = 2 << (bpc - 8);
++
++      get_qp_set(rc->qp_min, cm, bpc, DAL_MM_MIN, bpp);
++      get_qp_set(rc->qp_max, cm, bpc, DAL_MM_MAX, bpp);
++      if (cm == CM_444 && minor_version == 1) {
++              for (i = 0; i < QP_SET_SIZE; ++i) {
++                      rc->qp_min[i] = rc->qp_min[i] > 0 ? rc->qp_min[i] - 1 : 0;
++                      rc->qp_max[i] = rc->qp_max[i] > 0 ? rc->qp_max[i] - 1 : 0;
++              }
++      }
++      get_ofs_set(rc->ofs, cm, bpp);
++
++      /* fixed parameters */
++      rc->rc_model_size    = 8192;
++      rc->rc_edge_factor   = 6;
++      rc->rc_tgt_offset_hi = 3;
++      rc->rc_tgt_offset_lo = 3;
++
++      rc->rc_buf_thresh[0] = 896;
++      rc->rc_buf_thresh[1] = 1792;
++      rc->rc_buf_thresh[2] = 2688;
++      rc->rc_buf_thresh[3] = 3584;
++      rc->rc_buf_thresh[4] = 4480;
++      rc->rc_buf_thresh[5] = 5376;
++      rc->rc_buf_thresh[6] = 6272;
++      rc->rc_buf_thresh[7] = 6720;
++      rc->rc_buf_thresh[8] = 7168;
++      rc->rc_buf_thresh[9] = 7616;
++      rc->rc_buf_thresh[10] = 7744;
++      rc->rc_buf_thresh[11] = 7872;
++      rc->rc_buf_thresh[12] = 8000;
++      rc->rc_buf_thresh[13] = 8064;
++}
++
++u32 _do_bytes_per_pixel_calc(int slice_width,
++              u16 drm_bpp,
++              bool is_navite_422_or_420)
++{
++      float bpp;
++      u32 bytes_per_pixel;
++      double d_bytes_per_pixel;
++
++      dc_assert_fp_enabled();
++
++      bpp = ((float)drm_bpp / 16.0);
++      d_bytes_per_pixel = dsc_ceil(bpp * slice_width / 8.0) / slice_width;
++      // TODO: Make sure the formula for calculating this is precise (ceiling
++      // vs. floor, and at what point they should be applied)
++      if (is_navite_422_or_420)
++              d_bytes_per_pixel /= 2;
++
++      bytes_per_pixel = (u32)dsc_ceil(d_bytes_per_pixel * 0x10000000);
++
++      return bytes_per_pixel;
++}
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.h
+new file mode 100644
+index 0000000000000..b93b95409fbe2
+--- /dev/null
++++ b/drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.h
+@@ -0,0 +1,94 @@
++/*
++ * Copyright 2021 Advanced Micro Devices, Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * Authors: AMD
++ *
++ */
++
++#ifndef __RC_CALC_FPU_H__
++#define __RC_CALC_FPU_H__
++
++#include "os_types.h"
++#include <drm/drm_dsc.h>
++
++#define QP_SET_SIZE 15
++
++typedef int qp_set[QP_SET_SIZE];
++
++struct rc_params {
++      int      rc_quant_incr_limit0;
++      int      rc_quant_incr_limit1;
++      int      initial_fullness_offset;
++      int      initial_xmit_delay;
++      int      first_line_bpg_offset;
++      int      second_line_bpg_offset;
++      int      flatness_min_qp;
++      int      flatness_max_qp;
++      int      flatness_det_thresh;
++      qp_set   qp_min;
++      qp_set   qp_max;
++      qp_set   ofs;
++      int      rc_model_size;
++      int      rc_edge_factor;
++      int      rc_tgt_offset_hi;
++      int      rc_tgt_offset_lo;
++      int      rc_buf_thresh[QP_SET_SIZE - 1];
++};
++
++enum colour_mode {
++      CM_RGB,   /* 444 RGB */
++      CM_444,   /* 444 YUV or simple 422 */
++      CM_422,   /* native 422 */
++      CM_420    /* native 420 */
++};
++
++enum bits_per_comp {
++      BPC_8  =  8,
++      BPC_10 = 10,
++      BPC_12 = 12
++};
++
++enum max_min {
++      DAL_MM_MIN = 0,
++      DAL_MM_MAX = 1
++};
++
++struct qp_entry {
++      float         bpp;
++      const qp_set  qps;
++};
++
++typedef struct qp_entry qp_table[];
++
++u32 _do_bytes_per_pixel_calc(int slice_width,
++              u16 drm_bpp,
++              bool is_navite_422_or_420);
++
++void _do_calc_rc_params(struct rc_params *rc,
++              enum colour_mode cm,
++              enum bits_per_comp bpc,
++              u16 drm_bpp,
++              bool is_navite_422_or_420,
++              int slice_width,
++              int slice_height,
++              int minor_version);
++
++#endif
+diff --git a/drivers/gpu/drm/amd/display/dc/dsc/Makefile b/drivers/gpu/drm/amd/display/dc/dsc/Makefile
+index 8d31eb75c6a6e..a2537229ee88b 100644
+--- a/drivers/gpu/drm/amd/display/dc/dsc/Makefile
++++ b/drivers/gpu/drm/amd/display/dc/dsc/Makefile
+@@ -1,35 +1,6 @@
+ # SPDX-License-Identifier: MIT
+ #
+ # Makefile for the 'dsc' sub-component of DAL.
+-
+-ifdef CONFIG_X86
+-dsc_ccflags := -mhard-float -msse
+-endif
+-
+-ifdef CONFIG_PPC64
+-dsc_ccflags := -mhard-float -maltivec
+-endif
+-
+-ifdef CONFIG_CC_IS_GCC
+-ifeq ($(call cc-ifversion, -lt, 0701, y), y)
+-IS_OLD_GCC = 1
+-endif
+-endif
+-
+-ifdef CONFIG_X86
+-ifdef IS_OLD_GCC
+-# Stack alignment mismatch, proceed with caution.
+-# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
+-# (8B stack alignment).
+-dsc_ccflags += -mpreferred-stack-boundary=4
+-else
+-dsc_ccflags += -msse2
+-endif
+-endif
+-
+-CFLAGS_$(AMDDALPATH)/dc/dsc/rc_calc.o := $(dsc_ccflags)
+-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dsc/rc_calc.o := $(dsc_rcflags)
+-
+ DSC = dc_dsc.o rc_calc.o rc_calc_dpi.o
+ AMD_DAL_DSC = $(addprefix $(AMDDALPATH)/dc/dsc/,$(DSC))
+diff --git a/drivers/gpu/drm/amd/display/dc/dsc/rc_calc.c b/drivers/gpu/drm/amd/display/dc/dsc/rc_calc.c
+index 7b294f637881a..b19d3aeb5962c 100644
+--- a/drivers/gpu/drm/amd/display/dc/dsc/rc_calc.c
++++ b/drivers/gpu/drm/amd/display/dc/dsc/rc_calc.c
+@@ -23,266 +23,7 @@
+  * Authors: AMD
+  *
+  */
+-#include <drm/drm_dsc.h>
+-
+-#include "os_types.h"
+ #include "rc_calc.h"
+-#include "qp_tables.h"
+-
+-#define table_hash(mode, bpc, max_min) ((mode << 16) | (bpc << 8) | max_min)
+-
+-#define MODE_SELECT(val444, val422, val420) \
+-      (cm == CM_444 || cm == CM_RGB) ? (val444) : (cm == CM_422 ? (val422) : (val420))
+-
+-
+-#define TABLE_CASE(mode, bpc, max)   case (table_hash(mode, BPC_##bpc, max)): \
+-      table = qp_table_##mode##_##bpc##bpc_##max; \
+-      table_size = sizeof(qp_table_##mode##_##bpc##bpc_##max)/sizeof(*qp_table_##mode##_##bpc##bpc_##max); \
+-      break
+-
+-
+-static void get_qp_set(qp_set qps, enum colour_mode cm, enum bits_per_comp bpc,
+-                     enum max_min max_min, float bpp)
+-{
+-      int mode = MODE_SELECT(444, 422, 420);
+-      int sel = table_hash(mode, bpc, max_min);
+-      int table_size = 0;
+-      int index;
+-      const struct qp_entry *table = 0L;
+-
+-      // alias enum
+-      enum { min = DAL_MM_MIN, max = DAL_MM_MAX };
+-      switch (sel) {
+-              TABLE_CASE(444,  8, max);
+-              TABLE_CASE(444,  8, min);
+-              TABLE_CASE(444, 10, max);
+-              TABLE_CASE(444, 10, min);
+-              TABLE_CASE(444, 12, max);
+-              TABLE_CASE(444, 12, min);
+-              TABLE_CASE(422,  8, max);
+-              TABLE_CASE(422,  8, min);
+-              TABLE_CASE(422, 10, max);
+-              TABLE_CASE(422, 10, min);
+-              TABLE_CASE(422, 12, max);
+-              TABLE_CASE(422, 12, min);
+-              TABLE_CASE(420,  8, max);
+-              TABLE_CASE(420,  8, min);
+-              TABLE_CASE(420, 10, max);
+-              TABLE_CASE(420, 10, min);
+-              TABLE_CASE(420, 12, max);
+-              TABLE_CASE(420, 12, min);
+-      }
+-
+-      if (table == 0)
+-              return;
+-
+-      index = (bpp - table[0].bpp) * 2;
+-
+-      /* requested size is bigger than the table */
+-      if (index >= table_size) {
+-              dm_error("ERROR: Requested rc_calc to find a bpp entry that exceeds the table size\n");
+-              return;
+-      }
+-
+-      memcpy(qps, table[index].qps, sizeof(qp_set));
+-}
+-
+-static double dsc_roundf(double num)
+-{
+-      if (num < 0.0)
+-              num = num - 0.5;
+-      else
+-              num = num + 0.5;
+-
+-      return (int)(num);
+-}
+-
+-static double dsc_ceil(double num)
+-{
+-      double retval = (int)num;
+-
+-      if (retval != num && num > 0)
+-              retval = num + 1;
+-
+-      return (int)retval;
+-}
+-
+-static void get_ofs_set(qp_set ofs, enum colour_mode mode, float bpp)
+-{
+-      int   *p = ofs;
+-
+-      if (mode == CM_444 || mode == CM_RGB) {
+-              *p++ = (bpp <=  6) ? (0) : ((((bpp >=  8) && (bpp <= 12))) ? (2) : ((bpp >= 15) ? (10) : ((((bpp > 6) && (bpp < 8))) ? (0 + dsc_roundf((bpp -  6) * (2 / 2.0))) : (2 + dsc_roundf((bpp - 12) * (8 / 3.0))))));
+-              *p++ = (bpp <=  6) ? (-2) : ((((bpp >=  8) && (bpp <= 12))) ? (0) : ((bpp >= 15) ? (8) : ((((bpp > 6) && (bpp < 8))) ? (-2 + dsc_roundf((bpp -  6) * (2 / 2.0))) : (0 + dsc_roundf((bpp - 12) * (8 / 3.0))))));
+-              *p++ = (bpp <=  6) ? (-2) : ((((bpp >=  8) && (bpp <= 12))) ? (0) : ((bpp >= 15) ? (6) : ((((bpp > 6) && (bpp < 8))) ? (-2 + dsc_roundf((bpp -  6) * (2 / 2.0))) : (0 + dsc_roundf((bpp - 12) * (6 / 3.0))))));
+-              *p++ = (bpp <=  6) ? (-4) : ((((bpp >=  8) && (bpp <= 12))) ? (-2) : ((bpp >= 15) ? (4) : ((((bpp > 6) && (bpp < 8))) ? (-4 + dsc_roundf((bpp -  6) * (2 / 2.0))) : (-2 + dsc_roundf((bpp - 12) * (6 / 3.0))))));
+-              *p++ = (bpp <=  6) ? (-6) : ((((bpp >=  8) && (bpp <= 12))) ? (-4) : ((bpp >= 15) ? (2) : ((((bpp > 6) && (bpp < 8))) ? (-6 + dsc_roundf((bpp -  6) * (2 / 2.0))) : (-4 + dsc_roundf((bpp - 12) * (6 / 3.0))))));
+-              *p++ = (bpp <= 12) ? (-6) : ((bpp >= 15) ? (0) : (-6 + dsc_roundf((bpp - 12) * (6 / 3.0))));
+-              *p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-2) : (-8 + dsc_roundf((bpp - 12) * (6 / 3.0))));
+-              *p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-4) : (-8 + dsc_roundf((bpp - 12) * (4 / 3.0))));
+-              *p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-6) : (-8 + dsc_roundf((bpp - 12) * (2 / 3.0))));
+-              *p++ = (bpp <= 12) ? (-10) : ((bpp >= 15) ? (-8) : (-10 + dsc_roundf((bpp - 12) * (2 / 3.0))));
+-              *p++ = -10;
+-              *p++ = (bpp <=  6) ? (-12) : ((bpp >=  8) ? (-10) : (-12 + dsc_roundf((bpp -  6) * (2 / 2.0))));
+-              *p++ = -12;
+-              *p++ = -12;
+-              *p++ = -12;
+-      } else if (mode == CM_422) {
+-              *p++ = (bpp <=  8) ? (2) : ((bpp >= 10) ? (10) : (2 + dsc_roundf((bpp -  8) * (8 / 2.0))));
+-              *p++ = (bpp <=  8) ? (0) : ((bpp >= 10) ? (8) : (0 + dsc_roundf((bpp -  8) * (8 / 2.0))));
+-              *p++ = (bpp <=  8) ? (0) : ((bpp >= 10) ? (6) : (0 + dsc_roundf((bpp -  8) * (6 / 2.0))));
+-              *p++ = (bpp <=  8) ? (-2) : ((bpp >= 10) ? (4) : (-2 + dsc_roundf((bpp -  8) * (6 / 2.0))));
+-              *p++ = (bpp <=  8) ? (-4) : ((bpp >= 10) ? (2) : (-4 + dsc_roundf((bpp -  8) * (6 / 2.0))));
+-              *p++ = (bpp <=  8) ? (-6) : ((bpp >= 10) ? (0) : (-6 + dsc_roundf((bpp -  8) * (6 / 2.0))));
+-              *p++ = (bpp <=  8) ? (-8) : ((bpp >= 10) ? (-2) : (-8 + dsc_roundf((bpp -  8) * (6 / 2.0))));
+-              *p++ = (bpp <=  8) ? (-8) : ((bpp >= 10) ? (-4) : (-8 + dsc_roundf((bpp -  8) * (4 / 2.0))));
+-              *p++ = (bpp <=  8) ? (-8) : ((bpp >= 10) ? (-6) : (-8 + dsc_roundf((bpp -  8) * (2 / 2.0))));
+-              *p++ = (bpp <=  8) ? (-10) : ((bpp >= 10) ? (-8) : (-10 + dsc_roundf((bpp -  8) * (2 / 2.0))));
+-              *p++ = -10;
+-              *p++ = (bpp <=  6) ? (-12) : ((bpp >= 7) ? (-10) : (-12 + dsc_roundf((bpp -  6) * (2.0 / 1))));
+-              *p++ = -12;
+-              *p++ = -12;
+-              *p++ = -12;
+-      } else {
+-              *p++ = (bpp <=  6) ? (2) : ((bpp >=  8) ? (10) : (2 + dsc_roundf((bpp -  6) * (8 / 2.0))));
+-              *p++ = (bpp <=  6) ? (0) : ((bpp >=  8) ? (8) : (0 + dsc_roundf((bpp -  6) * (8 / 2.0))));
+-              *p++ = (bpp <=  6) ? (0) : ((bpp >=  8) ? (6) : (0 + dsc_roundf((bpp -  6) * (6 / 2.0))));
+-              *p++ = (bpp <=  6) ? (-2) : ((bpp >=  8) ? (4) : (-2 + dsc_roundf((bpp -  6) * (6 / 2.0))));
+-              *p++ = (bpp <=  6) ? (-4) : ((bpp >=  8) ? (2) : (-4 + dsc_roundf((bpp -  6) * (6 / 2.0))));
+-              *p++ = (bpp <=  6) ? (-6) : ((bpp >=  8) ? (0) : (-6 + dsc_roundf((bpp -  6) * (6 / 2.0))));
+-              *p++ = (bpp <=  6) ? (-8) : ((bpp >=  8) ? (-2) : (-8 + dsc_roundf((bpp -  6) * (6 / 2.0))));
+-              *p++ = (bpp <=  6) ? (-8) : ((bpp >=  8) ? (-4) : (-8 + dsc_roundf((bpp -  6) * (4 / 2.0))));
+-              *p++ = (bpp <=  6) ? (-8) : ((bpp >=  8) ? (-6) : (-8 + dsc_roundf((bpp -  6) * (2 / 2.0))));
+-              *p++ = (bpp <=  6) ? (-10) : ((bpp >=  8) ? (-8) : (-10 + dsc_roundf((bpp -  6) * (2 / 2.0))));
+-              *p++ = -10;
+-              *p++ = (bpp <=  4) ? (-12) : ((bpp >=  5) ? (-10) : (-12 + dsc_roundf((bpp -  4) * (2 / 1.0))));
+-              *p++ = -12;
+-              *p++ = -12;
+-              *p++ = -12;
+-      }
+-}
+-
+-static int median3(int a, int b, int c)
+-{
+-      if (a > b)
+-              swap(a, b);
+-      if (b > c)
+-              swap(b, c);
+-      if (a > b)
+-              swap(b, c);
+-
+-      return b;
+-}
+-
+-static void _do_calc_rc_params(struct rc_params *rc, enum colour_mode cm,
+-                             enum bits_per_comp bpc, u16 drm_bpp,
+-                             bool is_navite_422_or_420,
+-                             int slice_width, int slice_height,
+-                             int minor_version)
+-{
+-      float bpp;
+-      float bpp_group;
+-      float initial_xmit_delay_factor;
+-      int padding_pixels;
+-      int i;
+-
+-      bpp = ((float)drm_bpp / 16.0);
+-      /* in native_422 or native_420 modes, the bits_per_pixel is double the
+-       * target bpp (the latter is what calc_rc_params expects)
+-       */
+-      if (is_navite_422_or_420)
+-              bpp /= 2.0;
+-
+-      rc->rc_quant_incr_limit0 = ((bpc == BPC_8) ? 11 : (bpc == BPC_10 ? 15 : 19)) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
+-      rc->rc_quant_incr_limit1 = ((bpc == BPC_8) ? 11 : (bpc == BPC_10 ? 15 : 19)) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
+-
+-      bpp_group = MODE_SELECT(bpp, bpp * 2.0, bpp * 2.0);
+-
+-      switch (cm) {
+-      case CM_420:
+-              rc->initial_fullness_offset = (bpp >=  6) ? (2048) : ((bpp <=  4) ? (6144) : ((((bpp >  4) && (bpp <=  5))) ? (6144 - dsc_roundf((bpp - 4) * (512))) : (5632 - dsc_roundf((bpp -  5) * (3584)))));
+-              rc->first_line_bpg_offset   = median3(0, (12 + (int) (0.09 *  min(34, slice_height - 8))), (int)((3 * bpc * 3) - (3 * bpp_group)));
+-              rc->second_line_bpg_offset  = median3(0, 12, (int)((3 * bpc * 3) - (3 * bpp_group)));
+-              break;
+-      case CM_422:
+-              rc->initial_fullness_offset = (bpp >=  8) ? (2048) : ((bpp <=  7) ? (5632) : (5632 - dsc_roundf((bpp - 7) * (3584))));
+-              rc->first_line_bpg_offset   = median3(0, (12 + (int) (0.09 *  min(34, slice_height - 8))), (int)((3 * bpc * 4) - (3 * bpp_group)));
+-              rc->second_line_bpg_offset  = 0;
+-              break;
+-      case CM_444:
+-      case CM_RGB:
+-              rc->initial_fullness_offset = (bpp >= 12) ? (2048) : ((bpp <=  8) ? (6144) : ((((bpp >  8) && (bpp <= 10))) ? (6144 - dsc_roundf((bpp - 8) * (512 / 2))) : (5632 - dsc_roundf((bpp - 10) * (3584 / 2)))));
+-              rc->first_line_bpg_offset   = median3(0, (12 + (int) (0.09 *  min(34, slice_height - 8))), (int)(((3 * bpc + (cm == CM_444 ? 0 : 2)) * 3) - (3 * bpp_group)));
+-              rc->second_line_bpg_offset  = 0;
+-              break;
+-      }
+-
+-      initial_xmit_delay_factor = (cm == CM_444 || cm == CM_RGB) ? 1.0 : 2.0;
+-      rc->initial_xmit_delay = dsc_roundf(8192.0/2.0/bpp/initial_xmit_delay_factor);
+-
+-      if (cm == CM_422 || cm == CM_420)
+-              slice_width /= 2;
+-
+-      padding_pixels = ((slice_width % 3) != 0) ? (3 - (slice_width % 3)) * (rc->initial_xmit_delay / slice_width) : 0;
+-      if (3 * bpp_group >= (((rc->initial_xmit_delay + 2) / 3) * (3 + (cm == CM_422)))) {
+-              if ((rc->initial_xmit_delay + padding_pixels) % 3 == 1)
+-                      rc->initial_xmit_delay++;
+-      }
+-
+-      rc->flatness_min_qp     = ((bpc == BPC_8) ?  (3) : ((bpc == BPC_10) ? (7)  : (11))) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
+-      rc->flatness_max_qp     = ((bpc == BPC_8) ? (12) : ((bpc == BPC_10) ? (16) : (20))) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
+-      rc->flatness_det_thresh = 2 << (bpc - 8);
+-
+-      get_qp_set(rc->qp_min, cm, bpc, DAL_MM_MIN, bpp);
+-      get_qp_set(rc->qp_max, cm, bpc, DAL_MM_MAX, bpp);
+-      if (cm == CM_444 && minor_version == 1) {
+-              for (i = 0; i < QP_SET_SIZE; ++i) {
+-                      rc->qp_min[i] = rc->qp_min[i] > 0 ? rc->qp_min[i] - 1 : 0;
+-                      rc->qp_max[i] = rc->qp_max[i] > 0 ? rc->qp_max[i] - 1 : 0;
+-              }
+-      }
+-      get_ofs_set(rc->ofs, cm, bpp);
+-
+-      /* fixed parameters */
+-      rc->rc_model_size    = 8192;
+-      rc->rc_edge_factor   = 6;
+-      rc->rc_tgt_offset_hi = 3;
+-      rc->rc_tgt_offset_lo = 3;
+-
+-      rc->rc_buf_thresh[0] = 896;
+-      rc->rc_buf_thresh[1] = 1792;
+-      rc->rc_buf_thresh[2] = 2688;
+-      rc->rc_buf_thresh[3] = 3584;
+-      rc->rc_buf_thresh[4] = 4480;
+-      rc->rc_buf_thresh[5] = 5376;
+-      rc->rc_buf_thresh[6] = 6272;
+-      rc->rc_buf_thresh[7] = 6720;
+-      rc->rc_buf_thresh[8] = 7168;
+-      rc->rc_buf_thresh[9] = 7616;
+-      rc->rc_buf_thresh[10] = 7744;
+-      rc->rc_buf_thresh[11] = 7872;
+-      rc->rc_buf_thresh[12] = 8000;
+-      rc->rc_buf_thresh[13] = 8064;
+-}
+-
+-static u32 _do_bytes_per_pixel_calc(int slice_width, u16 drm_bpp,
+-                                  bool is_navite_422_or_420)
+-{
+-      float bpp;
+-      u32 bytes_per_pixel;
+-      double d_bytes_per_pixel;
+-
+-      bpp = ((float)drm_bpp / 16.0);
+-      d_bytes_per_pixel = dsc_ceil(bpp * slice_width / 8.0) / slice_width;
+-      // TODO: Make sure the formula for calculating this is precise (ceiling
+-      // vs. floor, and at what point they should be applied)
+-      if (is_navite_422_or_420)
+-              d_bytes_per_pixel /= 2;
+-
+-      bytes_per_pixel = (u32)dsc_ceil(d_bytes_per_pixel * 0x10000000);
+-
+-      return bytes_per_pixel;
+-}
+ /**
+  * calc_rc_params - reads the user's cmdline mode
+diff --git a/drivers/gpu/drm/amd/display/dc/dsc/rc_calc.h b/drivers/gpu/drm/amd/display/dc/dsc/rc_calc.h
+index 262f06afcbf95..c2340e001b578 100644
+--- a/drivers/gpu/drm/amd/display/dc/dsc/rc_calc.h
++++ b/drivers/gpu/drm/amd/display/dc/dsc/rc_calc.h
+@@ -27,55 +27,7 @@
+ #ifndef __RC_CALC_H__
+ #define __RC_CALC_H__
+-
+-#define QP_SET_SIZE 15
+-
+-typedef int qp_set[QP_SET_SIZE];
+-
+-struct rc_params {
+-      int      rc_quant_incr_limit0;
+-      int      rc_quant_incr_limit1;
+-      int      initial_fullness_offset;
+-      int      initial_xmit_delay;
+-      int      first_line_bpg_offset;
+-      int      second_line_bpg_offset;
+-      int      flatness_min_qp;
+-      int      flatness_max_qp;
+-      int      flatness_det_thresh;
+-      qp_set   qp_min;
+-      qp_set   qp_max;
+-      qp_set   ofs;
+-      int      rc_model_size;
+-      int      rc_edge_factor;
+-      int      rc_tgt_offset_hi;
+-      int      rc_tgt_offset_lo;
+-      int      rc_buf_thresh[QP_SET_SIZE - 1];
+-};
+-
+-enum colour_mode {
+-      CM_RGB,   /* 444 RGB */
+-      CM_444,   /* 444 YUV or simple 422 */
+-      CM_422,   /* native 422 */
+-      CM_420    /* native 420 */
+-};
+-
+-enum bits_per_comp {
+-      BPC_8  =  8,
+-      BPC_10 = 10,
+-      BPC_12 = 12
+-};
+-
+-enum max_min {
+-      DAL_MM_MIN = 0,
+-      DAL_MM_MAX = 1
+-};
+-
+-struct qp_entry {
+-      float         bpp;
+-      const qp_set  qps;
+-};
+-
+-typedef struct qp_entry qp_table[];
++#include "dml/dsc/rc_calc_fpu.h"
+ void calc_rc_params(struct rc_params *rc, const struct drm_dsc_config *pps);
+ u32 calc_dsc_bytes_per_pixel(const struct drm_dsc_config *pps);
+diff --git a/drivers/gpu/drm/amd/display/dc/dsc/rc_calc_dpi.c b/drivers/gpu/drm/amd/display/dc/dsc/rc_calc_dpi.c
+index ef830aded5b1c..1e19dd674e5a2 100644
+--- a/drivers/gpu/drm/amd/display/dc/dsc/rc_calc_dpi.c
++++ b/drivers/gpu/drm/amd/display/dc/dsc/rc_calc_dpi.c
+@@ -22,7 +22,6 @@
+  * Authors: AMD
+  *
+  */
+-#include "os_types.h"
+ #include <drm/drm_dsc.h>
+ #include "dscc_types.h"
+ #include "rc_calc.h"
+-- 
+2.34.1
+
diff --git a/queue-5.15/drm-amd-display-update-watermark-values-for-dcn301.patch b/queue-5.15/drm-amd-display-update-watermark-values-for-dcn301.patch
new file mode 100644 (file)
index 0000000..d72d09e
--- /dev/null
@@ -0,0 +1,73 @@
+From 2963c89373196122728d7ae127f32cd2f6f3fe8e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Jan 2022 17:51:53 -0500
+Subject: drm/amd/display: Update watermark values for DCN301
+
+From: Agustin Gutierrez <agustin.gutierrez@amd.com>
+
+[ Upstream commit 2d8ae25d233767171942a9fba5fd8f4a620996be ]
+
+[Why]
+There is underflow / visual corruption DCN301, for high
+bandwidth MST DSC configurations such as 2x1440p144 or 2x4k60.
+
+[How]
+Use up-to-date watermark values for DCN301.
+
+Reviewed-by: Zhan Liu <zhan.liu@amd.com>
+Signed-off-by: Agustin Gutierrez <agustin.gutierrez@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c   | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
+index 3eee32faa208c..329ce4e84b83c 100644
+--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
+@@ -582,32 +582,32 @@ static struct wm_table lpddr5_wm_table = {
+                       .wm_inst = WM_A,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 11.65333,
+-                      .sr_exit_time_us = 7.95,
+-                      .sr_enter_plus_exit_time_us = 9,
++                      .sr_exit_time_us = 13.5,
++                      .sr_enter_plus_exit_time_us = 16.5,
+                       .valid = true,
+               },
+               {
+                       .wm_inst = WM_B,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 11.65333,
+-                      .sr_exit_time_us = 9.82,
+-                      .sr_enter_plus_exit_time_us = 11.196,
++                      .sr_exit_time_us = 13.5,
++                      .sr_enter_plus_exit_time_us = 16.5,
+                       .valid = true,
+               },
+               {
+                       .wm_inst = WM_C,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 11.65333,
+-                      .sr_exit_time_us = 9.89,
+-                      .sr_enter_plus_exit_time_us = 11.24,
++                      .sr_exit_time_us = 13.5,
++                      .sr_enter_plus_exit_time_us = 16.5,
+                       .valid = true,
+               },
+               {
+                       .wm_inst = WM_D,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 11.65333,
+-                      .sr_exit_time_us = 9.748,
+-                      .sr_enter_plus_exit_time_us = 11.102,
++                      .sr_exit_time_us = 13.5,
++                      .sr_enter_plus_exit_time_us = 16.5,
+                       .valid = true,
+               },
+       }
+-- 
+2.34.1
+
diff --git a/queue-5.15/drm-amd-display-use-adjusted-dcn301-watermarks.patch b/queue-5.15/drm-amd-display-use-adjusted-dcn301-watermarks.patch
new file mode 100644 (file)
index 0000000..d4ab54a
--- /dev/null
@@ -0,0 +1,158 @@
+From 31557378affc12371a122565524ff1e538c6b55e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Sep 2021 22:09:01 -0400
+Subject: drm/amd/display: Use adjusted DCN301 watermarks
+
+From: Nikola Cornij <nikola.cornij@amd.com>
+
+[ Upstream commit 808643ea56a2f96a42873d5e11c399957d6493aa ]
+
+[why]
+If DCN30 watermark calc is used for DCN301, the calculated values are
+wrong due to the data structure mismatch between DCN30 and DCN301.
+However, using the original DCN301 watermark values causes underflow.
+
+[how]
+- Add DCN21-style watermark calculations
+- Adjust DCN301 watermark values to remove the underflow
+
+Reviewed-by: Zhan Liu <zhan.liu@amd.com>
+Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Signed-off-by: Nikola Cornij <nikola.cornij@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../display/dc/clk_mgr/dcn301/vg_clk_mgr.c    |  4 +-
+ .../amd/display/dc/dcn301/dcn301_resource.c   | 96 ++++++++++++++++++-
+ 2 files changed, 97 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
+index 7046da14bb2a5..3eee32faa208c 100644
+--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
+@@ -582,8 +582,8 @@ static struct wm_table lpddr5_wm_table = {
+                       .wm_inst = WM_A,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 11.65333,
+-                      .sr_exit_time_us = 5.32,
+-                      .sr_enter_plus_exit_time_us = 6.38,
++                      .sr_exit_time_us = 7.95,
++                      .sr_enter_plus_exit_time_us = 9,
+                       .valid = true,
+               },
+               {
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
+index 26ebe00a55f67..dea358b01791c 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
+@@ -1622,12 +1622,106 @@ static void dcn301_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *b
+       dml_init_instance(&dc->dml, &dcn3_01_soc, &dcn3_01_ip, DML_PROJECT_DCN30);
+ }
++static void calculate_wm_set_for_vlevel(
++              int vlevel,
++              struct wm_range_table_entry *table_entry,
++              struct dcn_watermarks *wm_set,
++              struct display_mode_lib *dml,
++              display_e2e_pipe_params_st *pipes,
++              int pipe_cnt)
++{
++      double dram_clock_change_latency_cached = dml->soc.dram_clock_change_latency_us;
++
++      ASSERT(vlevel < dml->soc.num_states);
++      /* only pipe 0 is read for voltage and dcf/soc clocks */
++      pipes[0].clks_cfg.voltage = vlevel;
++      pipes[0].clks_cfg.dcfclk_mhz = dml->soc.clock_limits[vlevel].dcfclk_mhz;
++      pipes[0].clks_cfg.socclk_mhz = dml->soc.clock_limits[vlevel].socclk_mhz;
++
++      dml->soc.dram_clock_change_latency_us = table_entry->pstate_latency_us;
++      dml->soc.sr_exit_time_us = table_entry->sr_exit_time_us;
++      dml->soc.sr_enter_plus_exit_time_us = table_entry->sr_enter_plus_exit_time_us;
++
++      wm_set->urgent_ns = get_wm_urgent(dml, pipes, pipe_cnt) * 1000;
++      wm_set->cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(dml, pipes, pipe_cnt) * 1000;
++      wm_set->cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(dml, pipes, pipe_cnt) * 1000;
++      wm_set->cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(dml, pipes, pipe_cnt) * 1000;
++      wm_set->pte_meta_urgent_ns = get_wm_memory_trip(dml, pipes, pipe_cnt) * 1000;
++      wm_set->frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(dml, pipes, pipe_cnt) * 1000;
++      wm_set->frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(dml, pipes, pipe_cnt) * 1000;
++      wm_set->urgent_latency_ns = get_urgent_latency(dml, pipes, pipe_cnt) * 1000;
++      dml->soc.dram_clock_change_latency_us = dram_clock_change_latency_cached;
++
++}
++
++static void dcn301_calculate_wm_and_dlg(
++              struct dc *dc, struct dc_state *context,
++              display_e2e_pipe_params_st *pipes,
++              int pipe_cnt,
++              int vlevel_req)
++{
++      int i, pipe_idx;
++      int vlevel, vlevel_max;
++      struct wm_range_table_entry *table_entry;
++      struct clk_bw_params *bw_params = dc->clk_mgr->bw_params;
++
++      ASSERT(bw_params);
++
++      vlevel_max = bw_params->clk_table.num_entries - 1;
++
++      /* WM Set D */
++      table_entry = &bw_params->wm_table.entries[WM_D];
++      if (table_entry->wm_type == WM_TYPE_RETRAINING)
++              vlevel = 0;
++      else
++              vlevel = vlevel_max;
++      calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.d,
++                                              &context->bw_ctx.dml, pipes, pipe_cnt);
++      /* WM Set C */
++      table_entry = &bw_params->wm_table.entries[WM_C];
++      vlevel = min(max(vlevel_req, 2), vlevel_max);
++      calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.c,
++                                              &context->bw_ctx.dml, pipes, pipe_cnt);
++      /* WM Set B */
++      table_entry = &bw_params->wm_table.entries[WM_B];
++      vlevel = min(max(vlevel_req, 1), vlevel_max);
++      calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.b,
++                                              &context->bw_ctx.dml, pipes, pipe_cnt);
++
++      /* WM Set A */
++      table_entry = &bw_params->wm_table.entries[WM_A];
++      vlevel = min(vlevel_req, vlevel_max);
++      calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.a,
++                                              &context->bw_ctx.dml, pipes, pipe_cnt);
++
++      for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
++              if (!context->res_ctx.pipe_ctx[i].stream)
++                      continue;
++
++              pipes[pipe_idx].clks_cfg.dispclk_mhz = get_dispclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt);
++              pipes[pipe_idx].clks_cfg.dppclk_mhz = get_dppclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
++
++              if (dc->config.forced_clocks) {
++                      pipes[pipe_idx].clks_cfg.dispclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dispclk_mhz;
++                      pipes[pipe_idx].clks_cfg.dppclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dppclk_mhz;
++              }
++              if (dc->debug.min_disp_clk_khz > pipes[pipe_idx].clks_cfg.dispclk_mhz * 1000)
++                      pipes[pipe_idx].clks_cfg.dispclk_mhz = dc->debug.min_disp_clk_khz / 1000.0;
++              if (dc->debug.min_dpp_clk_khz > pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000)
++                      pipes[pipe_idx].clks_cfg.dppclk_mhz = dc->debug.min_dpp_clk_khz / 1000.0;
++
++              pipe_idx++;
++      }
++
++      dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel);
++}
++
+ static struct resource_funcs dcn301_res_pool_funcs = {
+       .destroy = dcn301_destroy_resource_pool,
+       .link_enc_create = dcn301_link_encoder_create,
+       .panel_cntl_create = dcn301_panel_cntl_create,
+       .validate_bandwidth = dcn30_validate_bandwidth,
+-      .calculate_wm_and_dlg = dcn30_calculate_wm_and_dlg,
++      .calculate_wm_and_dlg = dcn301_calculate_wm_and_dlg,
+       .update_soc_for_wm_a = dcn30_update_soc_for_wm_a,
+       .populate_dml_pipes = dcn30_populate_dml_pipes_from_context,
+       .acquire_idle_pipe_for_layer = dcn20_acquire_idle_pipe_for_layer,
+-- 
+2.34.1
+
diff --git a/queue-5.15/drm-amd-display-wrap-dcn301_calculate_wm_and_dlg-for.patch b/queue-5.15/drm-amd-display-wrap-dcn301_calculate_wm_and_dlg-for.patch
new file mode 100644 (file)
index 0000000..d27ae56
--- /dev/null
@@ -0,0 +1,73 @@
+From 3d8f884b53616eb732e390e4caf21783958c5503 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Jan 2022 01:23:36 +0100
+Subject: drm/amd/display: Wrap dcn301_calculate_wm_and_dlg for FPU.
+
+From: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
+
+[ Upstream commit 25f1488bdbba63415239ff301fe61a8546140d9f ]
+
+Mirrors the logic for dcn30. Cue lots of WARNs and some
+kernel panics without this fix.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/dc/dcn301/dcn301_resource.c   | 11 +++++++++++
+ .../gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c    |  2 +-
+ .../gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.h    |  2 +-
+ 3 files changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
+index d17994bb318f7..34b01cc8f548b 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
+@@ -1387,6 +1387,17 @@ static void set_wm_ranges(
+       pp_smu->nv_funcs.set_wm_ranges(&pp_smu->nv_funcs.pp_smu, &ranges);
+ }
++static void dcn301_calculate_wm_and_dlg(
++              struct dc *dc, struct dc_state *context,
++              display_e2e_pipe_params_st *pipes,
++              int pipe_cnt,
++              int vlevel)
++{
++      DC_FP_START();
++      dcn301_calculate_wm_and_dlg_fp(dc, context, pipes, pipe_cnt, vlevel);
++      DC_FP_END();
++}
++
+ static struct resource_funcs dcn301_res_pool_funcs = {
+       .destroy = dcn301_destroy_resource_pool,
+       .link_enc_create = dcn301_link_encoder_create,
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c
+index 94c32832a0e7b..0a7a338649731 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c
+@@ -327,7 +327,7 @@ void dcn301_fpu_init_soc_bounding_box(struct bp_soc_bb_info bb_info)
+               dcn3_01_soc.sr_exit_time_us = bb_info.dram_sr_exit_latency_100ns * 10;
+ }
+-void dcn301_calculate_wm_and_dlg(struct dc *dc,
++void dcn301_calculate_wm_and_dlg_fp(struct dc *dc,
+               struct dc_state *context,
+               display_e2e_pipe_params_st *pipes,
+               int pipe_cnt,
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.h
+index fc7065d178422..774b0fdfc80be 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.h
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.h
+@@ -34,7 +34,7 @@ void dcn301_fpu_set_wm_ranges(int i,
+ void dcn301_fpu_init_soc_bounding_box(struct bp_soc_bb_info bb_info);
+-void dcn301_calculate_wm_and_dlg(struct dc *dc,
++void dcn301_calculate_wm_and_dlg_fp(struct dc *dc,
+               struct dc_state *context,
+               display_e2e_pipe_params_st *pipes,
+               int pipe_cnt,
+-- 
+2.34.1
+
diff --git a/queue-5.15/drm-amdgpu-display-only-set-vblank_disable_immediate.patch b/queue-5.15/drm-amdgpu-display-only-set-vblank_disable_immediate.patch
new file mode 100644 (file)
index 0000000..edf58ca
--- /dev/null
@@ -0,0 +1,66 @@
+From 457bc16c2cc5839102e056c5a98c957ff97ddea0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Nov 2021 09:32:33 -0500
+Subject: drm/amdgpu/display: Only set vblank_disable_immediate when PSR is not
+ enabled
+
+From: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+
+[ Upstream commit 70897848730470cc477d5d89e6222c0f6a9ac173 ]
+
+[Why]
+PSR currently relies on the kernel's delayed vblank on/off mechanism
+as an implicit bufferring mechanism to prevent excessive entry/exit.
+
+Without this delay the user experience is impacted since it can take
+a few frames to enter/exit.
+
+[How]
+Only allow vblank disable immediate for DC when psr is not supported.
+
+Leave a TODO indicating that this support should be extended in the
+future to delay independent of the vblank interrupt.
+
+Fixes: 92020e81ddbeac ("drm/amdgpu/display: set vblank_disable_immediate for DC")
+
+Acked-by: Alex Deucher <alexander.deucher@amd.com>
+Reviewed-by: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 5ae9b8133d6da..76967adc51606 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -1279,9 +1279,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
+       adev_to_drm(adev)->mode_config.cursor_width = adev->dm.dc->caps.max_cursor_size;
+       adev_to_drm(adev)->mode_config.cursor_height = adev->dm.dc->caps.max_cursor_size;
+-      /* Disable vblank IRQs aggressively for power-saving */
+-      adev_to_drm(adev)->vblank_disable_immediate = true;
+-
+       if (drm_vblank_init(adev_to_drm(adev), adev->dm.display_indexes_num)) {
+               DRM_ERROR(
+               "amdgpu: failed to initialize sw for display support.\n");
+@@ -3866,6 +3863,14 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
+       }
++      /*
++       * Disable vblank IRQs aggressively for power-saving.
++       *
++       * TODO: Fix vblank control helpers to delay PSR entry to allow this when PSR
++       * is also supported.
++       */
++      adev_to_drm(adev)->vblank_disable_immediate = !psr_feature_enabled;
++
+       /* Software is initialized. Now we can register interrupt handlers. */
+       switch (adev->asic_type) {
+ #if defined(CONFIG_DRM_AMD_DC_SI)
+-- 
+2.34.1
+
diff --git a/queue-5.15/drm-amdgpu-filter-out-radeon-pci-device-ids.patch b/queue-5.15/drm-amdgpu-filter-out-radeon-pci-device-ids.patch
new file mode 100644 (file)
index 0000000..fe0c76a
--- /dev/null
@@ -0,0 +1,692 @@
+From 3cc47c197755ac38101f0e1b38bf5f2adc31600e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Aug 2021 17:17:10 -0400
+Subject: drm/amdgpu: filter out radeon PCI device IDs
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+[ Upstream commit bdbeb0dde4258586bb2f481b12da1e83aa4766f3 ]
+
+Once we claim all 0x1002 PCI display class devices, we will
+need to filter out devices owned by radeon.
+
+v2: rename radeon id array to make it more clear that
+the devices are not supported by amdgpu.
+    add r128, mach64 pci ids as well
+
+Acked-by: Christian König <christian.koenig@amd.com> (v1)
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 638 +++++++++++++++++++++++-
+ 1 file changed, 637 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+index a8465e3195a67..82bb3e80219cd 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+@@ -891,6 +891,636 @@ MODULE_PARM_DESC(smu_pptable_id,
+       "specify pptable id to be used (-1 = auto(default) value, 0 = use pptable from vbios, > 0 = soft pptable id)");
+ module_param_named(smu_pptable_id, amdgpu_smu_pptable_id, int, 0444);
++/* These devices are not supported by amdgpu.
++ * They are supported by the mach64, r128, radeon drivers
++ */
++static const u16 amdgpu_unsupported_pciidlist[] = {
++      /* mach64 */
++      0x4354,
++      0x4358,
++      0x4554,
++      0x4742,
++      0x4744,
++      0x4749,
++      0x474C,
++      0x474D,
++      0x474E,
++      0x474F,
++      0x4750,
++      0x4751,
++      0x4752,
++      0x4753,
++      0x4754,
++      0x4755,
++      0x4756,
++      0x4757,
++      0x4758,
++      0x4759,
++      0x475A,
++      0x4C42,
++      0x4C44,
++      0x4C47,
++      0x4C49,
++      0x4C4D,
++      0x4C4E,
++      0x4C50,
++      0x4C51,
++      0x4C52,
++      0x4C53,
++      0x5654,
++      0x5655,
++      0x5656,
++      /* r128 */
++      0x4c45,
++      0x4c46,
++      0x4d46,
++      0x4d4c,
++      0x5041,
++      0x5042,
++      0x5043,
++      0x5044,
++      0x5045,
++      0x5046,
++      0x5047,
++      0x5048,
++      0x5049,
++      0x504A,
++      0x504B,
++      0x504C,
++      0x504D,
++      0x504E,
++      0x504F,
++      0x5050,
++      0x5051,
++      0x5052,
++      0x5053,
++      0x5054,
++      0x5055,
++      0x5056,
++      0x5057,
++      0x5058,
++      0x5245,
++      0x5246,
++      0x5247,
++      0x524b,
++      0x524c,
++      0x534d,
++      0x5446,
++      0x544C,
++      0x5452,
++      /* radeon */
++      0x3150,
++      0x3151,
++      0x3152,
++      0x3154,
++      0x3155,
++      0x3E50,
++      0x3E54,
++      0x4136,
++      0x4137,
++      0x4144,
++      0x4145,
++      0x4146,
++      0x4147,
++      0x4148,
++      0x4149,
++      0x414A,
++      0x414B,
++      0x4150,
++      0x4151,
++      0x4152,
++      0x4153,
++      0x4154,
++      0x4155,
++      0x4156,
++      0x4237,
++      0x4242,
++      0x4336,
++      0x4337,
++      0x4437,
++      0x4966,
++      0x4967,
++      0x4A48,
++      0x4A49,
++      0x4A4A,
++      0x4A4B,
++      0x4A4C,
++      0x4A4D,
++      0x4A4E,
++      0x4A4F,
++      0x4A50,
++      0x4A54,
++      0x4B48,
++      0x4B49,
++      0x4B4A,
++      0x4B4B,
++      0x4B4C,
++      0x4C57,
++      0x4C58,
++      0x4C59,
++      0x4C5A,
++      0x4C64,
++      0x4C66,
++      0x4C67,
++      0x4E44,
++      0x4E45,
++      0x4E46,
++      0x4E47,
++      0x4E48,
++      0x4E49,
++      0x4E4A,
++      0x4E4B,
++      0x4E50,
++      0x4E51,
++      0x4E52,
++      0x4E53,
++      0x4E54,
++      0x4E56,
++      0x5144,
++      0x5145,
++      0x5146,
++      0x5147,
++      0x5148,
++      0x514C,
++      0x514D,
++      0x5157,
++      0x5158,
++      0x5159,
++      0x515A,
++      0x515E,
++      0x5460,
++      0x5462,
++      0x5464,
++      0x5548,
++      0x5549,
++      0x554A,
++      0x554B,
++      0x554C,
++      0x554D,
++      0x554E,
++      0x554F,
++      0x5550,
++      0x5551,
++      0x5552,
++      0x5554,
++      0x564A,
++      0x564B,
++      0x564F,
++      0x5652,
++      0x5653,
++      0x5657,
++      0x5834,
++      0x5835,
++      0x5954,
++      0x5955,
++      0x5974,
++      0x5975,
++      0x5960,
++      0x5961,
++      0x5962,
++      0x5964,
++      0x5965,
++      0x5969,
++      0x5a41,
++      0x5a42,
++      0x5a61,
++      0x5a62,
++      0x5b60,
++      0x5b62,
++      0x5b63,
++      0x5b64,
++      0x5b65,
++      0x5c61,
++      0x5c63,
++      0x5d48,
++      0x5d49,
++      0x5d4a,
++      0x5d4c,
++      0x5d4d,
++      0x5d4e,
++      0x5d4f,
++      0x5d50,
++      0x5d52,
++      0x5d57,
++      0x5e48,
++      0x5e4a,
++      0x5e4b,
++      0x5e4c,
++      0x5e4d,
++      0x5e4f,
++      0x6700,
++      0x6701,
++      0x6702,
++      0x6703,
++      0x6704,
++      0x6705,
++      0x6706,
++      0x6707,
++      0x6708,
++      0x6709,
++      0x6718,
++      0x6719,
++      0x671c,
++      0x671d,
++      0x671f,
++      0x6720,
++      0x6721,
++      0x6722,
++      0x6723,
++      0x6724,
++      0x6725,
++      0x6726,
++      0x6727,
++      0x6728,
++      0x6729,
++      0x6738,
++      0x6739,
++      0x673e,
++      0x6740,
++      0x6741,
++      0x6742,
++      0x6743,
++      0x6744,
++      0x6745,
++      0x6746,
++      0x6747,
++      0x6748,
++      0x6749,
++      0x674A,
++      0x6750,
++      0x6751,
++      0x6758,
++      0x6759,
++      0x675B,
++      0x675D,
++      0x675F,
++      0x6760,
++      0x6761,
++      0x6762,
++      0x6763,
++      0x6764,
++      0x6765,
++      0x6766,
++      0x6767,
++      0x6768,
++      0x6770,
++      0x6771,
++      0x6772,
++      0x6778,
++      0x6779,
++      0x677B,
++      0x6840,
++      0x6841,
++      0x6842,
++      0x6843,
++      0x6849,
++      0x684C,
++      0x6850,
++      0x6858,
++      0x6859,
++      0x6880,
++      0x6888,
++      0x6889,
++      0x688A,
++      0x688C,
++      0x688D,
++      0x6898,
++      0x6899,
++      0x689b,
++      0x689c,
++      0x689d,
++      0x689e,
++      0x68a0,
++      0x68a1,
++      0x68a8,
++      0x68a9,
++      0x68b0,
++      0x68b8,
++      0x68b9,
++      0x68ba,
++      0x68be,
++      0x68bf,
++      0x68c0,
++      0x68c1,
++      0x68c7,
++      0x68c8,
++      0x68c9,
++      0x68d8,
++      0x68d9,
++      0x68da,
++      0x68de,
++      0x68e0,
++      0x68e1,
++      0x68e4,
++      0x68e5,
++      0x68e8,
++      0x68e9,
++      0x68f1,
++      0x68f2,
++      0x68f8,
++      0x68f9,
++      0x68fa,
++      0x68fe,
++      0x7100,
++      0x7101,
++      0x7102,
++      0x7103,
++      0x7104,
++      0x7105,
++      0x7106,
++      0x7108,
++      0x7109,
++      0x710A,
++      0x710B,
++      0x710C,
++      0x710E,
++      0x710F,
++      0x7140,
++      0x7141,
++      0x7142,
++      0x7143,
++      0x7144,
++      0x7145,
++      0x7146,
++      0x7147,
++      0x7149,
++      0x714A,
++      0x714B,
++      0x714C,
++      0x714D,
++      0x714E,
++      0x714F,
++      0x7151,
++      0x7152,
++      0x7153,
++      0x715E,
++      0x715F,
++      0x7180,
++      0x7181,
++      0x7183,
++      0x7186,
++      0x7187,
++      0x7188,
++      0x718A,
++      0x718B,
++      0x718C,
++      0x718D,
++      0x718F,
++      0x7193,
++      0x7196,
++      0x719B,
++      0x719F,
++      0x71C0,
++      0x71C1,
++      0x71C2,
++      0x71C3,
++      0x71C4,
++      0x71C5,
++      0x71C6,
++      0x71C7,
++      0x71CD,
++      0x71CE,
++      0x71D2,
++      0x71D4,
++      0x71D5,
++      0x71D6,
++      0x71DA,
++      0x71DE,
++      0x7200,
++      0x7210,
++      0x7211,
++      0x7240,
++      0x7243,
++      0x7244,
++      0x7245,
++      0x7246,
++      0x7247,
++      0x7248,
++      0x7249,
++      0x724A,
++      0x724B,
++      0x724C,
++      0x724D,
++      0x724E,
++      0x724F,
++      0x7280,
++      0x7281,
++      0x7283,
++      0x7284,
++      0x7287,
++      0x7288,
++      0x7289,
++      0x728B,
++      0x728C,
++      0x7290,
++      0x7291,
++      0x7293,
++      0x7297,
++      0x7834,
++      0x7835,
++      0x791e,
++      0x791f,
++      0x793f,
++      0x7941,
++      0x7942,
++      0x796c,
++      0x796d,
++      0x796e,
++      0x796f,
++      0x9400,
++      0x9401,
++      0x9402,
++      0x9403,
++      0x9405,
++      0x940A,
++      0x940B,
++      0x940F,
++      0x94A0,
++      0x94A1,
++      0x94A3,
++      0x94B1,
++      0x94B3,
++      0x94B4,
++      0x94B5,
++      0x94B9,
++      0x9440,
++      0x9441,
++      0x9442,
++      0x9443,
++      0x9444,
++      0x9446,
++      0x944A,
++      0x944B,
++      0x944C,
++      0x944E,
++      0x9450,
++      0x9452,
++      0x9456,
++      0x945A,
++      0x945B,
++      0x945E,
++      0x9460,
++      0x9462,
++      0x946A,
++      0x946B,
++      0x947A,
++      0x947B,
++      0x9480,
++      0x9487,
++      0x9488,
++      0x9489,
++      0x948A,
++      0x948F,
++      0x9490,
++      0x9491,
++      0x9495,
++      0x9498,
++      0x949C,
++      0x949E,
++      0x949F,
++      0x94C0,
++      0x94C1,
++      0x94C3,
++      0x94C4,
++      0x94C5,
++      0x94C6,
++      0x94C7,
++      0x94C8,
++      0x94C9,
++      0x94CB,
++      0x94CC,
++      0x94CD,
++      0x9500,
++      0x9501,
++      0x9504,
++      0x9505,
++      0x9506,
++      0x9507,
++      0x9508,
++      0x9509,
++      0x950F,
++      0x9511,
++      0x9515,
++      0x9517,
++      0x9519,
++      0x9540,
++      0x9541,
++      0x9542,
++      0x954E,
++      0x954F,
++      0x9552,
++      0x9553,
++      0x9555,
++      0x9557,
++      0x955f,
++      0x9580,
++      0x9581,
++      0x9583,
++      0x9586,
++      0x9587,
++      0x9588,
++      0x9589,
++      0x958A,
++      0x958B,
++      0x958C,
++      0x958D,
++      0x958E,
++      0x958F,
++      0x9590,
++      0x9591,
++      0x9593,
++      0x9595,
++      0x9596,
++      0x9597,
++      0x9598,
++      0x9599,
++      0x959B,
++      0x95C0,
++      0x95C2,
++      0x95C4,
++      0x95C5,
++      0x95C6,
++      0x95C7,
++      0x95C9,
++      0x95CC,
++      0x95CD,
++      0x95CE,
++      0x95CF,
++      0x9610,
++      0x9611,
++      0x9612,
++      0x9613,
++      0x9614,
++      0x9615,
++      0x9616,
++      0x9640,
++      0x9641,
++      0x9642,
++      0x9643,
++      0x9644,
++      0x9645,
++      0x9647,
++      0x9648,
++      0x9649,
++      0x964a,
++      0x964b,
++      0x964c,
++      0x964e,
++      0x964f,
++      0x9710,
++      0x9711,
++      0x9712,
++      0x9713,
++      0x9714,
++      0x9715,
++      0x9802,
++      0x9803,
++      0x9804,
++      0x9805,
++      0x9806,
++      0x9807,
++      0x9808,
++      0x9809,
++      0x980A,
++      0x9900,
++      0x9901,
++      0x9903,
++      0x9904,
++      0x9905,
++      0x9906,
++      0x9907,
++      0x9908,
++      0x9909,
++      0x990A,
++      0x990B,
++      0x990C,
++      0x990D,
++      0x990E,
++      0x990F,
++      0x9910,
++      0x9913,
++      0x9917,
++      0x9918,
++      0x9919,
++      0x9990,
++      0x9991,
++      0x9992,
++      0x9993,
++      0x9994,
++      0x9995,
++      0x9996,
++      0x9997,
++      0x9998,
++      0x9999,
++      0x999A,
++      0x999B,
++      0x999C,
++      0x999D,
++      0x99A0,
++      0x99A2,
++      0x99A4,
++};
++
+ static const struct pci_device_id pciidlist[] = {
+ #ifdef  CONFIG_DRM_AMDGPU_SI
+       {0x1002, 0x6780, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI},
+@@ -1273,7 +1903,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
+       struct drm_device *ddev;
+       struct amdgpu_device *adev;
+       unsigned long flags = ent->driver_data;
+-      int ret, retry = 0;
++      int ret, retry = 0, i;
+       bool supports_atomic = false;
+       bool is_fw_fb;
+       resource_size_t base, size;
+@@ -1281,6 +1911,12 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
+       if (amdgpu_aspm == -1 && !pcie_aspm_enabled(pdev))
+               amdgpu_aspm = 0;
++      /* skip devices which are owned by radeon */
++      for (i = 0; i < ARRAY_SIZE(amdgpu_unsupported_pciidlist); i++) {
++              if (amdgpu_unsupported_pciidlist[i] == pdev->device)
++                      return -ENODEV;
++      }
++
+       if (amdgpu_virtual_display ||
+           amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK))
+               supports_atomic = true;
+-- 
+2.34.1
+
diff --git a/queue-5.15/drm-amdgpu-filter-out-radeon-secondary-ids-as-well.patch b/queue-5.15/drm-amdgpu-filter-out-radeon-secondary-ids-as-well.patch
new file mode 100644 (file)
index 0000000..e967428
--- /dev/null
@@ -0,0 +1,122 @@
+From 09a0a406a4aad431624510f2d0f6403385e6d157 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Jan 2022 12:17:07 -0500
+Subject: drm/amdgpu: filter out radeon secondary ids as well
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+[ Upstream commit 9e5a14bce2402e84251a10269df0235cd7ce9234 ]
+
+Older radeon boards (r2xx-r5xx) had secondary PCI functions
+which we solely there for supporting multi-head on OSs with
+special requirements.  Add them to the unsupported list
+as well so we don't attempt to bind to them.  The driver
+would fail to bind to them anyway, but this does so
+in a cleaner way that should not confuse the user.
+
+Cc: stable@vger.kernel.org
+Acked-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 81 +++++++++++++++++++++++++
+ 1 file changed, 81 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+index 82bb3e80219cd..5a7fef324c820 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+@@ -1519,6 +1519,87 @@ static const u16 amdgpu_unsupported_pciidlist[] = {
+       0x99A0,
+       0x99A2,
+       0x99A4,
++      /* radeon secondary ids */
++      0x3171,
++      0x3e70,
++      0x4164,
++      0x4165,
++      0x4166,
++      0x4168,
++      0x4170,
++      0x4171,
++      0x4172,
++      0x4173,
++      0x496e,
++      0x4a69,
++      0x4a6a,
++      0x4a6b,
++      0x4a70,
++      0x4a74,
++      0x4b69,
++      0x4b6b,
++      0x4b6c,
++      0x4c6e,
++      0x4e64,
++      0x4e65,
++      0x4e66,
++      0x4e67,
++      0x4e68,
++      0x4e69,
++      0x4e6a,
++      0x4e71,
++      0x4f73,
++      0x5569,
++      0x556b,
++      0x556d,
++      0x556f,
++      0x5571,
++      0x5854,
++      0x5874,
++      0x5940,
++      0x5941,
++      0x5b72,
++      0x5b73,
++      0x5b74,
++      0x5b75,
++      0x5d44,
++      0x5d45,
++      0x5d6d,
++      0x5d6f,
++      0x5d72,
++      0x5d77,
++      0x5e6b,
++      0x5e6d,
++      0x7120,
++      0x7124,
++      0x7129,
++      0x712e,
++      0x712f,
++      0x7162,
++      0x7163,
++      0x7166,
++      0x7167,
++      0x7172,
++      0x7173,
++      0x71a0,
++      0x71a1,
++      0x71a3,
++      0x71a7,
++      0x71bb,
++      0x71e0,
++      0x71e1,
++      0x71e2,
++      0x71e6,
++      0x71e7,
++      0x71f2,
++      0x7269,
++      0x726b,
++      0x726e,
++      0x72a0,
++      0x72a8,
++      0x72b1,
++      0x72b3,
++      0x793f,
+ };
+ static const struct pci_device_id pciidlist[] = {
+-- 
+2.34.1
+
diff --git a/queue-5.15/drm-amdgpu-use-spin_lock_irqsave-to-avoid-deadlock-b.patch b/queue-5.15/drm-amdgpu-use-spin_lock_irqsave-to-avoid-deadlock-b.patch
new file mode 100644 (file)
index 0000000..c1abb33
--- /dev/null
@@ -0,0 +1,59 @@
+From 1078a53ddb07788f4791140faa1b7371c58ef3f4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Jan 2022 16:31:20 +0800
+Subject: drm/amdgpu: use spin_lock_irqsave to avoid deadlock by local
+ interrupt
+
+From: Guchun Chen <guchun.chen@amd.com>
+
+[ Upstream commit 2096b74b1da5ca418827b54ac4904493bd9de89c ]
+
+This is observed in SRIOV case with virtual KMS as display.
+
+_raw_spin_lock_irqsave+0x37/0x40
+drm_handle_vblank+0x69/0x350 [drm]
+? try_to_wake_up+0x432/0x5c0
+? amdgpu_vkms_prepare_fb+0x1c0/0x1c0 [amdgpu]
+drm_crtc_handle_vblank+0x17/0x20 [drm]
+amdgpu_vkms_vblank_simulate+0x4d/0x80 [amdgpu]
+__hrtimer_run_queues+0xfb/0x230
+hrtimer_interrupt+0x109/0x220
+__sysvec_apic_timer_interrupt+0x64/0xe0
+asm_call_irq_on_stack+0x12/0x20
+
+Fixes: 84ec374bd580 ("drm/amdgpu: create amdgpu_vkms (v4)")
+Signed-off-by: Guchun Chen <guchun.chen@amd.com>
+Acked-by: Alex Deucher <alexander.deucher@amd.com>
+Tested-by: Kelly Zytaruk <kelly.zytaruk@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
+index ac9a8cd21c4b6..7d58bf410be05 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
+@@ -142,15 +142,16 @@ static void amdgpu_vkms_crtc_atomic_disable(struct drm_crtc *crtc,
+ static void amdgpu_vkms_crtc_atomic_flush(struct drm_crtc *crtc,
+                                         struct drm_atomic_state *state)
+ {
++      unsigned long flags;
+       if (crtc->state->event) {
+-              spin_lock(&crtc->dev->event_lock);
++              spin_lock_irqsave(&crtc->dev->event_lock, flags);
+               if (drm_crtc_vblank_get(crtc) != 0)
+                       drm_crtc_send_vblank_event(crtc, crtc->state->event);
+               else
+                       drm_crtc_arm_vblank_event(crtc, crtc->state->event);
+-              spin_unlock(&crtc->dev->event_lock);
++              spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+               crtc->state->event = NULL;
+       }
+-- 
+2.34.1
+
diff --git a/queue-5.15/drm-amdkfd-check-for-null-pointer-after-calling-kmem.patch b/queue-5.15/drm-amdkfd-check-for-null-pointer-after-calling-kmem.patch
new file mode 100644 (file)
index 0000000..a69b48d
--- /dev/null
@@ -0,0 +1,41 @@
+From f6be691e2820235a10cb309a022d963871b53215 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Jan 2022 17:09:43 +0800
+Subject: drm/amdkfd: Check for null pointer after calling kmemdup
+
+From: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+
+[ Upstream commit abfaf0eee97925905e742aa3b0b72e04a918fa9e ]
+
+As the possible failure of the allocation, kmemdup() may return NULL
+pointer.
+Therefore, it should be better to check the 'props2' in order to prevent
+the dereference of NULL pointer.
+
+Fixes: 3a87177eb141 ("drm/amdkfd: Add topology support for dGPUs")
+Signed-off-by: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com>
+Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
+index cfedfb1e8596c..c33d689f29e8e 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
+@@ -1060,6 +1060,9 @@ static int kfd_parse_subtype_iolink(struct crat_subtype_iolink *iolink,
+                       return -ENODEV;
+               /* same everything but the other direction */
+               props2 = kmemdup(props, sizeof(*props2), GFP_KERNEL);
++              if (!props2)
++                      return -ENOMEM;
++
+               props2->node_from = id_to;
+               props2->node_to = id_from;
+               props2->kobj = NULL;
+-- 
+2.34.1
+
diff --git a/queue-5.15/drm-atomic-check-new_crtc_state-active-to-determine-.patch b/queue-5.15/drm-atomic-check-new_crtc_state-active-to-determine-.patch
new file mode 100644 (file)
index 0000000..a607ec1
--- /dev/null
@@ -0,0 +1,58 @@
+From 419f0f15ebedba23c94188b6b7e75c4e93b26f14 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Dec 2021 12:06:26 +0800
+Subject: drm/atomic: Check new_crtc_state->active to determine if CRTC needs
+ disable in self refresh mode
+
+From: Liu Ying <victor.liu@nxp.com>
+
+[ Upstream commit 69e630016ef4e4a1745310c446f204dc6243e907 ]
+
+Actual hardware state of CRTC is controlled by the member 'active' in
+struct drm_crtc_state instead of the member 'enable', according to the
+kernel doc of the member 'enable'.  In fact, the drm client modeset
+and atomic helpers are using the member 'active' to do the control.
+
+Referencing the member 'enable' of new_crtc_state, the function
+crtc_needs_disable() may fail to reflect if CRTC needs disable in
+self refresh mode, e.g., when the framebuffer emulation will be blanked
+through the client modeset helper with the next commit, the member
+'enable' of new_crtc_state is still true while the member 'active' is
+false, hence the relevant potential encoder and bridges won't be disabled.
+
+So, let's check new_crtc_state->active to determine if CRTC needs disable
+in self refresh mode instead of new_crtc_state->enable.
+
+Fixes: 1452c25b0e60 ("drm: Add helpers to kick off self refresh mode in drivers")
+Cc: Sean Paul <seanpaul@chromium.org>
+Cc: Rob Clark <robdclark@chromium.org>
+Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
+Cc: Maxime Ripard <mripard@kernel.org>
+Cc: Thomas Zimmermann <tzimmermann@suse.de>
+Cc: David Airlie <airlied@linux.ie>
+Cc: Daniel Vetter <daniel@ffwll.ch>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Liu Ying <victor.liu@nxp.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20211230040626.646807-1-victor.liu@nxp.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/drm_atomic_helper.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
+index 2c0c6ec928200..ff2bc9a118011 100644
+--- a/drivers/gpu/drm/drm_atomic_helper.c
++++ b/drivers/gpu/drm/drm_atomic_helper.c
+@@ -1001,7 +1001,7 @@ crtc_needs_disable(struct drm_crtc_state *old_state,
+        * it's in self refresh mode and needs to be fully disabled.
+        */
+       return old_state->active ||
+-             (old_state->self_refresh_active && !new_state->enable) ||
++             (old_state->self_refresh_active && !new_state->active) ||
+              new_state->self_refresh_active;
+ }
+-- 
+2.34.1
+
diff --git a/queue-5.15/drm-i915-disable-drrs-on-ivb-hsw-port-a.patch b/queue-5.15/drm-i915-disable-drrs-on-ivb-hsw-port-a.patch
new file mode 100644 (file)
index 0000000..d863299
--- /dev/null
@@ -0,0 +1,64 @@
+From 3f197b5b7dbef6c9fe4d1a1be2f817da2d346c7e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Jan 2022 12:37:50 +0200
+Subject: drm/i915: Disable DRRS on IVB/HSW port != A
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Ville Syrjälä <ville.syrjala@linux.intel.com>
+
+[ Upstream commit ee59792c97176f12c1da31f29fc4c2aab187f06e ]
+
+Currently we allow DRRS on IVB PCH ports, but we're missing a
+few programming steps meaning it is guaranteed to not work.
+And on HSW DRRS is not supported on anything but port A ever
+as only transcoder EDP has the M2/N2 registers (though I'm
+not sure if HSW ever has eDP on any other port).
+
+Starting from BDW all transcoders have the dynamically
+reprogrammable M/N registers so DRRS could work on any
+port.
+
+Stop initializing DRRS on ports where it cannot possibly work.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220128103757.22461-11-ville.syrjala@linux.intel.com
+Reviewed-by: Jani Nikula <jani.nikula@intel.com>
+(cherry picked from commit f0d4ce59f4d48622044933054a0e0cefa91ba15e)
+Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/i915/display/intel_drrs.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c
+index be9b6d4482f04..3c7d6bf579484 100644
+--- a/drivers/gpu/drm/i915/display/intel_drrs.c
++++ b/drivers/gpu/drm/i915/display/intel_drrs.c
+@@ -445,6 +445,7 @@ intel_dp_drrs_init(struct intel_connector *connector,
+                  struct drm_display_mode *fixed_mode)
+ {
+       struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
++      struct intel_encoder *encoder = connector->encoder;
+       struct drm_display_mode *downclock_mode = NULL;
+       INIT_DELAYED_WORK(&dev_priv->drrs.work, intel_edp_drrs_downclock_work);
+@@ -456,6 +457,13 @@ intel_dp_drrs_init(struct intel_connector *connector,
+               return NULL;
+       }
++      if ((DISPLAY_VER(dev_priv) < 8 && !HAS_GMCH(dev_priv)) &&
++          encoder->port != PORT_A) {
++              drm_dbg_kms(&dev_priv->drm,
++                          "DRRS only supported on eDP port A\n");
++              return NULL;
++      }
++
+       if (dev_priv->vbt.drrs_type != SEAMLESS_DRRS_SUPPORT) {
+               drm_dbg_kms(&dev_priv->drm, "VBT doesn't support DRRS\n");
+               return NULL;
+-- 
+2.34.1
+
diff --git a/queue-5.15/drm-i915-display-move-drrs-code-its-own-file.patch b/queue-5.15/drm-i915-display-move-drrs-code-its-own-file.patch
new file mode 100644 (file)
index 0000000..13fc669
--- /dev/null
@@ -0,0 +1,1158 @@
+From 466336274bae07f6eace5ba05208328057bf9541 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 27 Aug 2021 10:42:52 -0700
+Subject: drm/i915/display: Move DRRS code its own file
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: José Roberto de Souza <jose.souza@intel.com>
+
+[ Upstream commit a1b63119ee839c8ff622407aab25c9723943638a ]
+
+intel_dp.c is a 5k lines monster, so moving DRRS out of it to reduce
+some lines from it.
+
+Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Cc: Jani Nikula <jani.nikula@intel.com>
+Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20210827174253.51122-2-jose.souza@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/gpu/i915.rst                    |  14 +-
+ drivers/gpu/drm/i915/Makefile                 |   1 +
+ drivers/gpu/drm/i915/display/intel_ddi.c      |   1 +
+ .../drm/i915/display/intel_display_debugfs.c  |   1 +
+ drivers/gpu/drm/i915/display/intel_dp.c       | 467 +----------------
+ drivers/gpu/drm/i915/display/intel_dp.h       |  11 -
+ drivers/gpu/drm/i915/display/intel_drrs.c     | 477 ++++++++++++++++++
+ drivers/gpu/drm/i915/display/intel_drrs.h     |  32 ++
+ .../gpu/drm/i915/display/intel_frontbuffer.c  |   1 +
+ 9 files changed, 521 insertions(+), 484 deletions(-)
+ create mode 100644 drivers/gpu/drm/i915/display/intel_drrs.c
+ create mode 100644 drivers/gpu/drm/i915/display/intel_drrs.h
+
+diff --git a/Documentation/gpu/i915.rst b/Documentation/gpu/i915.rst
+index 204ebdaadb45a..03021dfa0dd81 100644
+--- a/Documentation/gpu/i915.rst
++++ b/Documentation/gpu/i915.rst
+@@ -183,25 +183,25 @@ Frame Buffer Compression (FBC)
+ Display Refresh Rate Switching (DRRS)
+ -------------------------------------
+-.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
++.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
+    :doc: Display Refresh Rate Switching (DRRS)
+-.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
++.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
+    :functions: intel_dp_set_drrs_state
+-.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
++.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
+    :functions: intel_edp_drrs_enable
+-.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
++.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
+    :functions: intel_edp_drrs_disable
+-.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
++.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
+    :functions: intel_edp_drrs_invalidate
+-.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
++.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
+    :functions: intel_edp_drrs_flush
+-.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
++.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
+    :functions: intel_dp_drrs_init
+ DPIO
+diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
+index a4154fe14f8c0..26cf754229451 100644
+--- a/drivers/gpu/drm/i915/Makefile
++++ b/drivers/gpu/drm/i915/Makefile
+@@ -212,6 +212,7 @@ i915-y += \
+       display/intel_dpll.o \
+       display/intel_dpll_mgr.o \
+       display/intel_dpt.o \
++      display/intel_drrs.o \
+       display/intel_dsb.o \
+       display/intel_fb.o \
+       display/intel_fbc.o \
+diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
+index 82e5064b4ce7b..f61901e26409e 100644
+--- a/drivers/gpu/drm/i915/display/intel_ddi.c
++++ b/drivers/gpu/drm/i915/display/intel_ddi.c
+@@ -40,6 +40,7 @@
+ #include "intel_dp_link_training.h"
+ #include "intel_dp_mst.h"
+ #include "intel_dpio_phy.h"
++#include "intel_drrs.h"
+ #include "intel_dsi.h"
+ #include "intel_fdi.h"
+ #include "intel_fifo_underrun.h"
+diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+index 8fdacb252bb19..b136a0fc0963b 100644
+--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
++++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+@@ -13,6 +13,7 @@
+ #include "intel_display_types.h"
+ #include "intel_dmc.h"
+ #include "intel_dp.h"
++#include "intel_drrs.h"
+ #include "intel_fbc.h"
+ #include "intel_hdcp.h"
+ #include "intel_hdmi.h"
+diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
+index d55363f1fa102..dbff4b6aa22bf 100644
+--- a/drivers/gpu/drm/i915/display/intel_dp.c
++++ b/drivers/gpu/drm/i915/display/intel_dp.c
+@@ -56,6 +56,7 @@
+ #include "intel_dp_mst.h"
+ #include "intel_dpio_phy.h"
+ #include "intel_dpll.h"
++#include "intel_drrs.h"
+ #include "intel_fifo_underrun.h"
+ #include "intel_hdcp.h"
+ #include "intel_hdmi.h"
+@@ -1610,46 +1611,6 @@ intel_dp_compute_hdr_metadata_infoframe_sdp(struct intel_dp *intel_dp,
+               intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GAMUT_METADATA);
+ }
+-static void
+-intel_dp_drrs_compute_config(struct intel_dp *intel_dp,
+-                           struct intel_crtc_state *pipe_config,
+-                           int output_bpp, bool constant_n)
+-{
+-      struct intel_connector *intel_connector = intel_dp->attached_connector;
+-      struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+-      int pixel_clock;
+-
+-      if (pipe_config->vrr.enable)
+-              return;
+-
+-      /*
+-       * DRRS and PSR can't be enable together, so giving preference to PSR
+-       * as it allows more power-savings by complete shutting down display,
+-       * so to guarantee this, intel_dp_drrs_compute_config() must be called
+-       * after intel_psr_compute_config().
+-       */
+-      if (pipe_config->has_psr)
+-              return;
+-
+-      if (!intel_connector->panel.downclock_mode ||
+-          dev_priv->drrs.type != SEAMLESS_DRRS_SUPPORT)
+-              return;
+-
+-      pipe_config->has_drrs = true;
+-
+-      pixel_clock = intel_connector->panel.downclock_mode->clock;
+-      if (pipe_config->splitter.enable)
+-              pixel_clock /= pipe_config->splitter.link_count;
+-
+-      intel_link_compute_m_n(output_bpp, pipe_config->lane_count, pixel_clock,
+-                             pipe_config->port_clock, &pipe_config->dp_m2_n2,
+-                             constant_n, pipe_config->fec_enable);
+-
+-      /* FIXME: abstract this better */
+-      if (pipe_config->splitter.enable)
+-              pipe_config->dp_m2_n2.gmch_m *= pipe_config->splitter.link_count;
+-}
+-
+ int
+ intel_dp_compute_config(struct intel_encoder *encoder,
+                       struct intel_crtc_state *pipe_config,
+@@ -4737,432 +4698,6 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
+               drm_connector_attach_vrr_capable_property(connector);
+ }
+-/**
+- * intel_dp_set_drrs_state - program registers for RR switch to take effect
+- * @dev_priv: i915 device
+- * @crtc_state: a pointer to the active intel_crtc_state
+- * @refresh_rate: RR to be programmed
+- *
+- * This function gets called when refresh rate (RR) has to be changed from
+- * one frequency to another. Switches can be between high and low RR
+- * supported by the panel or to any other RR based on media playback (in
+- * this case, RR value needs to be passed from user space).
+- *
+- * The caller of this function needs to take a lock on dev_priv->drrs.
+- */
+-static void intel_dp_set_drrs_state(struct drm_i915_private *dev_priv,
+-                                  const struct intel_crtc_state *crtc_state,
+-                                  int refresh_rate)
+-{
+-      struct intel_dp *intel_dp = dev_priv->drrs.dp;
+-      struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+-      enum drrs_refresh_rate_type index = DRRS_HIGH_RR;
+-
+-      if (refresh_rate <= 0) {
+-              drm_dbg_kms(&dev_priv->drm,
+-                          "Refresh rate should be positive non-zero.\n");
+-              return;
+-      }
+-
+-      if (intel_dp == NULL) {
+-              drm_dbg_kms(&dev_priv->drm, "DRRS not supported.\n");
+-              return;
+-      }
+-
+-      if (!crtc) {
+-              drm_dbg_kms(&dev_priv->drm,
+-                          "DRRS: intel_crtc not initialized\n");
+-              return;
+-      }
+-
+-      if (dev_priv->drrs.type < SEAMLESS_DRRS_SUPPORT) {
+-              drm_dbg_kms(&dev_priv->drm, "Only Seamless DRRS supported.\n");
+-              return;
+-      }
+-
+-      if (drm_mode_vrefresh(intel_dp->attached_connector->panel.downclock_mode) ==
+-                      refresh_rate)
+-              index = DRRS_LOW_RR;
+-
+-      if (index == dev_priv->drrs.refresh_rate_type) {
+-              drm_dbg_kms(&dev_priv->drm,
+-                          "DRRS requested for previously set RR...ignoring\n");
+-              return;
+-      }
+-
+-      if (!crtc_state->hw.active) {
+-              drm_dbg_kms(&dev_priv->drm,
+-                          "eDP encoder disabled. CRTC not Active\n");
+-              return;
+-      }
+-
+-      if (DISPLAY_VER(dev_priv) >= 8 && !IS_CHERRYVIEW(dev_priv)) {
+-              switch (index) {
+-              case DRRS_HIGH_RR:
+-                      intel_dp_set_m_n(crtc_state, M1_N1);
+-                      break;
+-              case DRRS_LOW_RR:
+-                      intel_dp_set_m_n(crtc_state, M2_N2);
+-                      break;
+-              case DRRS_MAX_RR:
+-              default:
+-                      drm_err(&dev_priv->drm,
+-                              "Unsupported refreshrate type\n");
+-              }
+-      } else if (DISPLAY_VER(dev_priv) > 6) {
+-              i915_reg_t reg = PIPECONF(crtc_state->cpu_transcoder);
+-              u32 val;
+-
+-              val = intel_de_read(dev_priv, reg);
+-              if (index > DRRS_HIGH_RR) {
+-                      if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+-                              val |= PIPECONF_EDP_RR_MODE_SWITCH_VLV;
+-                      else
+-                              val |= PIPECONF_EDP_RR_MODE_SWITCH;
+-              } else {
+-                      if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+-                              val &= ~PIPECONF_EDP_RR_MODE_SWITCH_VLV;
+-                      else
+-                              val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
+-              }
+-              intel_de_write(dev_priv, reg, val);
+-      }
+-
+-      dev_priv->drrs.refresh_rate_type = index;
+-
+-      drm_dbg_kms(&dev_priv->drm, "eDP Refresh Rate set to : %dHz\n",
+-                  refresh_rate);
+-}
+-
+-static void
+-intel_edp_drrs_enable_locked(struct intel_dp *intel_dp)
+-{
+-      struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+-
+-      dev_priv->drrs.busy_frontbuffer_bits = 0;
+-      dev_priv->drrs.dp = intel_dp;
+-}
+-
+-/**
+- * intel_edp_drrs_enable - init drrs struct if supported
+- * @intel_dp: DP struct
+- * @crtc_state: A pointer to the active crtc state.
+- *
+- * Initializes frontbuffer_bits and drrs.dp
+- */
+-void intel_edp_drrs_enable(struct intel_dp *intel_dp,
+-                         const struct intel_crtc_state *crtc_state)
+-{
+-      struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+-
+-      if (!crtc_state->has_drrs)
+-              return;
+-
+-      drm_dbg_kms(&dev_priv->drm, "Enabling DRRS\n");
+-
+-      mutex_lock(&dev_priv->drrs.mutex);
+-
+-      if (dev_priv->drrs.dp) {
+-              drm_warn(&dev_priv->drm, "DRRS already enabled\n");
+-              goto unlock;
+-      }
+-
+-      intel_edp_drrs_enable_locked(intel_dp);
+-
+-unlock:
+-      mutex_unlock(&dev_priv->drrs.mutex);
+-}
+-
+-static void
+-intel_edp_drrs_disable_locked(struct intel_dp *intel_dp,
+-                            const struct intel_crtc_state *crtc_state)
+-{
+-      struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+-
+-      if (dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR) {
+-              int refresh;
+-
+-              refresh = drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode);
+-              intel_dp_set_drrs_state(dev_priv, crtc_state, refresh);
+-      }
+-
+-      dev_priv->drrs.dp = NULL;
+-}
+-
+-/**
+- * intel_edp_drrs_disable - Disable DRRS
+- * @intel_dp: DP struct
+- * @old_crtc_state: Pointer to old crtc_state.
+- *
+- */
+-void intel_edp_drrs_disable(struct intel_dp *intel_dp,
+-                          const struct intel_crtc_state *old_crtc_state)
+-{
+-      struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+-
+-      if (!old_crtc_state->has_drrs)
+-              return;
+-
+-      mutex_lock(&dev_priv->drrs.mutex);
+-      if (!dev_priv->drrs.dp) {
+-              mutex_unlock(&dev_priv->drrs.mutex);
+-              return;
+-      }
+-
+-      intel_edp_drrs_disable_locked(intel_dp, old_crtc_state);
+-      mutex_unlock(&dev_priv->drrs.mutex);
+-
+-      cancel_delayed_work_sync(&dev_priv->drrs.work);
+-}
+-
+-/**
+- * intel_edp_drrs_update - Update DRRS state
+- * @intel_dp: Intel DP
+- * @crtc_state: new CRTC state
+- *
+- * This function will update DRRS states, disabling or enabling DRRS when
+- * executing fastsets. For full modeset, intel_edp_drrs_disable() and
+- * intel_edp_drrs_enable() should be called instead.
+- */
+-void
+-intel_edp_drrs_update(struct intel_dp *intel_dp,
+-                    const struct intel_crtc_state *crtc_state)
+-{
+-      struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+-
+-      if (dev_priv->drrs.type != SEAMLESS_DRRS_SUPPORT)
+-              return;
+-
+-      mutex_lock(&dev_priv->drrs.mutex);
+-
+-      /* New state matches current one? */
+-      if (crtc_state->has_drrs == !!dev_priv->drrs.dp)
+-              goto unlock;
+-
+-      if (crtc_state->has_drrs)
+-              intel_edp_drrs_enable_locked(intel_dp);
+-      else
+-              intel_edp_drrs_disable_locked(intel_dp, crtc_state);
+-
+-unlock:
+-      mutex_unlock(&dev_priv->drrs.mutex);
+-}
+-
+-static void intel_edp_drrs_downclock_work(struct work_struct *work)
+-{
+-      struct drm_i915_private *dev_priv =
+-              container_of(work, typeof(*dev_priv), drrs.work.work);
+-      struct intel_dp *intel_dp;
+-
+-      mutex_lock(&dev_priv->drrs.mutex);
+-
+-      intel_dp = dev_priv->drrs.dp;
+-
+-      if (!intel_dp)
+-              goto unlock;
+-
+-      /*
+-       * The delayed work can race with an invalidate hence we need to
+-       * recheck.
+-       */
+-
+-      if (dev_priv->drrs.busy_frontbuffer_bits)
+-              goto unlock;
+-
+-      if (dev_priv->drrs.refresh_rate_type != DRRS_LOW_RR) {
+-              struct drm_crtc *crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
+-
+-              intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config,
+-                      drm_mode_vrefresh(intel_dp->attached_connector->panel.downclock_mode));
+-      }
+-
+-unlock:
+-      mutex_unlock(&dev_priv->drrs.mutex);
+-}
+-
+-/**
+- * intel_edp_drrs_invalidate - Disable Idleness DRRS
+- * @dev_priv: i915 device
+- * @frontbuffer_bits: frontbuffer plane tracking bits
+- *
+- * This function gets called everytime rendering on the given planes start.
+- * Hence DRRS needs to be Upclocked, i.e. (LOW_RR -> HIGH_RR).
+- *
+- * Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits.
+- */
+-void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv,
+-                             unsigned int frontbuffer_bits)
+-{
+-      struct intel_dp *intel_dp;
+-      struct drm_crtc *crtc;
+-      enum pipe pipe;
+-
+-      if (dev_priv->drrs.type == DRRS_NOT_SUPPORTED)
+-              return;
+-
+-      cancel_delayed_work(&dev_priv->drrs.work);
+-
+-      mutex_lock(&dev_priv->drrs.mutex);
+-
+-      intel_dp = dev_priv->drrs.dp;
+-      if (!intel_dp) {
+-              mutex_unlock(&dev_priv->drrs.mutex);
+-              return;
+-      }
+-
+-      crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
+-      pipe = to_intel_crtc(crtc)->pipe;
+-
+-      frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
+-      dev_priv->drrs.busy_frontbuffer_bits |= frontbuffer_bits;
+-
+-      /* invalidate means busy screen hence upclock */
+-      if (frontbuffer_bits && dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
+-              intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config,
+-                                      drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode));
+-
+-      mutex_unlock(&dev_priv->drrs.mutex);
+-}
+-
+-/**
+- * intel_edp_drrs_flush - Restart Idleness DRRS
+- * @dev_priv: i915 device
+- * @frontbuffer_bits: frontbuffer plane tracking bits
+- *
+- * This function gets called every time rendering on the given planes has
+- * completed or flip on a crtc is completed. So DRRS should be upclocked
+- * (LOW_RR -> HIGH_RR). And also Idleness detection should be started again,
+- * if no other planes are dirty.
+- *
+- * Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits.
+- */
+-void intel_edp_drrs_flush(struct drm_i915_private *dev_priv,
+-                        unsigned int frontbuffer_bits)
+-{
+-      struct intel_dp *intel_dp;
+-      struct drm_crtc *crtc;
+-      enum pipe pipe;
+-
+-      if (dev_priv->drrs.type == DRRS_NOT_SUPPORTED)
+-              return;
+-
+-      cancel_delayed_work(&dev_priv->drrs.work);
+-
+-      mutex_lock(&dev_priv->drrs.mutex);
+-
+-      intel_dp = dev_priv->drrs.dp;
+-      if (!intel_dp) {
+-              mutex_unlock(&dev_priv->drrs.mutex);
+-              return;
+-      }
+-
+-      crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
+-      pipe = to_intel_crtc(crtc)->pipe;
+-
+-      frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
+-      dev_priv->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits;
+-
+-      /* flush means busy screen hence upclock */
+-      if (frontbuffer_bits && dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
+-              intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config,
+-                                      drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode));
+-
+-      /*
+-       * flush also means no more activity hence schedule downclock, if all
+-       * other fbs are quiescent too
+-       */
+-      if (!dev_priv->drrs.busy_frontbuffer_bits)
+-              schedule_delayed_work(&dev_priv->drrs.work,
+-                              msecs_to_jiffies(1000));
+-      mutex_unlock(&dev_priv->drrs.mutex);
+-}
+-
+-/**
+- * DOC: Display Refresh Rate Switching (DRRS)
+- *
+- * Display Refresh Rate Switching (DRRS) is a power conservation feature
+- * which enables swtching between low and high refresh rates,
+- * dynamically, based on the usage scenario. This feature is applicable
+- * for internal panels.
+- *
+- * Indication that the panel supports DRRS is given by the panel EDID, which
+- * would list multiple refresh rates for one resolution.
+- *
+- * DRRS is of 2 types - static and seamless.
+- * Static DRRS involves changing refresh rate (RR) by doing a full modeset
+- * (may appear as a blink on screen) and is used in dock-undock scenario.
+- * Seamless DRRS involves changing RR without any visual effect to the user
+- * and can be used during normal system usage. This is done by programming
+- * certain registers.
+- *
+- * Support for static/seamless DRRS may be indicated in the VBT based on
+- * inputs from the panel spec.
+- *
+- * DRRS saves power by switching to low RR based on usage scenarios.
+- *
+- * The implementation is based on frontbuffer tracking implementation.  When
+- * there is a disturbance on the screen triggered by user activity or a periodic
+- * system activity, DRRS is disabled (RR is changed to high RR).  When there is
+- * no movement on screen, after a timeout of 1 second, a switch to low RR is
+- * made.
+- *
+- * For integration with frontbuffer tracking code, intel_edp_drrs_invalidate()
+- * and intel_edp_drrs_flush() are called.
+- *
+- * DRRS can be further extended to support other internal panels and also
+- * the scenario of video playback wherein RR is set based on the rate
+- * requested by userspace.
+- */
+-
+-/**
+- * intel_dp_drrs_init - Init basic DRRS work and mutex.
+- * @connector: eDP connector
+- * @fixed_mode: preferred mode of panel
+- *
+- * This function is  called only once at driver load to initialize basic
+- * DRRS stuff.
+- *
+- * Returns:
+- * Downclock mode if panel supports it, else return NULL.
+- * DRRS support is determined by the presence of downclock mode (apart
+- * from VBT setting).
+- */
+-static struct drm_display_mode *
+-intel_dp_drrs_init(struct intel_connector *connector,
+-                 struct drm_display_mode *fixed_mode)
+-{
+-      struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+-      struct drm_display_mode *downclock_mode = NULL;
+-
+-      INIT_DELAYED_WORK(&dev_priv->drrs.work, intel_edp_drrs_downclock_work);
+-      mutex_init(&dev_priv->drrs.mutex);
+-
+-      if (DISPLAY_VER(dev_priv) <= 6) {
+-              drm_dbg_kms(&dev_priv->drm,
+-                          "DRRS supported for Gen7 and above\n");
+-              return NULL;
+-      }
+-
+-      if (dev_priv->vbt.drrs_type != SEAMLESS_DRRS_SUPPORT) {
+-              drm_dbg_kms(&dev_priv->drm, "VBT doesn't support DRRS\n");
+-              return NULL;
+-      }
+-
+-      downclock_mode = intel_panel_edid_downclock_mode(connector, fixed_mode);
+-      if (!downclock_mode) {
+-              drm_dbg_kms(&dev_priv->drm,
+-                          "Downclock mode is not found. DRRS not supported\n");
+-              return NULL;
+-      }
+-
+-      dev_priv->drrs.type = dev_priv->vbt.drrs_type;
+-
+-      dev_priv->drrs.refresh_rate_type = DRRS_HIGH_RR;
+-      drm_dbg_kms(&dev_priv->drm,
+-                  "seamless DRRS supported for eDP panel.\n");
+-      return downclock_mode;
+-}
+-
+ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
+                                    struct intel_connector *intel_connector)
+ {
+diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
+index 2121aaa9b8db0..3dd6ebc2f6b14 100644
+--- a/drivers/gpu/drm/i915/display/intel_dp.h
++++ b/drivers/gpu/drm/i915/display/intel_dp.h
+@@ -70,17 +70,6 @@ int intel_dp_max_link_rate(struct intel_dp *intel_dp);
+ int intel_dp_max_lane_count(struct intel_dp *intel_dp);
+ int intel_dp_rate_select(struct intel_dp *intel_dp, int rate);
+-void intel_edp_drrs_enable(struct intel_dp *intel_dp,
+-                         const struct intel_crtc_state *crtc_state);
+-void intel_edp_drrs_disable(struct intel_dp *intel_dp,
+-                          const struct intel_crtc_state *crtc_state);
+-void intel_edp_drrs_update(struct intel_dp *intel_dp,
+-                         const struct intel_crtc_state *crtc_state);
+-void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv,
+-                             unsigned int frontbuffer_bits);
+-void intel_edp_drrs_flush(struct drm_i915_private *dev_priv,
+-                        unsigned int frontbuffer_bits);
+-
+ void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
+                          u8 *link_bw, u8 *rate_select);
+ bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp);
+diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c
+new file mode 100644
+index 0000000000000..be9b6d4482f04
+--- /dev/null
++++ b/drivers/gpu/drm/i915/display/intel_drrs.c
+@@ -0,0 +1,477 @@
++// SPDX-License-Identifier: MIT
++/*
++ * Copyright Â© 2021 Intel Corporation
++ */
++
++#include "i915_drv.h"
++#include "intel_atomic.h"
++#include "intel_de.h"
++#include "intel_display_types.h"
++#include "intel_drrs.h"
++#include "intel_panel.h"
++
++/**
++ * DOC: Display Refresh Rate Switching (DRRS)
++ *
++ * Display Refresh Rate Switching (DRRS) is a power conservation feature
++ * which enables swtching between low and high refresh rates,
++ * dynamically, based on the usage scenario. This feature is applicable
++ * for internal panels.
++ *
++ * Indication that the panel supports DRRS is given by the panel EDID, which
++ * would list multiple refresh rates for one resolution.
++ *
++ * DRRS is of 2 types - static and seamless.
++ * Static DRRS involves changing refresh rate (RR) by doing a full modeset
++ * (may appear as a blink on screen) and is used in dock-undock scenario.
++ * Seamless DRRS involves changing RR without any visual effect to the user
++ * and can be used during normal system usage. This is done by programming
++ * certain registers.
++ *
++ * Support for static/seamless DRRS may be indicated in the VBT based on
++ * inputs from the panel spec.
++ *
++ * DRRS saves power by switching to low RR based on usage scenarios.
++ *
++ * The implementation is based on frontbuffer tracking implementation.  When
++ * there is a disturbance on the screen triggered by user activity or a periodic
++ * system activity, DRRS is disabled (RR is changed to high RR).  When there is
++ * no movement on screen, after a timeout of 1 second, a switch to low RR is
++ * made.
++ *
++ * For integration with frontbuffer tracking code, intel_edp_drrs_invalidate()
++ * and intel_edp_drrs_flush() are called.
++ *
++ * DRRS can be further extended to support other internal panels and also
++ * the scenario of video playback wherein RR is set based on the rate
++ * requested by userspace.
++ */
++
++void
++intel_dp_drrs_compute_config(struct intel_dp *intel_dp,
++                           struct intel_crtc_state *pipe_config,
++                           int output_bpp, bool constant_n)
++{
++      struct intel_connector *intel_connector = intel_dp->attached_connector;
++      struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
++      int pixel_clock;
++
++      if (pipe_config->vrr.enable)
++              return;
++
++      /*
++       * DRRS and PSR can't be enable together, so giving preference to PSR
++       * as it allows more power-savings by complete shutting down display,
++       * so to guarantee this, intel_dp_drrs_compute_config() must be called
++       * after intel_psr_compute_config().
++       */
++      if (pipe_config->has_psr)
++              return;
++
++      if (!intel_connector->panel.downclock_mode ||
++          dev_priv->drrs.type != SEAMLESS_DRRS_SUPPORT)
++              return;
++
++      pipe_config->has_drrs = true;
++
++      pixel_clock = intel_connector->panel.downclock_mode->clock;
++      if (pipe_config->splitter.enable)
++              pixel_clock /= pipe_config->splitter.link_count;
++
++      intel_link_compute_m_n(output_bpp, pipe_config->lane_count, pixel_clock,
++                             pipe_config->port_clock, &pipe_config->dp_m2_n2,
++                             constant_n, pipe_config->fec_enable);
++
++      /* FIXME: abstract this better */
++      if (pipe_config->splitter.enable)
++              pipe_config->dp_m2_n2.gmch_m *= pipe_config->splitter.link_count;
++}
++
++/**
++ * intel_dp_set_drrs_state - program registers for RR switch to take effect
++ * @dev_priv: i915 device
++ * @crtc_state: a pointer to the active intel_crtc_state
++ * @refresh_rate: RR to be programmed
++ *
++ * This function gets called when refresh rate (RR) has to be changed from
++ * one frequency to another. Switches can be between high and low RR
++ * supported by the panel or to any other RR based on media playback (in
++ * this case, RR value needs to be passed from user space).
++ *
++ * The caller of this function needs to take a lock on dev_priv->drrs.
++ */
++static void intel_dp_set_drrs_state(struct drm_i915_private *dev_priv,
++                                  const struct intel_crtc_state *crtc_state,
++                                  int refresh_rate)
++{
++      struct intel_dp *intel_dp = dev_priv->drrs.dp;
++      struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
++      enum drrs_refresh_rate_type index = DRRS_HIGH_RR;
++
++      if (refresh_rate <= 0) {
++              drm_dbg_kms(&dev_priv->drm,
++                          "Refresh rate should be positive non-zero.\n");
++              return;
++      }
++
++      if (intel_dp == NULL) {
++              drm_dbg_kms(&dev_priv->drm, "DRRS not supported.\n");
++              return;
++      }
++
++      if (!crtc) {
++              drm_dbg_kms(&dev_priv->drm,
++                          "DRRS: intel_crtc not initialized\n");
++              return;
++      }
++
++      if (dev_priv->drrs.type < SEAMLESS_DRRS_SUPPORT) {
++              drm_dbg_kms(&dev_priv->drm, "Only Seamless DRRS supported.\n");
++              return;
++      }
++
++      if (drm_mode_vrefresh(intel_dp->attached_connector->panel.downclock_mode) ==
++                      refresh_rate)
++              index = DRRS_LOW_RR;
++
++      if (index == dev_priv->drrs.refresh_rate_type) {
++              drm_dbg_kms(&dev_priv->drm,
++                          "DRRS requested for previously set RR...ignoring\n");
++              return;
++      }
++
++      if (!crtc_state->hw.active) {
++              drm_dbg_kms(&dev_priv->drm,
++                          "eDP encoder disabled. CRTC not Active\n");
++              return;
++      }
++
++      if (DISPLAY_VER(dev_priv) >= 8 && !IS_CHERRYVIEW(dev_priv)) {
++              switch (index) {
++              case DRRS_HIGH_RR:
++                      intel_dp_set_m_n(crtc_state, M1_N1);
++                      break;
++              case DRRS_LOW_RR:
++                      intel_dp_set_m_n(crtc_state, M2_N2);
++                      break;
++              case DRRS_MAX_RR:
++              default:
++                      drm_err(&dev_priv->drm,
++                              "Unsupported refreshrate type\n");
++              }
++      } else if (DISPLAY_VER(dev_priv) > 6) {
++              i915_reg_t reg = PIPECONF(crtc_state->cpu_transcoder);
++              u32 val;
++
++              val = intel_de_read(dev_priv, reg);
++              if (index > DRRS_HIGH_RR) {
++                      if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
++                              val |= PIPECONF_EDP_RR_MODE_SWITCH_VLV;
++                      else
++                              val |= PIPECONF_EDP_RR_MODE_SWITCH;
++              } else {
++                      if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
++                              val &= ~PIPECONF_EDP_RR_MODE_SWITCH_VLV;
++                      else
++                              val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
++              }
++              intel_de_write(dev_priv, reg, val);
++      }
++
++      dev_priv->drrs.refresh_rate_type = index;
++
++      drm_dbg_kms(&dev_priv->drm, "eDP Refresh Rate set to : %dHz\n",
++                  refresh_rate);
++}
++
++static void
++intel_edp_drrs_enable_locked(struct intel_dp *intel_dp)
++{
++      struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
++
++      dev_priv->drrs.busy_frontbuffer_bits = 0;
++      dev_priv->drrs.dp = intel_dp;
++}
++
++/**
++ * intel_edp_drrs_enable - init drrs struct if supported
++ * @intel_dp: DP struct
++ * @crtc_state: A pointer to the active crtc state.
++ *
++ * Initializes frontbuffer_bits and drrs.dp
++ */
++void intel_edp_drrs_enable(struct intel_dp *intel_dp,
++                         const struct intel_crtc_state *crtc_state)
++{
++      struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
++
++      if (!crtc_state->has_drrs)
++              return;
++
++      drm_dbg_kms(&dev_priv->drm, "Enabling DRRS\n");
++
++      mutex_lock(&dev_priv->drrs.mutex);
++
++      if (dev_priv->drrs.dp) {
++              drm_warn(&dev_priv->drm, "DRRS already enabled\n");
++              goto unlock;
++      }
++
++      intel_edp_drrs_enable_locked(intel_dp);
++
++unlock:
++      mutex_unlock(&dev_priv->drrs.mutex);
++}
++
++static void
++intel_edp_drrs_disable_locked(struct intel_dp *intel_dp,
++                            const struct intel_crtc_state *crtc_state)
++{
++      struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
++
++      if (dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR) {
++              int refresh;
++
++              refresh = drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode);
++              intel_dp_set_drrs_state(dev_priv, crtc_state, refresh);
++      }
++
++      dev_priv->drrs.dp = NULL;
++}
++
++/**
++ * intel_edp_drrs_disable - Disable DRRS
++ * @intel_dp: DP struct
++ * @old_crtc_state: Pointer to old crtc_state.
++ *
++ */
++void intel_edp_drrs_disable(struct intel_dp *intel_dp,
++                          const struct intel_crtc_state *old_crtc_state)
++{
++      struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
++
++      if (!old_crtc_state->has_drrs)
++              return;
++
++      mutex_lock(&dev_priv->drrs.mutex);
++      if (!dev_priv->drrs.dp) {
++              mutex_unlock(&dev_priv->drrs.mutex);
++              return;
++      }
++
++      intel_edp_drrs_disable_locked(intel_dp, old_crtc_state);
++      mutex_unlock(&dev_priv->drrs.mutex);
++
++      cancel_delayed_work_sync(&dev_priv->drrs.work);
++}
++
++/**
++ * intel_edp_drrs_update - Update DRRS state
++ * @intel_dp: Intel DP
++ * @crtc_state: new CRTC state
++ *
++ * This function will update DRRS states, disabling or enabling DRRS when
++ * executing fastsets. For full modeset, intel_edp_drrs_disable() and
++ * intel_edp_drrs_enable() should be called instead.
++ */
++void
++intel_edp_drrs_update(struct intel_dp *intel_dp,
++                    const struct intel_crtc_state *crtc_state)
++{
++      struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
++
++      if (dev_priv->drrs.type != SEAMLESS_DRRS_SUPPORT)
++              return;
++
++      mutex_lock(&dev_priv->drrs.mutex);
++
++      /* New state matches current one? */
++      if (crtc_state->has_drrs == !!dev_priv->drrs.dp)
++              goto unlock;
++
++      if (crtc_state->has_drrs)
++              intel_edp_drrs_enable_locked(intel_dp);
++      else
++              intel_edp_drrs_disable_locked(intel_dp, crtc_state);
++
++unlock:
++      mutex_unlock(&dev_priv->drrs.mutex);
++}
++
++static void intel_edp_drrs_downclock_work(struct work_struct *work)
++{
++      struct drm_i915_private *dev_priv =
++              container_of(work, typeof(*dev_priv), drrs.work.work);
++      struct intel_dp *intel_dp;
++
++      mutex_lock(&dev_priv->drrs.mutex);
++
++      intel_dp = dev_priv->drrs.dp;
++
++      if (!intel_dp)
++              goto unlock;
++
++      /*
++       * The delayed work can race with an invalidate hence we need to
++       * recheck.
++       */
++
++      if (dev_priv->drrs.busy_frontbuffer_bits)
++              goto unlock;
++
++      if (dev_priv->drrs.refresh_rate_type != DRRS_LOW_RR) {
++              struct drm_crtc *crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
++
++              intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config,
++                                      drm_mode_vrefresh(intel_dp->attached_connector->panel.downclock_mode));
++      }
++
++unlock:
++      mutex_unlock(&dev_priv->drrs.mutex);
++}
++
++/**
++ * intel_edp_drrs_invalidate - Disable Idleness DRRS
++ * @dev_priv: i915 device
++ * @frontbuffer_bits: frontbuffer plane tracking bits
++ *
++ * This function gets called everytime rendering on the given planes start.
++ * Hence DRRS needs to be Upclocked, i.e. (LOW_RR -> HIGH_RR).
++ *
++ * Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits.
++ */
++void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv,
++                             unsigned int frontbuffer_bits)
++{
++      struct intel_dp *intel_dp;
++      struct drm_crtc *crtc;
++      enum pipe pipe;
++
++      if (dev_priv->drrs.type == DRRS_NOT_SUPPORTED)
++              return;
++
++      cancel_delayed_work(&dev_priv->drrs.work);
++
++      mutex_lock(&dev_priv->drrs.mutex);
++
++      intel_dp = dev_priv->drrs.dp;
++      if (!intel_dp) {
++              mutex_unlock(&dev_priv->drrs.mutex);
++              return;
++      }
++
++      crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
++      pipe = to_intel_crtc(crtc)->pipe;
++
++      frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
++      dev_priv->drrs.busy_frontbuffer_bits |= frontbuffer_bits;
++
++      /* invalidate means busy screen hence upclock */
++      if (frontbuffer_bits && dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
++              intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config,
++                                      drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode));
++
++      mutex_unlock(&dev_priv->drrs.mutex);
++}
++
++/**
++ * intel_edp_drrs_flush - Restart Idleness DRRS
++ * @dev_priv: i915 device
++ * @frontbuffer_bits: frontbuffer plane tracking bits
++ *
++ * This function gets called every time rendering on the given planes has
++ * completed or flip on a crtc is completed. So DRRS should be upclocked
++ * (LOW_RR -> HIGH_RR). And also Idleness detection should be started again,
++ * if no other planes are dirty.
++ *
++ * Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits.
++ */
++void intel_edp_drrs_flush(struct drm_i915_private *dev_priv,
++                        unsigned int frontbuffer_bits)
++{
++      struct intel_dp *intel_dp;
++      struct drm_crtc *crtc;
++      enum pipe pipe;
++
++      if (dev_priv->drrs.type == DRRS_NOT_SUPPORTED)
++              return;
++
++      cancel_delayed_work(&dev_priv->drrs.work);
++
++      mutex_lock(&dev_priv->drrs.mutex);
++
++      intel_dp = dev_priv->drrs.dp;
++      if (!intel_dp) {
++              mutex_unlock(&dev_priv->drrs.mutex);
++              return;
++      }
++
++      crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
++      pipe = to_intel_crtc(crtc)->pipe;
++
++      frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
++      dev_priv->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits;
++
++      /* flush means busy screen hence upclock */
++      if (frontbuffer_bits && dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
++              intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config,
++                                      drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode));
++
++      /*
++       * flush also means no more activity hence schedule downclock, if all
++       * other fbs are quiescent too
++       */
++      if (!dev_priv->drrs.busy_frontbuffer_bits)
++              schedule_delayed_work(&dev_priv->drrs.work,
++                                    msecs_to_jiffies(1000));
++      mutex_unlock(&dev_priv->drrs.mutex);
++}
++
++/**
++ * intel_dp_drrs_init - Init basic DRRS work and mutex.
++ * @connector: eDP connector
++ * @fixed_mode: preferred mode of panel
++ *
++ * This function is  called only once at driver load to initialize basic
++ * DRRS stuff.
++ *
++ * Returns:
++ * Downclock mode if panel supports it, else return NULL.
++ * DRRS support is determined by the presence of downclock mode (apart
++ * from VBT setting).
++ */
++struct drm_display_mode *
++intel_dp_drrs_init(struct intel_connector *connector,
++                 struct drm_display_mode *fixed_mode)
++{
++      struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
++      struct drm_display_mode *downclock_mode = NULL;
++
++      INIT_DELAYED_WORK(&dev_priv->drrs.work, intel_edp_drrs_downclock_work);
++      mutex_init(&dev_priv->drrs.mutex);
++
++      if (DISPLAY_VER(dev_priv) <= 6) {
++              drm_dbg_kms(&dev_priv->drm,
++                          "DRRS supported for Gen7 and above\n");
++              return NULL;
++      }
++
++      if (dev_priv->vbt.drrs_type != SEAMLESS_DRRS_SUPPORT) {
++              drm_dbg_kms(&dev_priv->drm, "VBT doesn't support DRRS\n");
++              return NULL;
++      }
++
++      downclock_mode = intel_panel_edid_downclock_mode(connector, fixed_mode);
++      if (!downclock_mode) {
++              drm_dbg_kms(&dev_priv->drm,
++                          "Downclock mode is not found. DRRS not supported\n");
++              return NULL;
++      }
++
++      dev_priv->drrs.type = dev_priv->vbt.drrs_type;
++
++      dev_priv->drrs.refresh_rate_type = DRRS_HIGH_RR;
++      drm_dbg_kms(&dev_priv->drm,
++                  "seamless DRRS supported for eDP panel.\n");
++      return downclock_mode;
++}
+diff --git a/drivers/gpu/drm/i915/display/intel_drrs.h b/drivers/gpu/drm/i915/display/intel_drrs.h
+new file mode 100644
+index 0000000000000..ffa175b4cf4f4
+--- /dev/null
++++ b/drivers/gpu/drm/i915/display/intel_drrs.h
+@@ -0,0 +1,32 @@
++/* SPDX-License-Identifier: MIT */
++/*
++ * Copyright Â© 2021 Intel Corporation
++ */
++
++#ifndef __INTEL_DRRS_H__
++#define __INTEL_DRRS_H__
++
++#include <linux/types.h>
++
++struct drm_i915_private;
++struct intel_crtc_state;
++struct intel_connector;
++struct intel_dp;
++
++void intel_edp_drrs_enable(struct intel_dp *intel_dp,
++                         const struct intel_crtc_state *crtc_state);
++void intel_edp_drrs_disable(struct intel_dp *intel_dp,
++                          const struct intel_crtc_state *crtc_state);
++void intel_edp_drrs_update(struct intel_dp *intel_dp,
++                         const struct intel_crtc_state *crtc_state);
++void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv,
++                             unsigned int frontbuffer_bits);
++void intel_edp_drrs_flush(struct drm_i915_private *dev_priv,
++                        unsigned int frontbuffer_bits);
++void intel_dp_drrs_compute_config(struct intel_dp *intel_dp,
++                                struct intel_crtc_state *pipe_config,
++                                int output_bpp, bool constant_n);
++struct drm_display_mode *intel_dp_drrs_init(struct intel_connector *connector,
++                                          struct drm_display_mode *fixed_mode);
++
++#endif /* __INTEL_DRRS_H__ */
+diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.c b/drivers/gpu/drm/i915/display/intel_frontbuffer.c
+index 8e75debcce1a9..e4834d84ce5e3 100644
+--- a/drivers/gpu/drm/i915/display/intel_frontbuffer.c
++++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.c
+@@ -62,6 +62,7 @@
+ #include "intel_display_types.h"
+ #include "intel_fbc.h"
+ #include "intel_frontbuffer.h"
++#include "intel_drrs.h"
+ #include "intel_psr.h"
+ /**
+-- 
+2.34.1
+
diff --git a/queue-5.15/drm-i915-display-split-out-dpt-out-of-intel_display..patch b/queue-5.15/drm-i915-display-split-out-dpt-out-of-intel_display..patch
new file mode 100644 (file)
index 0000000..8252847
--- /dev/null
@@ -0,0 +1,544 @@
+From f71f4dd25f9469a9ada437ad871e59d0bf4bc790 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 23 Aug 2021 15:25:31 +0300
+Subject: drm/i915/display: split out dpt out of intel_display.c
+
+From: Jani Nikula <jani.nikula@intel.com>
+
+[ Upstream commit dc6d6158a6e8b11a11544a541583296d9323050f ]
+
+Let's try to reduce the size of intel_display.c, not increase it.
+
+Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/934a2a0db05e835f6843befef6082e2034f23b3a.1629721467.git.jani.nikula@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/i915/Makefile                |   1 +
+ drivers/gpu/drm/i915/display/intel_display.c | 220 +-----------------
+ drivers/gpu/drm/i915/display/intel_dpt.c     | 229 +++++++++++++++++++
+ drivers/gpu/drm/i915/display/intel_dpt.h     |  19 ++
+ 4 files changed, 250 insertions(+), 219 deletions(-)
+ create mode 100644 drivers/gpu/drm/i915/display/intel_dpt.c
+ create mode 100644 drivers/gpu/drm/i915/display/intel_dpt.h
+
+diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
+index 335ba9f43d8f7..a4154fe14f8c0 100644
+--- a/drivers/gpu/drm/i915/Makefile
++++ b/drivers/gpu/drm/i915/Makefile
+@@ -211,6 +211,7 @@ i915-y += \
+       display/intel_dpio_phy.o \
+       display/intel_dpll.o \
+       display/intel_dpll_mgr.o \
++      display/intel_dpt.o \
+       display/intel_dsb.o \
+       display/intel_fb.o \
+       display/intel_fbc.o \
+diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
+index 17f44ffea5866..625ce6975eeba 100644
+--- a/drivers/gpu/drm/i915/display/intel_display.c
++++ b/drivers/gpu/drm/i915/display/intel_display.c
+@@ -84,6 +84,7 @@
+ #include "intel_display_types.h"
+ #include "intel_dmc.h"
+ #include "intel_dp_link_training.h"
++#include "intel_dpt.h"
+ #include "intel_fbc.h"
+ #include "intel_fdi.h"
+ #include "intel_fbdev.h"
+@@ -126,182 +127,6 @@ static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state);
+ static void intel_modeset_setup_hw_state(struct drm_device *dev,
+                                        struct drm_modeset_acquire_ctx *ctx);
+-struct i915_dpt {
+-      struct i915_address_space vm;
+-
+-      struct drm_i915_gem_object *obj;
+-      struct i915_vma *vma;
+-      void __iomem *iomem;
+-};
+-
+-#define i915_is_dpt(vm) ((vm)->is_dpt)
+-
+-static inline struct i915_dpt *
+-i915_vm_to_dpt(struct i915_address_space *vm)
+-{
+-      BUILD_BUG_ON(offsetof(struct i915_dpt, vm));
+-      GEM_BUG_ON(!i915_is_dpt(vm));
+-      return container_of(vm, struct i915_dpt, vm);
+-}
+-
+-#define dpt_total_entries(dpt) ((dpt)->vm.total >> PAGE_SHIFT)
+-
+-static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte)
+-{
+-      writeq(pte, addr);
+-}
+-
+-static void dpt_insert_page(struct i915_address_space *vm,
+-                          dma_addr_t addr,
+-                          u64 offset,
+-                          enum i915_cache_level level,
+-                          u32 flags)
+-{
+-      struct i915_dpt *dpt = i915_vm_to_dpt(vm);
+-      gen8_pte_t __iomem *base = dpt->iomem;
+-
+-      gen8_set_pte(base + offset / I915_GTT_PAGE_SIZE,
+-                   vm->pte_encode(addr, level, flags));
+-}
+-
+-static void dpt_insert_entries(struct i915_address_space *vm,
+-                             struct i915_vma *vma,
+-                             enum i915_cache_level level,
+-                             u32 flags)
+-{
+-      struct i915_dpt *dpt = i915_vm_to_dpt(vm);
+-      gen8_pte_t __iomem *base = dpt->iomem;
+-      const gen8_pte_t pte_encode = vm->pte_encode(0, level, flags);
+-      struct sgt_iter sgt_iter;
+-      dma_addr_t addr;
+-      int i;
+-
+-      /*
+-       * Note that we ignore PTE_READ_ONLY here. The caller must be careful
+-       * not to allow the user to override access to a read only page.
+-       */
+-
+-      i = vma->node.start / I915_GTT_PAGE_SIZE;
+-      for_each_sgt_daddr(addr, sgt_iter, vma->pages)
+-              gen8_set_pte(&base[i++], pte_encode | addr);
+-}
+-
+-static void dpt_clear_range(struct i915_address_space *vm,
+-                          u64 start, u64 length)
+-{
+-}
+-
+-static void dpt_bind_vma(struct i915_address_space *vm,
+-                       struct i915_vm_pt_stash *stash,
+-                       struct i915_vma *vma,
+-                       enum i915_cache_level cache_level,
+-                       u32 flags)
+-{
+-      struct drm_i915_gem_object *obj = vma->obj;
+-      u32 pte_flags;
+-
+-      /* Applicable to VLV (gen8+ do not support RO in the GGTT) */
+-      pte_flags = 0;
+-      if (vma->vm->has_read_only && i915_gem_object_is_readonly(obj))
+-              pte_flags |= PTE_READ_ONLY;
+-      if (i915_gem_object_is_lmem(obj))
+-              pte_flags |= PTE_LM;
+-
+-      vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags);
+-
+-      vma->page_sizes.gtt = I915_GTT_PAGE_SIZE;
+-
+-      /*
+-       * Without aliasing PPGTT there's no difference between
+-       * GLOBAL/LOCAL_BIND, it's all the same ptes. Hence unconditionally
+-       * upgrade to both bound if we bind either to avoid double-binding.
+-       */
+-      atomic_or(I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND, &vma->flags);
+-}
+-
+-static void dpt_unbind_vma(struct i915_address_space *vm, struct i915_vma *vma)
+-{
+-      vm->clear_range(vm, vma->node.start, vma->size);
+-}
+-
+-static void dpt_cleanup(struct i915_address_space *vm)
+-{
+-      struct i915_dpt *dpt = i915_vm_to_dpt(vm);
+-
+-      i915_gem_object_put(dpt->obj);
+-}
+-
+-static struct i915_address_space *
+-intel_dpt_create(struct intel_framebuffer *fb)
+-{
+-      struct drm_gem_object *obj = &intel_fb_obj(&fb->base)->base;
+-      struct drm_i915_private *i915 = to_i915(obj->dev);
+-      struct drm_i915_gem_object *dpt_obj;
+-      struct i915_address_space *vm;
+-      struct i915_dpt *dpt;
+-      size_t size;
+-      int ret;
+-
+-      if (intel_fb_needs_pot_stride_remap(fb))
+-              size = intel_remapped_info_size(&fb->remapped_view.gtt.remapped);
+-      else
+-              size = DIV_ROUND_UP_ULL(obj->size, I915_GTT_PAGE_SIZE);
+-
+-      size = round_up(size * sizeof(gen8_pte_t), I915_GTT_PAGE_SIZE);
+-
+-      if (HAS_LMEM(i915))
+-              dpt_obj = i915_gem_object_create_lmem(i915, size, 0);
+-      else
+-              dpt_obj = i915_gem_object_create_stolen(i915, size);
+-      if (IS_ERR(dpt_obj))
+-              return ERR_CAST(dpt_obj);
+-
+-      ret = i915_gem_object_set_cache_level(dpt_obj, I915_CACHE_NONE);
+-      if (ret) {
+-              i915_gem_object_put(dpt_obj);
+-              return ERR_PTR(ret);
+-      }
+-
+-      dpt = kzalloc(sizeof(*dpt), GFP_KERNEL);
+-      if (!dpt) {
+-              i915_gem_object_put(dpt_obj);
+-              return ERR_PTR(-ENOMEM);
+-      }
+-
+-      vm = &dpt->vm;
+-
+-      vm->gt = &i915->gt;
+-      vm->i915 = i915;
+-      vm->dma = i915->drm.dev;
+-      vm->total = (size / sizeof(gen8_pte_t)) * I915_GTT_PAGE_SIZE;
+-      vm->is_dpt = true;
+-
+-      i915_address_space_init(vm, VM_CLASS_DPT);
+-
+-      vm->insert_page = dpt_insert_page;
+-      vm->clear_range = dpt_clear_range;
+-      vm->insert_entries = dpt_insert_entries;
+-      vm->cleanup = dpt_cleanup;
+-
+-      vm->vma_ops.bind_vma    = dpt_bind_vma;
+-      vm->vma_ops.unbind_vma  = dpt_unbind_vma;
+-      vm->vma_ops.set_pages   = ggtt_set_pages;
+-      vm->vma_ops.clear_pages = clear_pages;
+-
+-      vm->pte_encode = gen8_ggtt_pte_encode;
+-
+-      dpt->obj = dpt_obj;
+-
+-      return &dpt->vm;
+-}
+-
+-static void intel_dpt_destroy(struct i915_address_space *vm)
+-{
+-      struct i915_dpt *dpt = i915_vm_to_dpt(vm);
+-
+-      i915_vm_close(&dpt->vm);
+-}
+-
+ /* returns HPLL frequency in kHz */
+ int vlv_get_hpll_vco(struct drm_i915_private *dev_priv)
+ {
+@@ -1879,49 +1704,6 @@ static void intel_plane_disable_noatomic(struct intel_crtc *crtc,
+       intel_wait_for_vblank(dev_priv, crtc->pipe);
+ }
+-static struct i915_vma *intel_dpt_pin(struct i915_address_space *vm)
+-{
+-      struct drm_i915_private *i915 = vm->i915;
+-      struct i915_dpt *dpt = i915_vm_to_dpt(vm);
+-      intel_wakeref_t wakeref;
+-      struct i915_vma *vma;
+-      void __iomem *iomem;
+-
+-      wakeref = intel_runtime_pm_get(&i915->runtime_pm);
+-      atomic_inc(&i915->gpu_error.pending_fb_pin);
+-
+-      vma = i915_gem_object_ggtt_pin(dpt->obj, NULL, 0, 4096,
+-                                     HAS_LMEM(i915) ? 0 : PIN_MAPPABLE);
+-      if (IS_ERR(vma))
+-              goto err;
+-
+-      iomem = i915_vma_pin_iomap(vma);
+-      i915_vma_unpin(vma);
+-      if (IS_ERR(iomem)) {
+-              vma = iomem;
+-              goto err;
+-      }
+-
+-      dpt->vma = vma;
+-      dpt->iomem = iomem;
+-
+-      i915_vma_get(vma);
+-
+-err:
+-      atomic_dec(&i915->gpu_error.pending_fb_pin);
+-      intel_runtime_pm_put(&i915->runtime_pm, wakeref);
+-
+-      return vma;
+-}
+-
+-static void intel_dpt_unpin(struct i915_address_space *vm)
+-{
+-      struct i915_dpt *dpt = i915_vm_to_dpt(vm);
+-
+-      i915_vma_unpin_iomap(dpt->vma);
+-      i915_vma_put(dpt->vma);
+-}
+-
+ static bool
+ intel_reuse_initial_plane_obj(struct drm_i915_private *i915,
+                             const struct intel_initial_plane_config *plane_config,
+diff --git a/drivers/gpu/drm/i915/display/intel_dpt.c b/drivers/gpu/drm/i915/display/intel_dpt.c
+new file mode 100644
+index 0000000000000..22acd945a9e47
+--- /dev/null
++++ b/drivers/gpu/drm/i915/display/intel_dpt.c
+@@ -0,0 +1,229 @@
++// SPDX-License-Identifier: MIT
++/*
++ * Copyright Â© 2021 Intel Corporation
++ */
++
++#include "i915_drv.h"
++#include "intel_display_types.h"
++#include "intel_dpt.h"
++#include "intel_fb.h"
++#include "gt/gen8_ppgtt.h"
++
++struct i915_dpt {
++      struct i915_address_space vm;
++
++      struct drm_i915_gem_object *obj;
++      struct i915_vma *vma;
++      void __iomem *iomem;
++};
++
++#define i915_is_dpt(vm) ((vm)->is_dpt)
++
++static inline struct i915_dpt *
++i915_vm_to_dpt(struct i915_address_space *vm)
++{
++      BUILD_BUG_ON(offsetof(struct i915_dpt, vm));
++      GEM_BUG_ON(!i915_is_dpt(vm));
++      return container_of(vm, struct i915_dpt, vm);
++}
++
++#define dpt_total_entries(dpt) ((dpt)->vm.total >> PAGE_SHIFT)
++
++static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte)
++{
++      writeq(pte, addr);
++}
++
++static void dpt_insert_page(struct i915_address_space *vm,
++                          dma_addr_t addr,
++                          u64 offset,
++                          enum i915_cache_level level,
++                          u32 flags)
++{
++      struct i915_dpt *dpt = i915_vm_to_dpt(vm);
++      gen8_pte_t __iomem *base = dpt->iomem;
++
++      gen8_set_pte(base + offset / I915_GTT_PAGE_SIZE,
++                   vm->pte_encode(addr, level, flags));
++}
++
++static void dpt_insert_entries(struct i915_address_space *vm,
++                             struct i915_vma *vma,
++                             enum i915_cache_level level,
++                             u32 flags)
++{
++      struct i915_dpt *dpt = i915_vm_to_dpt(vm);
++      gen8_pte_t __iomem *base = dpt->iomem;
++      const gen8_pte_t pte_encode = vm->pte_encode(0, level, flags);
++      struct sgt_iter sgt_iter;
++      dma_addr_t addr;
++      int i;
++
++      /*
++       * Note that we ignore PTE_READ_ONLY here. The caller must be careful
++       * not to allow the user to override access to a read only page.
++       */
++
++      i = vma->node.start / I915_GTT_PAGE_SIZE;
++      for_each_sgt_daddr(addr, sgt_iter, vma->pages)
++              gen8_set_pte(&base[i++], pte_encode | addr);
++}
++
++static void dpt_clear_range(struct i915_address_space *vm,
++                          u64 start, u64 length)
++{
++}
++
++static void dpt_bind_vma(struct i915_address_space *vm,
++                       struct i915_vm_pt_stash *stash,
++                       struct i915_vma *vma,
++                       enum i915_cache_level cache_level,
++                       u32 flags)
++{
++      struct drm_i915_gem_object *obj = vma->obj;
++      u32 pte_flags;
++
++      /* Applicable to VLV (gen8+ do not support RO in the GGTT) */
++      pte_flags = 0;
++      if (vma->vm->has_read_only && i915_gem_object_is_readonly(obj))
++              pte_flags |= PTE_READ_ONLY;
++      if (i915_gem_object_is_lmem(obj))
++              pte_flags |= PTE_LM;
++
++      vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags);
++
++      vma->page_sizes.gtt = I915_GTT_PAGE_SIZE;
++
++      /*
++       * Without aliasing PPGTT there's no difference between
++       * GLOBAL/LOCAL_BIND, it's all the same ptes. Hence unconditionally
++       * upgrade to both bound if we bind either to avoid double-binding.
++       */
++      atomic_or(I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND, &vma->flags);
++}
++
++static void dpt_unbind_vma(struct i915_address_space *vm, struct i915_vma *vma)
++{
++      vm->clear_range(vm, vma->node.start, vma->size);
++}
++
++static void dpt_cleanup(struct i915_address_space *vm)
++{
++      struct i915_dpt *dpt = i915_vm_to_dpt(vm);
++
++      i915_gem_object_put(dpt->obj);
++}
++
++struct i915_vma *intel_dpt_pin(struct i915_address_space *vm)
++{
++      struct drm_i915_private *i915 = vm->i915;
++      struct i915_dpt *dpt = i915_vm_to_dpt(vm);
++      intel_wakeref_t wakeref;
++      struct i915_vma *vma;
++      void __iomem *iomem;
++
++      wakeref = intel_runtime_pm_get(&i915->runtime_pm);
++      atomic_inc(&i915->gpu_error.pending_fb_pin);
++
++      vma = i915_gem_object_ggtt_pin(dpt->obj, NULL, 0, 4096,
++                                     HAS_LMEM(i915) ? 0 : PIN_MAPPABLE);
++      if (IS_ERR(vma))
++              goto err;
++
++      iomem = i915_vma_pin_iomap(vma);
++      i915_vma_unpin(vma);
++      if (IS_ERR(iomem)) {
++              vma = iomem;
++              goto err;
++      }
++
++      dpt->vma = vma;
++      dpt->iomem = iomem;
++
++      i915_vma_get(vma);
++
++err:
++      atomic_dec(&i915->gpu_error.pending_fb_pin);
++      intel_runtime_pm_put(&i915->runtime_pm, wakeref);
++
++      return vma;
++}
++
++void intel_dpt_unpin(struct i915_address_space *vm)
++{
++      struct i915_dpt *dpt = i915_vm_to_dpt(vm);
++
++      i915_vma_unpin_iomap(dpt->vma);
++      i915_vma_put(dpt->vma);
++}
++
++struct i915_address_space *
++intel_dpt_create(struct intel_framebuffer *fb)
++{
++      struct drm_gem_object *obj = &intel_fb_obj(&fb->base)->base;
++      struct drm_i915_private *i915 = to_i915(obj->dev);
++      struct drm_i915_gem_object *dpt_obj;
++      struct i915_address_space *vm;
++      struct i915_dpt *dpt;
++      size_t size;
++      int ret;
++
++      if (intel_fb_needs_pot_stride_remap(fb))
++              size = intel_remapped_info_size(&fb->remapped_view.gtt.remapped);
++      else
++              size = DIV_ROUND_UP_ULL(obj->size, I915_GTT_PAGE_SIZE);
++
++      size = round_up(size * sizeof(gen8_pte_t), I915_GTT_PAGE_SIZE);
++
++      if (HAS_LMEM(i915))
++              dpt_obj = i915_gem_object_create_lmem(i915, size, 0);
++      else
++              dpt_obj = i915_gem_object_create_stolen(i915, size);
++      if (IS_ERR(dpt_obj))
++              return ERR_CAST(dpt_obj);
++
++      ret = i915_gem_object_set_cache_level(dpt_obj, I915_CACHE_NONE);
++      if (ret) {
++              i915_gem_object_put(dpt_obj);
++              return ERR_PTR(ret);
++      }
++
++      dpt = kzalloc(sizeof(*dpt), GFP_KERNEL);
++      if (!dpt) {
++              i915_gem_object_put(dpt_obj);
++              return ERR_PTR(-ENOMEM);
++      }
++
++      vm = &dpt->vm;
++
++      vm->gt = &i915->gt;
++      vm->i915 = i915;
++      vm->dma = i915->drm.dev;
++      vm->total = (size / sizeof(gen8_pte_t)) * I915_GTT_PAGE_SIZE;
++      vm->is_dpt = true;
++
++      i915_address_space_init(vm, VM_CLASS_DPT);
++
++      vm->insert_page = dpt_insert_page;
++      vm->clear_range = dpt_clear_range;
++      vm->insert_entries = dpt_insert_entries;
++      vm->cleanup = dpt_cleanup;
++
++      vm->vma_ops.bind_vma    = dpt_bind_vma;
++      vm->vma_ops.unbind_vma  = dpt_unbind_vma;
++      vm->vma_ops.set_pages   = ggtt_set_pages;
++      vm->vma_ops.clear_pages = clear_pages;
++
++      vm->pte_encode = gen8_ggtt_pte_encode;
++
++      dpt->obj = dpt_obj;
++
++      return &dpt->vm;
++}
++
++void intel_dpt_destroy(struct i915_address_space *vm)
++{
++      struct i915_dpt *dpt = i915_vm_to_dpt(vm);
++
++      i915_vm_close(&dpt->vm);
++}
+diff --git a/drivers/gpu/drm/i915/display/intel_dpt.h b/drivers/gpu/drm/i915/display/intel_dpt.h
+new file mode 100644
+index 0000000000000..45142b8f849f6
+--- /dev/null
++++ b/drivers/gpu/drm/i915/display/intel_dpt.h
+@@ -0,0 +1,19 @@
++/* SPDX-License-Identifier: MIT */
++/*
++ * Copyright Â© 2021 Intel Corporation
++ */
++
++#ifndef __INTEL_DPT_H__
++#define __INTEL_DPT_H__
++
++struct i915_address_space;
++struct i915_vma;
++struct intel_framebuffer;
++
++void intel_dpt_destroy(struct i915_address_space *vm);
++struct i915_vma *intel_dpt_pin(struct i915_address_space *vm);
++void intel_dpt_unpin(struct i915_address_space *vm);
++struct i915_address_space *
++intel_dpt_create(struct intel_framebuffer *fb);
++
++#endif /* __INTEL_DPT_H__ */
+-- 
+2.34.1
+
diff --git a/queue-5.15/drm-i915-don-t-call-free_mmap_offset-when-purging.patch b/queue-5.15/drm-i915-don-t-call-free_mmap_offset-when-purging.patch
new file mode 100644 (file)
index 0000000..dc87f7b
--- /dev/null
@@ -0,0 +1,80 @@
+From 6df27b9017b57b841b65e9935baafae2e60aa06e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Jan 2022 17:49:07 +0000
+Subject: drm/i915: don't call free_mmap_offset when purging
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Matthew Auld <matthew.auld@intel.com>
+
+[ Upstream commit 4c2602ba8d74c35d550ed3d518809c697de08d88 ]
+
+The TTM backend is in theory the only user here(also purge should only
+be called once we have dropped the pages), where it is setup at object
+creation and is only removed once the object is destroyed. Also
+resetting the node here might be iffy since the ttm fault handler
+uses the stored fake offset to determine the page offset within the pages
+array.
+
+This also blows up in the dontneed-before-mmap test, since the
+expectation is that the vma_node will live on, until the object is
+destroyed:
+
+<2> [749.062902] kernel BUG at drivers/gpu/drm/i915/gem/i915_gem_ttm.c:943!
+<4> [749.062923] invalid opcode: 0000 [#1] PREEMPT SMP NOPTI
+<4> [749.062928] CPU: 0 PID: 1643 Comm: gem_madvise Tainted: G     U  W         5.16.0-rc8-CI-CI_DRM_11046+ #1
+<4> [749.062933] Hardware name: Gigabyte Technology Co., Ltd. GB-Z390 Garuda/GB-Z390 Garuda-CF, BIOS IG1c 11/19/2019
+<4> [749.062937] RIP: 0010:i915_ttm_mmap_offset.cold.35+0x5b/0x5d [i915]
+<4> [749.063044] Code: 00 48 c7 c2 a0 23 4e a0 48 c7 c7 26 df 4a a0 e8 95 1d d0 e0 bf 01 00 00 00 e8 8b ec cf e0 31 f6 bf 09 00 00 00 e8 5f 30 c0 e0 <0f> 0b 48 c7 c1 24 4b 56 a0 ba 5b 03 00 00 48 c7 c6 c0 23 4e a0 48
+<4> [749.063052] RSP: 0018:ffffc90002ab7d38 EFLAGS: 00010246
+<4> [749.063056] RAX: 0000000000000240 RBX: ffff88811f2e61c0 RCX: 0000000000000006
+<4> [749.063060] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000009
+<4> [749.063063] RBP: ffffc90002ab7e58 R08: 0000000000000001 R09: 0000000000000001
+<4> [749.063067] R10: 000000000123d0f8 R11: ffffc90002ab7b20 R12: ffff888112a1a000
+<4> [749.063071] R13: 0000000000000004 R14: ffff88811f2e61c0 R15: ffff888112a1a000
+<4> [749.063074] FS:  00007f6e5fcad500(0000) GS:ffff8884ad600000(0000) knlGS:0000000000000000
+<4> [749.063078] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+<4> [749.063081] CR2: 00007efd264e39f0 CR3: 0000000115fd6005 CR4: 00000000003706f0
+<4> [749.063085] Call Trace:
+<4> [749.063087]  <TASK>
+<4> [749.063089]  __assign_mmap_offset+0x41/0x300 [i915]
+<4> [749.063171]  __assign_mmap_offset_handle+0x159/0x270 [i915]
+<4> [749.063248]  ? i915_gem_dumb_mmap_offset+0x70/0x70 [i915]
+<4> [749.063325]  drm_ioctl_kernel+0xae/0x140
+<4> [749.063330]  drm_ioctl+0x201/0x3d0
+<4> [749.063333]  ? i915_gem_dumb_mmap_offset+0x70/0x70 [i915]
+<4> [749.063409]  ? do_user_addr_fault+0x200/0x670
+<4> [749.063415]  __x64_sys_ioctl+0x6d/0xa0
+<4> [749.063419]  do_syscall_64+0x3a/0xb0
+<4> [749.063423]  entry_SYSCALL_64_after_hwframe+0x44/0xae
+<4> [749.063428] RIP: 0033:0x7f6e5f100317
+
+Testcase: igt/gem_madvise/dontneed-before-mmap
+Fixes: cf3e3e86d779 ("drm/i915: Use ttm mmap handling for ttm bo's.")
+Signed-off-by: Matthew Auld <matthew.auld@intel.com>
+Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Reviewed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220106174910.280616-1-matthew.auld@intel.com
+(cherry picked from commit 658a0c632625e1db51837ff754fe18a6a7f2ccf8)
+Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/i915/gem/i915_gem_pages.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
+index 8d6c38a622016..9053cea3395a6 100644
+--- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c
++++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
+@@ -162,7 +162,6 @@ int i915_gem_object_pin_pages_unlocked(struct drm_i915_gem_object *obj)
+ /* Immediately discard the backing storage */
+ void i915_gem_object_truncate(struct drm_i915_gem_object *obj)
+ {
+-      drm_gem_free_mmap_offset(&obj->base);
+       if (obj->ops->truncate)
+               obj->ops->truncate(obj);
+ }
+-- 
+2.34.1
+
diff --git a/queue-5.15/drm-i915-workaround-broken-bios-dbuf-configuration-o.patch b/queue-5.15/drm-i915-workaround-broken-bios-dbuf-configuration-o.patch
new file mode 100644 (file)
index 0000000..3316877
--- /dev/null
@@ -0,0 +1,151 @@
+From f37369add07a90e7fa0b7df826e27f7bae06c6ff Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Feb 2022 16:18:18 +0200
+Subject: drm/i915: Workaround broken BIOS DBUF configuration on TGL/RKL
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Ville Syrjälä <ville.syrjala@linux.intel.com>
+
+[ Upstream commit 4e6f55120c7eccf6f9323bb681632e23cbcb3f3c ]
+
+On TGL/RKL the BIOS likes to use some kind of bogus DBUF layout
+that doesn't match what the spec recommends. With a single active
+pipe that is not going to be a problem, but with multiple pipes
+active skl_commit_modeset_enables() goes into an infinite loop
+since it can't figure out any order in which it can commit the
+pipes without causing DBUF overlaps between the planes.
+
+We'd need some kind of extra DBUF defrag stage in between to
+make the transition possible. But that is clearly way too complex
+a solution, so in the name of simplicity let's just sanitize the
+DBUF state by simply turning off all planes when we detect a
+pipe encroaching on its neighbours' DBUF slices. We only have
+to disable the primary planes as all other planes should have
+already been disabled (if they somehow were enabled) by
+earlier sanitization steps.
+
+And for good measure let's also sanitize in case the DBUF
+allocations of the pipes already seem to overlap each other.
+
+Cc: <stable@vger.kernel.org> # v5.14+
+Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/4762
+Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220204141818.1900-3-ville.syrjala@linux.intel.com
+Reviewed-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
+(cherry picked from commit 15512021eb3975a8c2366e3883337e252bb0eee5)
+Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/i915/display/intel_display.c |  1 +
+ drivers/gpu/drm/i915/intel_pm.c              | 68 ++++++++++++++++++++
+ drivers/gpu/drm/i915/intel_pm.h              |  1 +
+ 3 files changed, 70 insertions(+)
+
+diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
+index 625ce6975eeba..dd9cfb193432c 100644
+--- a/drivers/gpu/drm/i915/display/intel_display.c
++++ b/drivers/gpu/drm/i915/display/intel_display.c
+@@ -13217,6 +13217,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
+               vlv_wm_sanitize(dev_priv);
+       } else if (DISPLAY_VER(dev_priv) >= 9) {
+               skl_wm_get_hw_state(dev_priv);
++              skl_wm_sanitize(dev_priv);
+       } else if (HAS_PCH_SPLIT(dev_priv)) {
+               ilk_wm_get_hw_state(dev_priv);
+       }
+diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
+index 9c5e4758947b6..c7c8a556e401a 100644
+--- a/drivers/gpu/drm/i915/intel_pm.c
++++ b/drivers/gpu/drm/i915/intel_pm.c
+@@ -6681,6 +6681,74 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
+       dbuf_state->enabled_slices = dev_priv->dbuf.enabled_slices;
+ }
++static bool skl_dbuf_is_misconfigured(struct drm_i915_private *i915)
++{
++      const struct intel_dbuf_state *dbuf_state =
++              to_intel_dbuf_state(i915->dbuf.obj.state);
++      struct skl_ddb_entry entries[I915_MAX_PIPES] = {};
++      struct intel_crtc *crtc;
++
++      for_each_intel_crtc(&i915->drm, crtc) {
++              const struct intel_crtc_state *crtc_state =
++                      to_intel_crtc_state(crtc->base.state);
++
++              entries[crtc->pipe] = crtc_state->wm.skl.ddb;
++      }
++
++      for_each_intel_crtc(&i915->drm, crtc) {
++              const struct intel_crtc_state *crtc_state =
++                      to_intel_crtc_state(crtc->base.state);
++              u8 slices;
++
++              slices = skl_compute_dbuf_slices(crtc, dbuf_state->active_pipes,
++                                               dbuf_state->joined_mbus);
++              if (dbuf_state->slices[crtc->pipe] & ~slices)
++                      return true;
++
++              if (skl_ddb_allocation_overlaps(&crtc_state->wm.skl.ddb, entries,
++                                              I915_MAX_PIPES, crtc->pipe))
++                      return true;
++      }
++
++      return false;
++}
++
++void skl_wm_sanitize(struct drm_i915_private *i915)
++{
++      struct intel_crtc *crtc;
++
++      /*
++       * On TGL/RKL (at least) the BIOS likes to assign the planes
++       * to the wrong DBUF slices. This will cause an infinite loop
++       * in skl_commit_modeset_enables() as it can't find a way to
++       * transition between the old bogus DBUF layout to the new
++       * proper DBUF layout without DBUF allocation overlaps between
++       * the planes (which cannot be allowed or else the hardware
++       * may hang). If we detect a bogus DBUF layout just turn off
++       * all the planes so that skl_commit_modeset_enables() can
++       * simply ignore them.
++       */
++      if (!skl_dbuf_is_misconfigured(i915))
++              return;
++
++      drm_dbg_kms(&i915->drm, "BIOS has misprogrammed the DBUF, disabling all planes\n");
++
++      for_each_intel_crtc(&i915->drm, crtc) {
++              struct intel_plane *plane = to_intel_plane(crtc->base.primary);
++              const struct intel_plane_state *plane_state =
++                      to_intel_plane_state(plane->base.state);
++              struct intel_crtc_state *crtc_state =
++                      to_intel_crtc_state(crtc->base.state);
++
++              if (plane_state->uapi.visible)
++                      intel_plane_disable_noatomic(crtc, plane);
++
++              drm_WARN_ON(&i915->drm, crtc_state->active_planes != 0);
++
++              memset(&crtc_state->wm.skl.ddb, 0, sizeof(crtc_state->wm.skl.ddb));
++      }
++}
++
+ static void ilk_pipe_wm_get_hw_state(struct intel_crtc *crtc)
+ {
+       struct drm_device *dev = crtc->base.dev;
+diff --git a/drivers/gpu/drm/i915/intel_pm.h b/drivers/gpu/drm/i915/intel_pm.h
+index 91f23b7f0af2e..79d89fe22d8c8 100644
+--- a/drivers/gpu/drm/i915/intel_pm.h
++++ b/drivers/gpu/drm/i915/intel_pm.h
+@@ -48,6 +48,7 @@ void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc,
+                             struct skl_pipe_wm *out);
+ void g4x_wm_sanitize(struct drm_i915_private *dev_priv);
+ void vlv_wm_sanitize(struct drm_i915_private *dev_priv);
++void skl_wm_sanitize(struct drm_i915_private *dev_priv);
+ bool intel_can_enable_sagv(struct drm_i915_private *dev_priv,
+                          const struct intel_bw_state *bw_state);
+ void intel_sagv_pre_plane_update(struct intel_atomic_state *state);
+-- 
+2.34.1
+
diff --git a/queue-5.15/drm-mediatek-mtk_dsi-avoid-eprobe_defer-loop-with-ex.patch b/queue-5.15/drm-mediatek-mtk_dsi-avoid-eprobe_defer-loop-with-ex.patch
new file mode 100644 (file)
index 0000000..32489df
--- /dev/null
@@ -0,0 +1,268 @@
+From 460c08e7fbc77dbfe90b71ecd174041ef795413f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 31 Jan 2022 09:55:20 +0100
+Subject: drm/mediatek: mtk_dsi: Avoid EPROBE_DEFER loop with external bridge
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+[ Upstream commit 647474b8d980256b26b1cd112d7333a4dbd4260a ]
+
+DRM bridge drivers are now attaching their DSI device at probe time,
+which requires us to register our DSI host in order to let the bridge
+to probe: this recently started producing an endless -EPROBE_DEFER
+loop on some machines that are using external bridges, like the
+parade-ps8640, found on the ACER Chromebook R13.
+
+Now that the DSI hosts/devices probe sequence is documented, we can
+do adjustments to the mtk_dsi driver as to both fix now and make sure
+to avoid this situation in the future: for this, following what is
+documented in drm_bridge.c, move the mtk_dsi component_add() to the
+mtk_dsi_ops.attach callback and delete it in the detach callback;
+keeping in mind that we are registering a drm_bridge for our DSI,
+which is only used/attached if the DSI Host is bound, it wouldn't
+make sense to keep adding our bridge at probe time (as it would
+be useless to have it if mtk_dsi_ops.attach() fails!), so also move
+that one to the dsi host attach function (and remove it in detach).
+
+Cc: <stable@vger.kernel.org> # 5.15.x
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
+Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>
+Tested-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
+Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/mediatek/mtk_dsi.c | 167 +++++++++++++++--------------
+ 1 file changed, 84 insertions(+), 83 deletions(-)
+
+diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
+index 5d90d2eb00193..bced4c7d668e3 100644
+--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
++++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
+@@ -786,18 +786,101 @@ void mtk_dsi_ddp_stop(struct device *dev)
+       mtk_dsi_poweroff(dsi);
+ }
++static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
++{
++      int ret;
++
++      ret = drm_simple_encoder_init(drm, &dsi->encoder,
++                                    DRM_MODE_ENCODER_DSI);
++      if (ret) {
++              DRM_ERROR("Failed to encoder init to drm\n");
++              return ret;
++      }
++
++      dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
++
++      ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
++                              DRM_BRIDGE_ATTACH_NO_CONNECTOR);
++      if (ret)
++              goto err_cleanup_encoder;
++
++      dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
++      if (IS_ERR(dsi->connector)) {
++              DRM_ERROR("Unable to create bridge connector\n");
++              ret = PTR_ERR(dsi->connector);
++              goto err_cleanup_encoder;
++      }
++      drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
++
++      return 0;
++
++err_cleanup_encoder:
++      drm_encoder_cleanup(&dsi->encoder);
++      return ret;
++}
++
++static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
++{
++      int ret;
++      struct drm_device *drm = data;
++      struct mtk_dsi *dsi = dev_get_drvdata(dev);
++
++      ret = mtk_dsi_encoder_init(drm, dsi);
++      if (ret)
++              return ret;
++
++      return device_reset_optional(dev);
++}
++
++static void mtk_dsi_unbind(struct device *dev, struct device *master,
++                         void *data)
++{
++      struct mtk_dsi *dsi = dev_get_drvdata(dev);
++
++      drm_encoder_cleanup(&dsi->encoder);
++}
++
++static const struct component_ops mtk_dsi_component_ops = {
++      .bind = mtk_dsi_bind,
++      .unbind = mtk_dsi_unbind,
++};
++
+ static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
+                              struct mipi_dsi_device *device)
+ {
+       struct mtk_dsi *dsi = host_to_dsi(host);
++      struct device *dev = host->dev;
++      int ret;
+       dsi->lanes = device->lanes;
+       dsi->format = device->format;
+       dsi->mode_flags = device->mode_flags;
++      dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
++      if (IS_ERR(dsi->next_bridge))
++              return PTR_ERR(dsi->next_bridge);
++
++      drm_bridge_add(&dsi->bridge);
++
++      ret = component_add(host->dev, &mtk_dsi_component_ops);
++      if (ret) {
++              DRM_ERROR("failed to add dsi_host component: %d\n", ret);
++              drm_bridge_remove(&dsi->bridge);
++              return ret;
++      }
+       return 0;
+ }
++static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
++                             struct mipi_dsi_device *device)
++{
++      struct mtk_dsi *dsi = host_to_dsi(host);
++
++      component_del(host->dev, &mtk_dsi_component_ops);
++      drm_bridge_remove(&dsi->bridge);
++      return 0;
++}
++
+ static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
+ {
+       int ret;
+@@ -938,73 +1021,14 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
+ static const struct mipi_dsi_host_ops mtk_dsi_ops = {
+       .attach = mtk_dsi_host_attach,
++      .detach = mtk_dsi_host_detach,
+       .transfer = mtk_dsi_host_transfer,
+ };
+-static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
+-{
+-      int ret;
+-
+-      ret = drm_simple_encoder_init(drm, &dsi->encoder,
+-                                    DRM_MODE_ENCODER_DSI);
+-      if (ret) {
+-              DRM_ERROR("Failed to encoder init to drm\n");
+-              return ret;
+-      }
+-
+-      dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
+-
+-      ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
+-                              DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+-      if (ret)
+-              goto err_cleanup_encoder;
+-
+-      dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
+-      if (IS_ERR(dsi->connector)) {
+-              DRM_ERROR("Unable to create bridge connector\n");
+-              ret = PTR_ERR(dsi->connector);
+-              goto err_cleanup_encoder;
+-      }
+-      drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
+-
+-      return 0;
+-
+-err_cleanup_encoder:
+-      drm_encoder_cleanup(&dsi->encoder);
+-      return ret;
+-}
+-
+-static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
+-{
+-      int ret;
+-      struct drm_device *drm = data;
+-      struct mtk_dsi *dsi = dev_get_drvdata(dev);
+-
+-      ret = mtk_dsi_encoder_init(drm, dsi);
+-      if (ret)
+-              return ret;
+-
+-      return device_reset_optional(dev);
+-}
+-
+-static void mtk_dsi_unbind(struct device *dev, struct device *master,
+-                         void *data)
+-{
+-      struct mtk_dsi *dsi = dev_get_drvdata(dev);
+-
+-      drm_encoder_cleanup(&dsi->encoder);
+-}
+-
+-static const struct component_ops mtk_dsi_component_ops = {
+-      .bind = mtk_dsi_bind,
+-      .unbind = mtk_dsi_unbind,
+-};
+-
+ static int mtk_dsi_probe(struct platform_device *pdev)
+ {
+       struct mtk_dsi *dsi;
+       struct device *dev = &pdev->dev;
+-      struct drm_panel *panel;
+       struct resource *regs;
+       int irq_num;
+       int ret;
+@@ -1021,19 +1045,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
+               return ret;
+       }
+-      ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
+-                                        &panel, &dsi->next_bridge);
+-      if (ret)
+-              goto err_unregister_host;
+-
+-      if (panel) {
+-              dsi->next_bridge = devm_drm_panel_bridge_add(dev, panel);
+-              if (IS_ERR(dsi->next_bridge)) {
+-                      ret = PTR_ERR(dsi->next_bridge);
+-                      goto err_unregister_host;
+-              }
+-      }
+-
+       dsi->driver_data = of_device_get_match_data(dev);
+       dsi->engine_clk = devm_clk_get(dev, "engine");
+@@ -1098,14 +1109,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
+       dsi->bridge.of_node = dev->of_node;
+       dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
+-      drm_bridge_add(&dsi->bridge);
+-
+-      ret = component_add(&pdev->dev, &mtk_dsi_component_ops);
+-      if (ret) {
+-              dev_err(&pdev->dev, "failed to add component: %d\n", ret);
+-              goto err_unregister_host;
+-      }
+-
+       return 0;
+ err_unregister_host:
+@@ -1118,8 +1121,6 @@ static int mtk_dsi_remove(struct platform_device *pdev)
+       struct mtk_dsi *dsi = platform_get_drvdata(pdev);
+       mtk_output_dsi_disable(dsi);
+-      drm_bridge_remove(&dsi->bridge);
+-      component_del(&pdev->dev, &mtk_dsi_component_ops);
+       mipi_dsi_host_unregister(&dsi->host);
+       return 0;
+-- 
+2.34.1
+
diff --git a/queue-5.15/drm-mediatek-mtk_dsi-reset-the-dsi0-hardware.patch b/queue-5.15/drm-mediatek-mtk_dsi-reset-the-dsi0-hardware.patch
new file mode 100644 (file)
index 0000000..930b012
--- /dev/null
@@ -0,0 +1,55 @@
+From 0b673f13350208b4d5a98cb41ab106975cbfaa4f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Sep 2021 10:31:50 +0200
+Subject: drm/mediatek: mtk_dsi: Reset the dsi0 hardware
+
+From: Enric Balletbo i Serra <enric.balletbo@collabora.com>
+
+[ Upstream commit 605c83753d97946aab176735020a33ebfb0b4615 ]
+
+Reset dsi0 HW to default when power on. This prevents to have different
+settingis between the bootloader and the kernel.
+
+As not all Mediatek boards have the reset consumer configured in their
+board description, also is not needed on all of them, the reset is optional,
+so the change is compatible with all boards.
+
+Cc: Jitao Shi <jitao.shi@mediatek.com>
+Suggested-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
+Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
+Acked-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
+Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
+Link: https://lore.kernel.org/r/20210930103105.v4.7.Idbb4727ddf00ba2fe796b630906baff10d994d89@changeid
+Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/mediatek/mtk_dsi.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
+index 93b40c245f007..5d90d2eb00193 100644
+--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
++++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
+@@ -11,6 +11,7 @@
+ #include <linux/of_platform.h>
+ #include <linux/phy/phy.h>
+ #include <linux/platform_device.h>
++#include <linux/reset.h>
+ #include <video/mipi_display.h>
+ #include <video/videomode.h>
+@@ -980,8 +981,10 @@ static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
+       struct mtk_dsi *dsi = dev_get_drvdata(dev);
+       ret = mtk_dsi_encoder_init(drm, dsi);
++      if (ret)
++              return ret;
+-      return ret;
++      return device_reset_optional(dev);
+ }
+ static void mtk_dsi_unbind(struct device *dev, struct device *master,
+-- 
+2.34.1
+
diff --git a/queue-5.15/drm-mxsfb-fix-null-pointer-dereference.patch b/queue-5.15/drm-mxsfb-fix-null-pointer-dereference.patch
new file mode 100644 (file)
index 0000000..84c75f0
--- /dev/null
@@ -0,0 +1,42 @@
+From 16d1845d71f4224988a9cc7b2a6a9e07b0bc3401 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Feb 2022 09:17:55 +0100
+Subject: drm: mxsfb: Fix NULL pointer dereference
+
+From: Alexander Stein <alexander.stein@ew.tq-group.com>
+
+[ Upstream commit 622c9a3a7868e1eeca39c55305ca3ebec4742b64 ]
+
+mxsfb should not ever dereference the NULL pointer which
+drm_atomic_get_new_bridge_state is allowed to return.
+Assume a fixed format instead.
+
+Fixes: b776b0f00f24 ("drm: mxsfb: Use bus_format from the nearest bridge if present")
+Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com>
+Signed-off-by: Marek Vasut <marex@denx.de>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220202081755.145716-3-alexander.stein@ew.tq-group.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/mxsfb/mxsfb_kms.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
+index b96ba348c68d9..988bc4fbd78df 100644
+--- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
++++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
+@@ -361,7 +361,11 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc,
+               bridge_state =
+                       drm_atomic_get_new_bridge_state(state,
+                                                       mxsfb->bridge);
+-              bus_format = bridge_state->input_bus_cfg.format;
++              if (!bridge_state)
++                      bus_format = MEDIA_BUS_FMT_FIXED;
++              else
++                      bus_format = bridge_state->input_bus_cfg.format;
++
+               if (bus_format == MEDIA_BUS_FMT_FIXED) {
+                       dev_warn_once(drm->dev,
+                                     "Bridge does not provide bus format, assuming MEDIA_BUS_FMT_RGB888_1X24.\n"
+-- 
+2.34.1
+
diff --git a/queue-5.15/drm-mxsfb-set-fallback-bus-format-when-the-bridge-do.patch b/queue-5.15/drm-mxsfb-set-fallback-bus-format-when-the-bridge-do.patch
new file mode 100644 (file)
index 0000000..b431884
--- /dev/null
@@ -0,0 +1,50 @@
+From 1153d6f3ae72e8cdfc119494d61628384447c625 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Oct 2021 15:41:27 +0200
+Subject: drm: mxsfb: Set fallback bus format when the bridge doesn't provide
+ one
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Guido Günther <agx@sigxcpu.org>
+
+[ Upstream commit 1db060509903b29d63fe2e39c14fd0f99c4a447e ]
+
+If a bridge doesn't do any bus format handling MEDIA_BUS_FMT_FIXED is
+returned. Fallback to a reasonable default (MEDIA_BUS_FMT_RGB888_1X24) in
+that case.
+
+This unbreaks e.g. using mxsfb with the nwl bridge and mipi dsi panels.
+
+Reported-by: Martin Kepplinger <martink@posteo.de>
+Signed-off-by: Guido Günther <agx@sigxcpu.org>
+Reviewed-by: Lucas Stach <l.stach@pengutronix.de>
+Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
+Acked-by: Stefan Agner <stefan@agner.ch>
+Link: https://patchwork.freedesktop.org/patch/msgid/781f0352052cc50c823c199ef5f53c84902d0580.1633959458.git.agx@sigxcpu.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/mxsfb/mxsfb_kms.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
+index 89dd618d78f31..b96ba348c68d9 100644
+--- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c
++++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c
+@@ -362,6 +362,12 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc,
+                       drm_atomic_get_new_bridge_state(state,
+                                                       mxsfb->bridge);
+               bus_format = bridge_state->input_bus_cfg.format;
++              if (bus_format == MEDIA_BUS_FMT_FIXED) {
++                      dev_warn_once(drm->dev,
++                                    "Bridge does not provide bus format, assuming MEDIA_BUS_FMT_RGB888_1X24.\n"
++                                    "Please fix bridge driver by handling atomic_get_input_bus_fmts.\n");
++                      bus_format = MEDIA_BUS_FMT_RGB888_1X24;
++              }
+       }
+       /* If there is no bridge, use bus format from connector */
+-- 
+2.34.1
+
diff --git a/queue-5.15/drm-sun4i-dw-hdmi-fix-missing-put_device-call-in-sun.patch b/queue-5.15/drm-sun4i-dw-hdmi-fix-missing-put_device-call-in-sun.patch
new file mode 100644 (file)
index 0000000..0e14717
--- /dev/null
@@ -0,0 +1,42 @@
+From f1c7237c9e9b5cd94246d005bdb28882a47b44ec Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Jan 2022 08:36:32 +0000
+Subject: drm/sun4i: dw-hdmi: Fix missing put_device() call in
+ sun8i_hdmi_phy_get
+
+From: Miaoqian Lin <linmq006@gmail.com>
+
+[ Upstream commit c71af3dae3e34d2fde0c19623cf7f8483321f0e3 ]
+
+The reference taken by 'of_find_device_by_node()' must be released when
+not needed anymore.
+Add the corresponding 'put_device()' in the error handling path.
+
+Fixes: 9bf3797796f5 ("drm/sun4i: dw-hdmi: Make HDMI PHY into a platform device")
+Signed-off-by: Miaoqian Lin <linmq006@gmail.com>
+Signed-off-by: Maxime Ripard <maxime@cerno.tech>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220107083633.20843-1-linmq006@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+index b64d93da651d2..5e2b0175df36f 100644
+--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
++++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+@@ -658,8 +658,10 @@ int sun8i_hdmi_phy_get(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
+               return -EPROBE_DEFER;
+       phy = platform_get_drvdata(pdev);
+-      if (!phy)
++      if (!phy) {
++              put_device(&pdev->dev);
+               return -EPROBE_DEFER;
++      }
+       hdmi->phy = phy;
+-- 
+2.34.1
+
diff --git a/queue-5.15/ethtool-fix-link-extended-state-for-big-endian.patch b/queue-5.15/ethtool-fix-link-extended-state-for-big-endian.patch
new file mode 100644 (file)
index 0000000..6905bab
--- /dev/null
@@ -0,0 +1,42 @@
+From 9459c0d5df599fef4ea450453d6b4031bec9773d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Jan 2022 11:55:50 +0200
+Subject: ethtool: Fix link extended state for big endian
+
+From: Moshe Tal <moshet@nvidia.com>
+
+[ Upstream commit e2f08207c558bc0bc8abaa557cdb29bad776ac7b ]
+
+The link extended sub-states are assigned as enum that is an integer
+size but read from a union as u8, this is working for small values on
+little endian systems but for big endian this always give 0. Fix the
+variable in the union to match the enum size.
+
+Fixes: ecc31c60240b ("ethtool: Add link extended state")
+Signed-off-by: Moshe Tal <moshet@nvidia.com>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Tested-by: Ido Schimmel <idosch@nvidia.com>
+Reviewed-by: Gal Pressman <gal@nvidia.com>
+Reviewed-by: Amit Cohen <amcohen@nvidia.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/ethtool.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
+index 849524b55d89a..3fad741df53ef 100644
+--- a/include/linux/ethtool.h
++++ b/include/linux/ethtool.h
+@@ -94,7 +94,7 @@ struct ethtool_link_ext_state_info {
+               enum ethtool_link_ext_substate_link_logical_mismatch link_logical_mismatch;
+               enum ethtool_link_ext_substate_bad_signal_integrity bad_signal_integrity;
+               enum ethtool_link_ext_substate_cable_issue cable_issue;
+-              u8 __link_ext_substate;
++              u32 __link_ext_substate;
+       };
+ };
+-- 
+2.34.1
+
diff --git a/queue-5.15/gve-recording-rx-queue-before-sending-to-napi.patch b/queue-5.15/gve-recording-rx-queue-before-sending-to-napi.patch
new file mode 100644 (file)
index 0000000..977590f
--- /dev/null
@@ -0,0 +1,36 @@
+From 9057e49e9e9d3caf90620f83692593748922b325 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 7 Feb 2022 09:59:01 -0800
+Subject: gve: Recording rx queue before sending to napi
+
+From: Tao Liu <xliutaox@google.com>
+
+[ Upstream commit 084cbb2ec3af2d23be9de65fcc9493e21e265859 ]
+
+This caused a significant performance degredation when using generic XDP
+with multiple queues.
+
+Fixes: f5cedc84a30d2 ("gve: Add transmit and receive support")
+Signed-off-by: Tao Liu <xliutaox@google.com>
+Link: https://lore.kernel.org/r/20220207175901.2486596-1-jeroendb@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/google/gve/gve_rx.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/google/gve/gve_rx.c b/drivers/net/ethernet/google/gve/gve_rx.c
+index 629d8ed08fc61..97431969a488f 100644
+--- a/drivers/net/ethernet/google/gve/gve_rx.c
++++ b/drivers/net/ethernet/google/gve/gve_rx.c
+@@ -450,6 +450,7 @@ static bool gve_rx(struct gve_rx_ring *rx, struct gve_rx_desc *rx_desc,
+               skb_set_hash(skb, be32_to_cpu(rx_desc->rss_hash),
+                            gve_rss_type(rx_desc->flags_seq));
++      skb_record_rx_queue(skb, rx->q_num);
+       if (skb_is_nonlinear(skb))
+               napi_gro_frags(napi);
+       else
+-- 
+2.34.1
+
diff --git a/queue-5.15/hugetlbfs-fix-off-by-one-error-in-hugetlb_vmdelete_l.patch b/queue-5.15/hugetlbfs-fix-off-by-one-error-in-hugetlb_vmdelete_l.patch
new file mode 100644 (file)
index 0000000..4266f56
--- /dev/null
@@ -0,0 +1,63 @@
+From ba30006e8f89da85729012c9bf2cdf85f95b92f7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Jan 2022 14:08:30 -0800
+Subject: hugetlbfs: fix off-by-one error in hugetlb_vmdelete_list()
+
+From: Sean Christopherson <seanjc@google.com>
+
+[ Upstream commit d6aba4c8e20d4d2bf65d589953f6d891c178f3a3 ]
+
+Pass "end - 1" instead of "end" when walking the interval tree in
+hugetlb_vmdelete_list() to fix an inclusive vs.  exclusive bug.  The two
+callers that pass a non-zero "end" treat it as exclusive, whereas the
+interval tree iterator expects an inclusive "last".  E.g.  punching a
+hole in a file that precisely matches the size of a single hugepage,
+with a vma starting right on the boundary, will result in
+unmap_hugepage_range() being called twice, with the second call having
+start==end.
+
+The off-by-one error doesn't cause functional problems as
+__unmap_hugepage_range() turns into a massive nop due to
+short-circuiting its for-loop on "address < end".  But, the mmu_notifier
+invocations to invalid_range_{start,end}() are passed a bogus zero-sized
+range, which may be unexpected behavior for secondary MMUs.
+
+The bug was exposed by commit ed922739c919 ("KVM: Use interval tree to
+do fast hva lookup in memslots"), currently queued in the KVM tree for
+5.17, which added a WARN to detect ranges with start==end.
+
+Link: https://lkml.kernel.org/r/20211228234257.1926057-1-seanjc@google.com
+Fixes: 1bfad99ab425 ("hugetlbfs: hugetlb_vmtruncate_list() needs to take a range to delete")
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Reported-by: syzbot+4e697fe80a31aa7efe21@syzkaller.appspotmail.com
+Reviewed-by: Mike Kravetz <mike.kravetz@oracle.com>
+Cc: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/hugetlbfs/inode.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
+index cdfb1ae78a3f8..54c4e0b0dda4a 100644
+--- a/fs/hugetlbfs/inode.c
++++ b/fs/hugetlbfs/inode.c
+@@ -409,10 +409,11 @@ hugetlb_vmdelete_list(struct rb_root_cached *root, pgoff_t start, pgoff_t end)
+       struct vm_area_struct *vma;
+       /*
+-       * end == 0 indicates that the entire range after
+-       * start should be unmapped.
++       * end == 0 indicates that the entire range after start should be
++       * unmapped.  Note, end is exclusive, whereas the interval tree takes
++       * an inclusive "last".
+        */
+-      vma_interval_tree_foreach(vma, root, start, end ? end : ULONG_MAX) {
++      vma_interval_tree_foreach(vma, root, start, end ? end - 1 : ULONG_MAX) {
+               unsigned long v_offset;
+               unsigned long v_end;
+-- 
+2.34.1
+
diff --git a/queue-5.15/i3c-fix-incorrect-address-slot-lookup-on-64-bit.patch b/queue-5.15/i3c-fix-incorrect-address-slot-lookup-on-64-bit.patch
new file mode 100644 (file)
index 0000000..bbb8552
--- /dev/null
@@ -0,0 +1,42 @@
+From f90b5ab43f4ff136848ca34ad0add59f3b4bcf79 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Sep 2021 17:56:00 +0100
+Subject: i3c: fix incorrect address slot lookup on 64-bit
+
+From: Jamie Iles <quic_jiles@quicinc.com>
+
+[ Upstream commit f18f98110f2b179792cb70d85cba697320a3790f ]
+
+The address slot bitmap is an array of unsigned long's which are the
+same size as an int on 32-bit platforms but not 64-bit.  Loading the
+bitmap into an int could result in the incorrect status being returned
+for a slot and slots being reported as the wrong status.
+
+Fixes: 3a379bbcea0a ("i3c: Add core I3C infrastructure")
+Cc: Boris Brezillon <bbrezillon@kernel.org>
+Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Signed-off-by: Jamie Iles <quic_jiles@quicinc.com>
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Link: https://lore.kernel.org/r/20210922165600.179394-1-quic_jiles@quicinc.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i3c/master.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
+index c3b4c677b4429..dfe18dcd008d4 100644
+--- a/drivers/i3c/master.c
++++ b/drivers/i3c/master.c
+@@ -343,7 +343,8 @@ struct bus_type i3c_bus_type = {
+ static enum i3c_addr_slot_status
+ i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
+ {
+-      int status, bitpos = addr * 2;
++      unsigned long status;
++      int bitpos = addr * 2;
+       if (addr > I2C_MAX_ADDR)
+               return I3C_ADDR_SLOT_RSVD;
+-- 
+2.34.1
+
diff --git a/queue-5.15/i3c-master-dw-check-return-of-dw_i3c_master_get_free.patch b/queue-5.15/i3c-master-dw-check-return-of-dw_i3c_master_get_free.patch
new file mode 100644 (file)
index 0000000..4c2ea3c
--- /dev/null
@@ -0,0 +1,45 @@
+From 5170d69923c048228abe57909b2c1ec6e2c334c9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Jan 2022 07:09:48 -0800
+Subject: i3c: master: dw: check return of dw_i3c_master_get_free_pos()
+
+From: Tom Rix <trix@redhat.com>
+
+[ Upstream commit 13462ba1815db5a96891293a9cfaa2451f7bd623 ]
+
+Clang static analysis reports this problem
+dw-i3c-master.c:799:9: warning: The result of the left shift is
+  undefined because the left operand is negative
+                      COMMAND_PORT_DEV_INDEX(pos) |
+                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+pos can be negative because dw_i3c_master_get_free_pos() can return an
+error.  So check for an error.
+
+Fixes: 1dd728f5d4d4 ("i3c: master: Add driver for Synopsys DesignWare IP")
+Signed-off-by: Tom Rix <trix@redhat.com>
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Link: https://lore.kernel.org/r/20220108150948.3988790-1-trix@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i3c/master/dw-i3c-master.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c
+index 03a368da51b95..51a8608203de7 100644
+--- a/drivers/i3c/master/dw-i3c-master.c
++++ b/drivers/i3c/master/dw-i3c-master.c
+@@ -793,6 +793,10 @@ static int dw_i3c_master_daa(struct i3c_master_controller *m)
+               return -ENOMEM;
+       pos = dw_i3c_master_get_free_pos(master);
++      if (pos < 0) {
++              dw_i3c_master_free_xfer(xfer);
++              return pos;
++      }
+       cmd = &xfer->cmds[0];
+       cmd->cmd_hi = 0x1;
+       cmd->cmd_lo = COMMAND_PORT_DEV_COUNT(master->maxdevs - pos) |
+-- 
+2.34.1
+
diff --git a/queue-5.15/i3c-master-mipi-i3c-hci-fix-a-potentially-infinite-l.patch b/queue-5.15/i3c-master-mipi-i3c-hci-fix-a-potentially-infinite-l.patch
new file mode 100644 (file)
index 0000000..7fd3ec5
--- /dev/null
@@ -0,0 +1,48 @@
+From 8e9f8d8f0fb81cc6912cb8d858883799008074fd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 17 Nov 2021 23:05:23 +0100
+Subject: i3c/master/mipi-i3c-hci: Fix a potentially infinite loop in
+ 'hci_dat_v1_get_index()'
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit 3f43926f271287fb1744c9ac9ae1122497f2b0c2 ]
+
+The code in 'hci_dat_v1_get_index()' really looks like a hand coded version
+of 'for_each_set_bit()', except that a +1 is missing when searching for the
+next set bit.
+
+This really looks odd and it seems that it will loop until 'dat_w0_read()'
+returns the expected result.
+
+So use 'for_each_set_bit()' instead. It is less verbose and should be more
+correct.
+
+Fixes: 9ad9a52cce28 ("i3c/master: introduce the mipi-i3c-hci driver")
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Acked-by: Nicolas Pitre <npitre@baylibre.com>
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Link: https://lore.kernel.org/r/0cdf3cb10293ead1acd271fdb8a70369c298c082.1637186628.git.christophe.jaillet@wanadoo.fr
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i3c/master/mipi-i3c-hci/dat_v1.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/drivers/i3c/master/mipi-i3c-hci/dat_v1.c b/drivers/i3c/master/mipi-i3c-hci/dat_v1.c
+index 783e551a2c85a..97bb49ff5b53b 100644
+--- a/drivers/i3c/master/mipi-i3c-hci/dat_v1.c
++++ b/drivers/i3c/master/mipi-i3c-hci/dat_v1.c
+@@ -160,9 +160,7 @@ static int hci_dat_v1_get_index(struct i3c_hci *hci, u8 dev_addr)
+       unsigned int dat_idx;
+       u32 dat_w0;
+-      for (dat_idx = find_first_bit(hci->DAT_data, hci->DAT_entries);
+-           dat_idx < hci->DAT_entries;
+-           dat_idx = find_next_bit(hci->DAT_data, hci->DAT_entries, dat_idx)) {
++      for_each_set_bit(dat_idx, hci->DAT_data, hci->DAT_entries) {
+               dat_w0 = dat_w0_read(dat_idx);
+               if (FIELD_GET(DAT_0_DYNAMIC_ADDRESS, dat_w0) == dev_addr)
+                       return dat_idx;
+-- 
+2.34.1
+
diff --git a/queue-5.15/ibmvnic-don-t-release-napi-in-__ibmvnic_open.patch b/queue-5.15/ibmvnic-don-t-release-napi-in-__ibmvnic_open.patch
new file mode 100644 (file)
index 0000000..c11cce3
--- /dev/null
@@ -0,0 +1,108 @@
+From 479e4b164d3df2a26506c1db2db3747e8895ce98 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 7 Feb 2022 16:19:18 -0800
+Subject: ibmvnic: don't release napi in __ibmvnic_open()
+
+From: Sukadev Bhattiprolu <sukadev@linux.ibm.com>
+
+[ Upstream commit 61772b0908c640d0309c40f7d41d062ca4e979fa ]
+
+If __ibmvnic_open() encounters an error such as when setting link state,
+it calls release_resources() which frees the napi structures needlessly.
+Instead, have __ibmvnic_open() only clean up the work it did so far (i.e.
+disable napi and irqs) and leave the rest to the callers.
+
+If caller of __ibmvnic_open() is ibmvnic_open(), it should release the
+resources immediately. If the caller is do_reset() or do_hard_reset(),
+they will release the resources on the next reset.
+
+This fixes following crash that occurred when running the drmgr command
+several times to add/remove a vnic interface:
+
+       [102056] ibmvnic 30000003 env3: Disabling rx_scrq[6] irq
+       [102056] ibmvnic 30000003 env3: Disabling rx_scrq[7] irq
+       [102056] ibmvnic 30000003 env3: Replenished 8 pools
+       Kernel attempted to read user page (10) - exploit attempt? (uid: 0)
+       BUG: Kernel NULL pointer dereference on read at 0x00000010
+       Faulting instruction address: 0xc000000000a3c840
+       Oops: Kernel access of bad area, sig: 11 [#1]
+       LE PAGE_SIZE=64K MMU=Radix SMP NR_CPUS=2048 NUMA pSeries
+       ...
+       CPU: 9 PID: 102056 Comm: kworker/9:2 Kdump: loaded Not tainted 5.16.0-rc5-autotest-g6441998e2e37 #1
+       Workqueue: events_long __ibmvnic_reset [ibmvnic]
+       NIP:  c000000000a3c840 LR: c0080000029b5378 CTR: c000000000a3c820
+       REGS: c0000000548e37e0 TRAP: 0300   Not tainted  (5.16.0-rc5-autotest-g6441998e2e37)
+       MSR:  8000000000009033 <SF,EE,ME,IR,DR,RI,LE>  CR: 28248484  XER: 00000004
+       CFAR: c0080000029bdd24 DAR: 0000000000000010 DSISR: 40000000 IRQMASK: 0
+       GPR00: c0080000029b55d0 c0000000548e3a80 c0000000028f0200 0000000000000000
+       ...
+       NIP [c000000000a3c840] napi_enable+0x20/0xc0
+       LR [c0080000029b5378] __ibmvnic_open+0xf0/0x430 [ibmvnic]
+       Call Trace:
+       [c0000000548e3a80] [0000000000000006] 0x6 (unreliable)
+       [c0000000548e3ab0] [c0080000029b55d0] __ibmvnic_open+0x348/0x430 [ibmvnic]
+       [c0000000548e3b40] [c0080000029bcc28] __ibmvnic_reset+0x500/0xdf0 [ibmvnic]
+       [c0000000548e3c60] [c000000000176228] process_one_work+0x288/0x570
+       [c0000000548e3d00] [c000000000176588] worker_thread+0x78/0x660
+       [c0000000548e3da0] [c0000000001822f0] kthread+0x1c0/0x1d0
+       [c0000000548e3e10] [c00000000000cf64] ret_from_kernel_thread+0x5c/0x64
+       Instruction dump:
+       7d2948f8 792307e0 4e800020 60000000 3c4c01eb 384239e0 f821ffd1 39430010
+       38a0fff6 e92d1100 f9210028 39200000 <e9030010> f9010020 60420000 e9210020
+       ---[ end trace 5f8033b08fd27706 ]---
+
+Fixes: ed651a10875f ("ibmvnic: Updated reset handling")
+Reported-by: Abdul Haleem <abdhalee@linux.vnet.ibm.com>
+Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.ibm.com>
+Reviewed-by: Dany Madden <drt@linux.ibm.com>
+Link: https://lore.kernel.org/r/20220208001918.900602-1-sukadev@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/ibm/ibmvnic.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
+index 14a729ba737a8..cc5ab66a81850 100644
+--- a/drivers/net/ethernet/ibm/ibmvnic.c
++++ b/drivers/net/ethernet/ibm/ibmvnic.c
+@@ -108,6 +108,7 @@ static int init_crq_queue(struct ibmvnic_adapter *adapter);
+ static int send_query_phys_parms(struct ibmvnic_adapter *adapter);
+ static void ibmvnic_tx_scrq_clean_buffer(struct ibmvnic_adapter *adapter,
+                                        struct ibmvnic_sub_crq_queue *tx_scrq);
++static void ibmvnic_disable_irqs(struct ibmvnic_adapter *adapter);
+ struct ibmvnic_stat {
+       char name[ETH_GSTRING_LEN];
+@@ -1245,7 +1246,7 @@ static int __ibmvnic_open(struct net_device *netdev)
+       rc = set_link_state(adapter, IBMVNIC_LOGICAL_LNK_UP);
+       if (rc) {
+               ibmvnic_napi_disable(adapter);
+-              release_resources(adapter);
++              ibmvnic_disable_irqs(adapter);
+               return rc;
+       }
+@@ -1295,7 +1296,6 @@ static int ibmvnic_open(struct net_device *netdev)
+               rc = init_resources(adapter);
+               if (rc) {
+                       netdev_err(netdev, "failed to initialize resources\n");
+-                      release_resources(adapter);
+                       goto out;
+               }
+       }
+@@ -1312,6 +1312,11 @@ static int ibmvnic_open(struct net_device *netdev)
+               adapter->state = VNIC_OPEN;
+               rc = 0;
+       }
++
++      if (rc) {
++              release_resources(adapter);
++      }
++
+       return rc;
+ }
+-- 
+2.34.1
+
diff --git a/queue-5.15/input-ti_am335x_tsc-fix-stepconfig-setup-for-z2.patch b/queue-5.15/input-ti_am335x_tsc-fix-stepconfig-setup-for-z2.patch
new file mode 100644 (file)
index 0000000..359f187
--- /dev/null
@@ -0,0 +1,41 @@
+From b4c807b11f8688dc42d4f14aed342877f80c74d2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 12 Dec 2021 21:14:48 -0800
+Subject: Input: ti_am335x_tsc - fix STEPCONFIG setup for Z2
+
+From: Dario Binacchi <dariobin@libero.it>
+
+[ Upstream commit 6bfeb6c21e1bdc11c328b7d996d20f0f73c6b9b0 ]
+
+The Z2 step configuration doesn't erase the SEL_INP_SWC_3_0 bit-field
+before setting the ADC channel. This way its value could be corrupted by
+the ADC channel selected for the Z1 coordinate.
+
+Fixes: 8c896308feae ("input: ti_am335x_adc: use only FIFO0 and clean up a little")
+Signed-off-by: Dario Binacchi <dariobin@libero.it>
+Link: https://lore.kernel.org/r/20211212125358.14416-3-dariobin@libero.it
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/input/touchscreen/ti_am335x_tsc.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
+index fd3ffdd23470b..cfc943423241f 100644
+--- a/drivers/input/touchscreen/ti_am335x_tsc.c
++++ b/drivers/input/touchscreen/ti_am335x_tsc.c
+@@ -196,7 +196,10 @@ static void titsc_step_config(struct titsc *ts_dev)
+                       STEPCONFIG_OPENDLY);
+       end_step++;
+-      config |= STEPCONFIG_INP(ts_dev->inp_yn);
++      config = STEPCONFIG_MODE_HWSYNC |
++                      STEPCONFIG_AVG_16 | ts_dev->bit_yp |
++                      ts_dev->bit_xn | STEPCONFIG_INM_ADCREFM |
++                      STEPCONFIG_INP(ts_dev->inp_yn);
+       titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config);
+       titsc_writel(ts_dev, REG_STEPDELAY(end_step),
+                       STEPCONFIG_OPENDLY);
+-- 
+2.34.1
+
diff --git a/queue-5.15/input-ti_am335x_tsc-set-adcrefm-for-x-configuration.patch b/queue-5.15/input-ti_am335x_tsc-set-adcrefm-for-x-configuration.patch
new file mode 100644 (file)
index 0000000..0bf0e6d
--- /dev/null
@@ -0,0 +1,42 @@
+From d3e5391b28c80d8e6b027a5947dce8c7b3b343b9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 12 Dec 2021 21:14:35 -0800
+Subject: Input: ti_am335x_tsc - set ADCREFM for X configuration
+
+From: Dario Binacchi <dariobin@libero.it>
+
+[ Upstream commit 73cca71a903202cddc8279fc76b2da4995da5bea ]
+
+As reported by the STEPCONFIG[1-16] registered field descriptions of the
+TI reference manual, for the ADC "in single ended, SEL_INM_SWC_3_0 must
+be 1xxx".
+
+Unlike the Y and Z coordinates, this bit has not been set for the step
+configuration registers used to sample the X coordinate.
+
+Fixes: 1b8be32e6914 ("Input: add support for TI Touchscreen controller")
+Signed-off-by: Dario Binacchi <dariobin@libero.it>
+Link: https://lore.kernel.org/r/20211212125358.14416-2-dariobin@libero.it
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/input/touchscreen/ti_am335x_tsc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
+index 83e685557a197..fd3ffdd23470b 100644
+--- a/drivers/input/touchscreen/ti_am335x_tsc.c
++++ b/drivers/input/touchscreen/ti_am335x_tsc.c
+@@ -131,7 +131,8 @@ static void titsc_step_config(struct titsc *ts_dev)
+       u32 stepenable;
+       config = STEPCONFIG_MODE_HWSYNC |
+-                      STEPCONFIG_AVG_16 | ts_dev->bit_xp;
++                      STEPCONFIG_AVG_16 | ts_dev->bit_xp |
++                      STEPCONFIG_INM_ADCREFM;
+       switch (ts_dev->wires) {
+       case 4:
+               config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
+-- 
+2.34.1
+
diff --git a/queue-5.15/io_uring-fix-no-lock-protection-for-ctx-cq_extra.patch b/queue-5.15/io_uring-fix-no-lock-protection-for-ctx-cq_extra.patch
new file mode 100644 (file)
index 0000000..d82c240
--- /dev/null
@@ -0,0 +1,43 @@
+From 9280fd6ba6fe7f3a1248d91847fe6180fc420b95 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Nov 2021 17:21:02 +0800
+Subject: io_uring: fix no lock protection for ctx->cq_extra
+
+From: Hao Xu <haoxu@linux.alibaba.com>
+
+[ Upstream commit e302f1046f4c209291b07ff7bc4d15ca26891f16 ]
+
+ctx->cq_extra should be protected by completion lock so that the
+req_need_defer() does the right check.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Hao Xu <haoxu@linux.alibaba.com>
+Link: https://lore.kernel.org/r/20211125092103.224502-2-haoxu@linux.alibaba.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/io_uring.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/fs/io_uring.c b/fs/io_uring.c
+index d7e49e87b49b9..156c54ebb62b7 100644
+--- a/fs/io_uring.c
++++ b/fs/io_uring.c
+@@ -6573,11 +6573,14 @@ static bool io_drain_req(struct io_kiocb *req)
+       }
+       /* Still need defer if there is pending req in defer list. */
++      spin_lock(&ctx->completion_lock);
+       if (likely(list_empty_careful(&ctx->defer_list) &&
+               !(req->flags & REQ_F_IO_DRAIN))) {
++              spin_unlock(&ctx->completion_lock);
+               ctx->drain_active = false;
+               return false;
+       }
++      spin_unlock(&ctx->completion_lock);
+       seq = io_get_sequence(req);
+       /* Still a chance to pass the sequence check */
+-- 
+2.34.1
+
diff --git a/queue-5.15/kasan-fix-quarantine-conflicting-with-init_on_free.patch b/queue-5.15/kasan-fix-quarantine-conflicting-with-init_on_free.patch
new file mode 100644 (file)
index 0000000..bc551ba
--- /dev/null
@@ -0,0 +1,63 @@
+From db0064f5b592974042fe6c4a4a7ea6892f1ca26c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Jan 2022 14:05:01 -0800
+Subject: kasan: fix quarantine conflicting with init_on_free
+
+From: Andrey Konovalov <andreyknvl@google.com>
+
+[ Upstream commit 26dca996ea7b1ac7008b6b6063fc88b849e3ac3e ]
+
+KASAN's quarantine might save its metadata inside freed objects.  As
+this happens after the memory is zeroed by the slab allocator when
+init_on_free is enabled, the memory coming out of quarantine is not
+properly zeroed.
+
+This causes lib/test_meminit.c tests to fail with Generic KASAN.
+
+Zero the metadata when the object is removed from quarantine.
+
+Link: https://lkml.kernel.org/r/2805da5df4b57138fdacd671f5d227d58950ba54.1640037083.git.andreyknvl@google.com
+Fixes: 6471384af2a6 ("mm: security: introduce init_on_alloc=1 and init_on_free=1 boot options")
+Signed-off-by: Andrey Konovalov <andreyknvl@google.com>
+Reviewed-by: Marco Elver <elver@google.com>
+Cc: Alexander Potapenko <glider@google.com>
+Cc: Andrey Konovalov <andreyknvl@gmail.com>
+Cc: Dmitry Vyukov <dvyukov@google.com>
+Cc: Andrey Ryabinin <ryabinin.a.a@gmail.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ mm/kasan/quarantine.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/mm/kasan/quarantine.c b/mm/kasan/quarantine.c
+index d8ccff4c1275e..47ed4fc33a29e 100644
+--- a/mm/kasan/quarantine.c
++++ b/mm/kasan/quarantine.c
+@@ -132,11 +132,22 @@ static void *qlink_to_object(struct qlist_node *qlink, struct kmem_cache *cache)
+ static void qlink_free(struct qlist_node *qlink, struct kmem_cache *cache)
+ {
+       void *object = qlink_to_object(qlink, cache);
++      struct kasan_free_meta *meta = kasan_get_free_meta(cache, object);
+       unsigned long flags;
+       if (IS_ENABLED(CONFIG_SLAB))
+               local_irq_save(flags);
++      /*
++       * If init_on_free is enabled and KASAN's free metadata is stored in
++       * the object, zero the metadata. Otherwise, the object's memory will
++       * not be properly zeroed, as KASAN saves the metadata after the slab
++       * allocator zeroes the object.
++       */
++      if (slab_want_init_on_free(cache) &&
++          cache->kasan_info.free_meta_offset == 0)
++              memzero_explicit(meta, sizeof(*meta));
++
+       /*
+        * As the object now gets freed from the quarantine, assume that its
+        * free track is no longer valid.
+-- 
+2.34.1
+
diff --git a/queue-5.15/kvm-s390-ensure-kvm_arch_no_poll-is-read-once-when-b.patch b/queue-5.15/kvm-s390-ensure-kvm_arch_no_poll-is-read-once-when-b.patch
new file mode 100644 (file)
index 0000000..3d350fa
--- /dev/null
@@ -0,0 +1,78 @@
+From 2274bce3b02d3be39e1413342e82bee1229f01b7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 Oct 2021 19:11:56 -0700
+Subject: KVM: s390: Ensure kvm_arch_no_poll() is read once when blocking vCPU
+
+From: Sean Christopherson <seanjc@google.com>
+
+[ Upstream commit 6f390916c4fb359507d9ac4bf1b28a4f8abee5c0 ]
+
+Wrap s390's halt_poll_max_steal with READ_ONCE and snapshot the result of
+kvm_arch_no_poll() in kvm_vcpu_block() to avoid a mostly-theoretical,
+largely benign bug on s390 where the result of kvm_arch_no_poll() could
+change due to userspace modifying halt_poll_max_steal while the vCPU is
+blocking.  The bug is largely benign as it will either cause KVM to skip
+updating halt-polling times (no_poll toggles false=>true) or to update
+halt-polling times with a slightly flawed block_ns.
+
+Note, READ_ONCE is unnecessary in the current code, add it in case the
+arch hook is ever inlined, and to provide a hint that userspace can
+change the param at will.
+
+Fixes: 8b905d28ee17 ("KVM: s390: provide kvm_arch_no_poll function")
+Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Message-Id: <20211009021236.4122790-4-seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/kvm/kvm-s390.c | 2 +-
+ virt/kvm/kvm_main.c      | 5 +++--
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
+index 9a8c086528f56..402597f9d0505 100644
+--- a/arch/s390/kvm/kvm-s390.c
++++ b/arch/s390/kvm/kvm-s390.c
+@@ -3447,7 +3447,7 @@ bool kvm_arch_no_poll(struct kvm_vcpu *vcpu)
+ {
+       /* do not poll with more than halt_poll_max_steal percent of steal time */
+       if (S390_lowcore.avg_steal_timer * 100 / (TICK_USEC << 12) >=
+-          halt_poll_max_steal) {
++          READ_ONCE(halt_poll_max_steal)) {
+               vcpu->stat.halt_no_poll_steal++;
+               return true;
+       }
+diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
+index 13aff136e6eef..f8b42e19bc775 100644
+--- a/virt/kvm/kvm_main.c
++++ b/virt/kvm/kvm_main.c
+@@ -3222,6 +3222,7 @@ update_halt_poll_stats(struct kvm_vcpu *vcpu, u64 poll_ns, bool waited)
+  */
+ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
+ {
++      bool halt_poll_allowed = !kvm_arch_no_poll(vcpu);
+       ktime_t start, cur, poll_end;
+       bool waited = false;
+       u64 block_ns;
+@@ -3229,7 +3230,7 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
+       kvm_arch_vcpu_blocking(vcpu);
+       start = cur = poll_end = ktime_get();
+-      if (vcpu->halt_poll_ns && !kvm_arch_no_poll(vcpu)) {
++      if (vcpu->halt_poll_ns && halt_poll_allowed) {
+               ktime_t stop = ktime_add_ns(ktime_get(), vcpu->halt_poll_ns);
+               ++vcpu->stat.generic.halt_attempted_poll;
+@@ -3284,7 +3285,7 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
+       update_halt_poll_stats(
+               vcpu, ktime_to_ns(ktime_sub(poll_end, start)), waited);
+-      if (!kvm_arch_no_poll(vcpu)) {
++      if (halt_poll_allowed) {
+               if (!vcpu_valid_wakeup(vcpu)) {
+                       shrink_halt_poll_ns(vcpu);
+               } else if (vcpu->kvm->max_halt_poll_ns) {
+-- 
+2.34.1
+
diff --git a/queue-5.15/kvm-vmx-don-t-unblock-vcpu-w-posted-irq-if-irqs-are-.patch b/queue-5.15/kvm-vmx-don-t-unblock-vcpu-w-posted-irq-if-irqs-are-.patch
new file mode 100644 (file)
index 0000000..84dae50
--- /dev/null
@@ -0,0 +1,40 @@
+From 0a713f4775326a1f14b9be05496678143e66f4e2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 Nov 2021 09:32:47 -0500
+Subject: KVM: VMX: Don't unblock vCPU w/ Posted IRQ if IRQs are disabled in
+ guest
+
+From: Paolo Bonzini <pbonzini@redhat.com>
+
+[ Upstream commit 1831fa44df743a7cdffdf1c12c799bf6f3c12b8c ]
+
+Don't configure the wakeup handler when a vCPU is blocking with IRQs
+disabled, in which case any IRQ, posted or otherwise, should not be
+recognized and thus should not wake the vCPU.
+
+Fixes: bf9f6ac8d749 ("KVM: Update Posted-Interrupts Descriptor when vCPU is blocked")
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Message-Id: <20211009021236.4122790-2-seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/vmx/posted_intr.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/arch/x86/kvm/vmx/posted_intr.c b/arch/x86/kvm/vmx/posted_intr.c
+index 21ea58d25771f..696ad48ab5daa 100644
+--- a/arch/x86/kvm/vmx/posted_intr.c
++++ b/arch/x86/kvm/vmx/posted_intr.c
+@@ -147,7 +147,8 @@ int pi_pre_block(struct kvm_vcpu *vcpu)
+       struct pi_desc old, new;
+       struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
+-      if (!vmx_can_use_vtd_pi(vcpu->kvm))
++      if (!vmx_can_use_vtd_pi(vcpu->kvm) ||
++          vmx_interrupt_blocked(vcpu))
+               return 0;
+       WARN_ON(irqs_disabled());
+-- 
+2.34.1
+
diff --git a/queue-5.15/kvm-vmx-read-posted-interrupt-control-exactly-once-p.patch b/queue-5.15/kvm-vmx-read-posted-interrupt-control-exactly-once-p.patch
new file mode 100644 (file)
index 0000000..b53e5b6
--- /dev/null
@@ -0,0 +1,58 @@
+From be48023e4c4ddce7d34258c248478878c3a60b11 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 Oct 2021 19:12:19 -0700
+Subject: KVM: VMX: Read Posted Interrupt "control" exactly once per loop
+ iteration
+
+From: Sean Christopherson <seanjc@google.com>
+
+[ Upstream commit cfb0e1306a3790eb055ebf7cdb7b0ee8a23e9b6e ]
+
+Use READ_ONCE() when loading the posted interrupt descriptor control
+field to ensure "old" and "new" have the same base value.  If the
+compiler emits separate loads, and loads into "new" before "old", KVM
+could theoretically drop the ON bit if it were set between the loads.
+
+Fixes: 28b835d60fcc ("KVM: Update Posted-Interrupts Descriptor when vCPU is preempted")
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Message-Id: <20211009021236.4122790-27-seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/vmx/posted_intr.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/arch/x86/kvm/vmx/posted_intr.c b/arch/x86/kvm/vmx/posted_intr.c
+index 696ad48ab5daa..46fb83d6a286e 100644
+--- a/arch/x86/kvm/vmx/posted_intr.c
++++ b/arch/x86/kvm/vmx/posted_intr.c
+@@ -51,7 +51,7 @@ void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)
+       /* The full case.  */
+       do {
+-              old.control = new.control = pi_desc->control;
++              old.control = new.control = READ_ONCE(pi_desc->control);
+               dest = cpu_physical_id(cpu);
+@@ -104,7 +104,7 @@ static void __pi_post_block(struct kvm_vcpu *vcpu)
+       unsigned int dest;
+       do {
+-              old.control = new.control = pi_desc->control;
++              old.control = new.control = READ_ONCE(pi_desc->control);
+               WARN(old.nv != POSTED_INTR_WAKEUP_VECTOR,
+                    "Wakeup handler not enabled while the VCPU is blocked\n");
+@@ -163,7 +163,7 @@ int pi_pre_block(struct kvm_vcpu *vcpu)
+       }
+       do {
+-              old.control = new.control = pi_desc->control;
++              old.control = new.control = READ_ONCE(pi_desc->control);
+               WARN((pi_desc->sn == 1),
+                    "Warning: SN field of posted-interrupts "
+-- 
+2.34.1
+
diff --git a/queue-5.15/kvm-x86-ensure-that-dirty-pdptrs-are-loaded.patch b/queue-5.15/kvm-x86-ensure-that-dirty-pdptrs-are-loaded.patch
new file mode 100644 (file)
index 0000000..8514166
--- /dev/null
@@ -0,0 +1,54 @@
+From 2c48cac2a6520e9ca3ef08d76cfcb8d7c8863375 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 Nov 2021 20:43:53 +0800
+Subject: KVM: X86: Ensure that dirty PDPTRs are loaded
+
+From: Lai Jiangshan <laijs@linux.alibaba.com>
+
+[ Upstream commit 2c5653caecc4807b8abfe9c41880ac38417be7bf ]
+
+For VMX with EPT, dirty PDPTRs need to be loaded before the next vmentry
+via vmx_load_mmu_pgd()
+
+But not all paths that call load_pdptrs() will cause vmx_load_mmu_pgd()
+to be invoked.  Normally, kvm_mmu_reset_context() is used to cause
+KVM_REQ_LOAD_MMU_PGD, but sometimes it is skipped:
+
+* commit d81135a57aa6("KVM: x86: do not reset mmu if CR0.CD and
+CR0.NW are changed") skips kvm_mmu_reset_context() after load_pdptrs()
+when changing CR0.CD and CR0.NW.
+
+* commit 21823fbda552("KVM: x86: Invalidate all PGDs for the current
+PCID on MOV CR3 w/ flush") skips KVM_REQ_LOAD_MMU_PGD after
+load_pdptrs() when rewriting the CR3 with the same value.
+
+* commit a91a7c709600("KVM: X86: Don't reset mmu context when
+toggling X86_CR4_PGE") skips kvm_mmu_reset_context() after
+load_pdptrs() when changing CR4.PGE.
+
+Fixes: d81135a57aa6 ("KVM: x86: do not reset mmu if CR0.CD and CR0.NW are changed")
+Fixes: 21823fbda552 ("KVM: x86: Invalidate all PGDs for the current PCID on MOV CR3 w/ flush")
+Fixes: a91a7c709600 ("KVM: X86: Don't reset mmu context when toggling X86_CR4_PGE")
+Signed-off-by: Lai Jiangshan <laijs@linux.alibaba.com>
+Message-Id: <20211108124407.12187-2-jiangshanlai@gmail.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/x86.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index 33cb065181248..33457b27e220b 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -848,6 +848,7 @@ int load_pdptrs(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, unsigned long cr3)
+       memcpy(mmu->pdptrs, pdpte, sizeof(mmu->pdptrs));
+       kvm_register_mark_dirty(vcpu, VCPU_EXREG_PDPTR);
++      kvm_make_request(KVM_REQ_LOAD_MMU_PGD, vcpu);
+       vcpu->arch.pdptrs_from_userspace = false;
+ out:
+-- 
+2.34.1
+
diff --git a/queue-5.15/kvm-x86-exit-to-userspace-if-emulation-prepared-a-co.patch b/queue-5.15/kvm-x86-exit-to-userspace-if-emulation-prepared-a-co.patch
new file mode 100644 (file)
index 0000000..0f1bc4a
--- /dev/null
@@ -0,0 +1,57 @@
+From 042d9bbd6ea21adc9a95e30b44b3e8cc98158dc3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Nov 2021 17:15:32 +0800
+Subject: KVM: x86: Exit to userspace if emulation prepared a completion
+ callback
+
+From: Hou Wenlong <houwenlong93@linux.alibaba.com>
+
+[ Upstream commit adbfb12d4c4517a8adde23a7fc46538953d56eea ]
+
+em_rdmsr() and em_wrmsr() return X86EMUL_IO_NEEDED if MSR accesses
+required an exit to userspace. However, x86_emulate_insn() doesn't return
+X86EMUL_*, so x86_emulate_instruction() doesn't directly act on
+X86EMUL_IO_NEEDED; instead, it looks for other signals to differentiate
+between PIO, MMIO, etc. causing RDMSR/WRMSR emulation not to
+exit to userspace now.
+
+Nevertheless, if the userspace_msr_exit_test testcase in selftests
+is changed to test RDMSR/WRMSR with a forced emulation prefix,
+the test passes.  What happens is that first userspace exit
+information is filled but the userspace exit does not happen.
+Because x86_emulate_instruction() returns 1, the guest retries
+the instruction---but this time RIP has already been adjusted
+past the forced emulation prefix, so the guest executes RDMSR/WRMSR
+and the userspace exit finally happens.
+
+Since the X86EMUL_IO_NEEDED path has provided a complete_userspace_io
+callback, x86_emulate_instruction() can just return 0 if the
+callback is not NULL. Then RDMSR/WRMSR instruction emulation will
+exit to userspace directly, without the RDMSR/WRMSR vmexit.
+
+Fixes: 1ae099540e8c7 ("KVM: x86: Allow deflecting unknown MSR accesses to user space")
+Signed-off-by: Hou Wenlong <houwenlong93@linux.alibaba.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Message-Id: <56f9df2ee5c05a81155e2be366c9dc1f7adc8817.1635842679.git.houwenlong93@linux.alibaba.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/x86.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index 6b76486702ded..8213f7fb71a7b 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -8068,6 +8068,9 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
+                       writeback = false;
+               r = 0;
+               vcpu->arch.complete_userspace_io = complete_emulated_mmio;
++      } else if (vcpu->arch.complete_userspace_io) {
++              writeback = false;
++              r = 0;
+       } else if (r == EMULATION_RESTART)
+               goto restart;
+       else
+-- 
+2.34.1
+
diff --git a/queue-5.15/kvm-x86-handle-32-bit-wrap-of-eip-for-emultype_skip-.patch b/queue-5.15/kvm-x86-handle-32-bit-wrap-of-eip-for-emultype_skip-.patch
new file mode 100644 (file)
index 0000000..a631339
--- /dev/null
@@ -0,0 +1,48 @@
+From ebdb52f41732c62c9316577c2fe2f010650cb804 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Nov 2021 17:15:29 +0800
+Subject: KVM: x86: Handle 32-bit wrap of EIP for EMULTYPE_SKIP with flat code
+ seg
+
+From: Sean Christopherson <seanjc@google.com>
+
+[ Upstream commit 5e854864ee4384736f27a986633bae21731a4e4e ]
+
+Truncate the new EIP to a 32-bit value when handling EMULTYPE_SKIP as the
+decode phase does not truncate _eip.  Wrapping the 32-bit boundary is
+legal if and only if CS is a flat code segment, but that check is
+implicitly handled in the form of limit checks in the decode phase.
+
+Opportunstically prepare for a future fix by storing the result of any
+truncation in "eip" instead of "_eip".
+
+Fixes: 1957aa63be53 ("KVM: VMX: Handle single-step #DB for EMULTYPE_SKIP on EPT misconfig")
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Message-Id: <093eabb1eab2965201c9b018373baf26ff256d85.1635842679.git.houwenlong93@linux.alibaba.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/x86.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index 33457b27e220b..6b76486702ded 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -7999,7 +7999,12 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
+        * updating interruptibility state and injecting single-step #DBs.
+        */
+       if (emulation_type & EMULTYPE_SKIP) {
+-              kvm_rip_write(vcpu, ctxt->_eip);
++              if (ctxt->mode != X86EMUL_MODE_PROT64)
++                      ctxt->eip = (u32)ctxt->_eip;
++              else
++                      ctxt->eip = ctxt->_eip;
++
++              kvm_rip_write(vcpu, ctxt->eip);
+               if (ctxt->eflags & X86_EFLAGS_RF)
+                       kvm_set_rflags(vcpu, ctxt->eflags & ~X86_EFLAGS_RF);
+               return 1;
+-- 
+2.34.1
+
diff --git a/queue-5.15/mips-fix-local_-add-sub-_return-on-mips64.patch b/queue-5.15/mips-fix-local_-add-sub-_return-on-mips64.patch
new file mode 100644 (file)
index 0000000..92716f7
--- /dev/null
@@ -0,0 +1,70 @@
+From 34c83f285509179a83cbe733f8efcfe7dfb41b9f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Dec 2021 16:44:57 +0800
+Subject: MIPS: fix local_{add,sub}_return on MIPS64
+
+From: Huang Pei <huangpei@loongson.cn>
+
+[ Upstream commit 277c8cb3e8ac199f075bf9576ad286687ed17173 ]
+
+Use "daddu/dsubu" for long int on MIPS64 instead of "addu/subu"
+
+Fixes: 7232311ef14c ("local_t: mips extension")
+Signed-off-by: Huang Pei <huangpei@loongson.cn>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/mips/include/asm/local.h | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/arch/mips/include/asm/local.h b/arch/mips/include/asm/local.h
+index ecda7295ddcd1..3fa6340903882 100644
+--- a/arch/mips/include/asm/local.h
++++ b/arch/mips/include/asm/local.h
+@@ -5,6 +5,7 @@
+ #include <linux/percpu.h>
+ #include <linux/bitops.h>
+ #include <linux/atomic.h>
++#include <asm/asm.h>
+ #include <asm/cmpxchg.h>
+ #include <asm/compiler.h>
+ #include <asm/war.h>
+@@ -39,7 +40,7 @@ static __inline__ long local_add_return(long i, local_t * l)
+               "       .set    arch=r4000                              \n"
+                       __SYNC(full, loongson3_war) "                   \n"
+               "1:"    __LL    "%1, %2         # local_add_return      \n"
+-              "       addu    %0, %1, %3                              \n"
++                      __stringify(LONG_ADDU)  "       %0, %1, %3      \n"
+                       __SC    "%0, %2                                 \n"
+               "       beqzl   %0, 1b                                  \n"
+               "       addu    %0, %1, %3                              \n"
+@@ -55,7 +56,7 @@ static __inline__ long local_add_return(long i, local_t * l)
+               "       .set    "MIPS_ISA_ARCH_LEVEL"                   \n"
+                       __SYNC(full, loongson3_war) "                   \n"
+               "1:"    __LL    "%1, %2         # local_add_return      \n"
+-              "       addu    %0, %1, %3                              \n"
++                      __stringify(LONG_ADDU)  "       %0, %1, %3      \n"
+                       __SC    "%0, %2                                 \n"
+               "       beqz    %0, 1b                                  \n"
+               "       addu    %0, %1, %3                              \n"
+@@ -88,7 +89,7 @@ static __inline__ long local_sub_return(long i, local_t * l)
+               "       .set    arch=r4000                              \n"
+                       __SYNC(full, loongson3_war) "                   \n"
+               "1:"    __LL    "%1, %2         # local_sub_return      \n"
+-              "       subu    %0, %1, %3                              \n"
++                      __stringify(LONG_SUBU)  "       %0, %1, %3      \n"
+                       __SC    "%0, %2                                 \n"
+               "       beqzl   %0, 1b                                  \n"
+               "       subu    %0, %1, %3                              \n"
+@@ -104,7 +105,7 @@ static __inline__ long local_sub_return(long i, local_t * l)
+               "       .set    "MIPS_ISA_ARCH_LEVEL"                   \n"
+                       __SYNC(full, loongson3_war) "                   \n"
+               "1:"    __LL    "%1, %2         # local_sub_return      \n"
+-              "       subu    %0, %1, %3                              \n"
++                      __stringify(LONG_SUBU)  "       %0, %1, %3      \n"
+                       __SC    "%0, %2                                 \n"
+               "       beqz    %0, 1b                                  \n"
+               "       subu    %0, %1, %3                              \n"
+-- 
+2.34.1
+
diff --git a/queue-5.15/mm-defer-kmemleak-object-creation-of-module_alloc.patch b/queue-5.15/mm-defer-kmemleak-object-creation-of-module_alloc.patch
new file mode 100644 (file)
index 0000000..6806680
--- /dev/null
@@ -0,0 +1,227 @@
+From 2298c87dd7c6976c6aebe29e0882140cd1fcd6c7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Jan 2022 14:04:11 -0800
+Subject: mm: defer kmemleak object creation of module_alloc()
+
+From: Kefeng Wang <wangkefeng.wang@huawei.com>
+
+[ Upstream commit 60115fa54ad7b913b7cb5844e6b7ffeb842d55f2 ]
+
+Yongqiang reports a kmemleak panic when module insmod/rmmod with KASAN
+enabled(without KASAN_VMALLOC) on x86[1].
+
+When the module area allocates memory, it's kmemleak_object is created
+successfully, but the KASAN shadow memory of module allocation is not
+ready, so when kmemleak scan the module's pointer, it will panic due to
+no shadow memory with KASAN check.
+
+  module_alloc
+    __vmalloc_node_range
+      kmemleak_vmalloc
+                               kmemleak_scan
+                                 update_checksum
+    kasan_module_alloc
+      kmemleak_ignore
+
+Note, there is no problem if KASAN_VMALLOC enabled, the modules area
+entire shadow memory is preallocated.  Thus, the bug only exits on ARCH
+which supports dynamic allocation of module area per module load, for
+now, only x86/arm64/s390 are involved.
+
+Add a VM_DEFER_KMEMLEAK flags, defer vmalloc'ed object register of
+kmemleak in module_alloc() to fix this issue.
+
+[1] https://lore.kernel.org/all/6d41e2b9-4692-5ec4-b1cd-cbe29ae89739@huawei.com/
+
+[wangkefeng.wang@huawei.com: fix build]
+  Link: https://lkml.kernel.org/r/20211125080307.27225-1-wangkefeng.wang@huawei.com
+[akpm@linux-foundation.org: simplify ifdefs, per Andrey]
+  Link: https://lkml.kernel.org/r/CA+fCnZcnwJHUQq34VuRxpdoY6_XbJCDJ-jopksS5Eia4PijPzw@mail.gmail.com
+
+Link: https://lkml.kernel.org/r/20211124142034.192078-1-wangkefeng.wang@huawei.com
+Fixes: 793213a82de4 ("s390/kasan: dynamic shadow mem allocation for modules")
+Fixes: 39d114ddc682 ("arm64: add KASAN support")
+Fixes: bebf56a1b176 ("kasan: enable instrumentation of global variables")
+Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
+Reported-by: Yongqiang Liu <liuyongqiang13@huawei.com>
+Cc: Andrey Konovalov <andreyknvl@gmail.com>
+Cc: Andrey Ryabinin <ryabinin.a.a@gmail.com>
+Cc: Dmitry Vyukov <dvyukov@google.com>
+Cc: Catalin Marinas <catalin.marinas@arm.com>
+Cc: Will Deacon <will@kernel.org>
+Cc: Heiko Carstens <hca@linux.ibm.com>
+Cc: Vasily Gorbik <gor@linux.ibm.com>
+Cc: Christian Borntraeger <borntraeger@linux.ibm.com>
+Cc: Alexander Gordeev <agordeev@linux.ibm.com>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Borislav Petkov <bp@alien8.de>
+Cc: Dave Hansen <dave.hansen@linux.intel.com>
+Cc: Alexander Potapenko <glider@google.com>
+Cc: Kefeng Wang <wangkefeng.wang@huawei.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/kernel/module.c | 4 ++--
+ arch/s390/kernel/module.c  | 5 +++--
+ arch/x86/kernel/module.c   | 7 ++++---
+ include/linux/kasan.h      | 4 ++--
+ include/linux/vmalloc.h    | 7 +++++++
+ mm/kasan/shadow.c          | 9 +++++++--
+ mm/vmalloc.c               | 3 ++-
+ 7 files changed, 27 insertions(+), 12 deletions(-)
+
+diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c
+index b5ec010c481f3..309a27553c875 100644
+--- a/arch/arm64/kernel/module.c
++++ b/arch/arm64/kernel/module.c
+@@ -36,7 +36,7 @@ void *module_alloc(unsigned long size)
+               module_alloc_end = MODULES_END;
+       p = __vmalloc_node_range(size, MODULE_ALIGN, module_alloc_base,
+-                              module_alloc_end, gfp_mask, PAGE_KERNEL, 0,
++                              module_alloc_end, gfp_mask, PAGE_KERNEL, VM_DEFER_KMEMLEAK,
+                               NUMA_NO_NODE, __builtin_return_address(0));
+       if (!p && IS_ENABLED(CONFIG_ARM64_MODULE_PLTS) &&
+@@ -58,7 +58,7 @@ void *module_alloc(unsigned long size)
+                               PAGE_KERNEL, 0, NUMA_NO_NODE,
+                               __builtin_return_address(0));
+-      if (p && (kasan_module_alloc(p, size) < 0)) {
++      if (p && (kasan_module_alloc(p, size, gfp_mask) < 0)) {
+               vfree(p);
+               return NULL;
+       }
+diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c
+index a805ea5cb92d1..b032e556eeb71 100644
+--- a/arch/s390/kernel/module.c
++++ b/arch/s390/kernel/module.c
+@@ -37,14 +37,15 @@
+ void *module_alloc(unsigned long size)
+ {
++      gfp_t gfp_mask = GFP_KERNEL;
+       void *p;
+       if (PAGE_ALIGN(size) > MODULES_LEN)
+               return NULL;
+       p = __vmalloc_node_range(size, MODULE_ALIGN, MODULES_VADDR, MODULES_END,
+-                               GFP_KERNEL, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,
++                               gfp_mask, PAGE_KERNEL_EXEC, VM_DEFER_KMEMLEAK, NUMA_NO_NODE,
+                                __builtin_return_address(0));
+-      if (p && (kasan_module_alloc(p, size) < 0)) {
++      if (p && (kasan_module_alloc(p, size, gfp_mask) < 0)) {
+               vfree(p);
+               return NULL;
+       }
+diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c
+index 5e9a34b5bd741..867a341a0c7e8 100644
+--- a/arch/x86/kernel/module.c
++++ b/arch/x86/kernel/module.c
+@@ -67,6 +67,7 @@ static unsigned long int get_module_load_offset(void)
+ void *module_alloc(unsigned long size)
+ {
++      gfp_t gfp_mask = GFP_KERNEL;
+       void *p;
+       if (PAGE_ALIGN(size) > MODULES_LEN)
+@@ -74,10 +75,10 @@ void *module_alloc(unsigned long size)
+       p = __vmalloc_node_range(size, MODULE_ALIGN,
+                                   MODULES_VADDR + get_module_load_offset(),
+-                                  MODULES_END, GFP_KERNEL,
+-                                  PAGE_KERNEL, 0, NUMA_NO_NODE,
++                                  MODULES_END, gfp_mask,
++                                  PAGE_KERNEL, VM_DEFER_KMEMLEAK, NUMA_NO_NODE,
+                                   __builtin_return_address(0));
+-      if (p && (kasan_module_alloc(p, size) < 0)) {
++      if (p && (kasan_module_alloc(p, size, gfp_mask) < 0)) {
+               vfree(p);
+               return NULL;
+       }
+diff --git a/include/linux/kasan.h b/include/linux/kasan.h
+index dd874a1ee862a..f407e937241af 100644
+--- a/include/linux/kasan.h
++++ b/include/linux/kasan.h
+@@ -461,12 +461,12 @@ static inline void kasan_release_vmalloc(unsigned long start,
+  * allocations with real shadow memory. With KASAN vmalloc, the special
+  * case is unnecessary, as the work is handled in the generic case.
+  */
+-int kasan_module_alloc(void *addr, size_t size);
++int kasan_module_alloc(void *addr, size_t size, gfp_t gfp_mask);
+ void kasan_free_shadow(const struct vm_struct *vm);
+ #else /* (CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS) && !CONFIG_KASAN_VMALLOC */
+-static inline int kasan_module_alloc(void *addr, size_t size) { return 0; }
++static inline int kasan_module_alloc(void *addr, size_t size, gfp_t gfp_mask) { return 0; }
+ static inline void kasan_free_shadow(const struct vm_struct *vm) {}
+ #endif /* (CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS) && !CONFIG_KASAN_VMALLOC */
+diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
+index 671d402c3778f..4fe9e885bbfac 100644
+--- a/include/linux/vmalloc.h
++++ b/include/linux/vmalloc.h
+@@ -28,6 +28,13 @@ struct notifier_block;              /* in notifier.h */
+ #define VM_MAP_PUT_PAGES      0x00000200      /* put pages and free array in vfree */
+ #define VM_NO_HUGE_VMAP               0x00000400      /* force PAGE_SIZE pte mapping */
++#if (defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS)) && \
++      !defined(CONFIG_KASAN_VMALLOC)
++#define VM_DEFER_KMEMLEAK     0x00000800      /* defer kmemleak object creation */
++#else
++#define VM_DEFER_KMEMLEAK     0
++#endif
++
+ /*
+  * VM_KASAN is used slightly differently depending on CONFIG_KASAN_VMALLOC.
+  *
+diff --git a/mm/kasan/shadow.c b/mm/kasan/shadow.c
+index 8d95ee52d0194..dd79840e60964 100644
+--- a/mm/kasan/shadow.c
++++ b/mm/kasan/shadow.c
+@@ -493,7 +493,7 @@ void kasan_release_vmalloc(unsigned long start, unsigned long end,
+ #else /* CONFIG_KASAN_VMALLOC */
+-int kasan_module_alloc(void *addr, size_t size)
++int kasan_module_alloc(void *addr, size_t size, gfp_t gfp_mask)
+ {
+       void *ret;
+       size_t scaled_size;
+@@ -515,9 +515,14 @@ int kasan_module_alloc(void *addr, size_t size)
+                       __builtin_return_address(0));
+       if (ret) {
++              struct vm_struct *vm = find_vm_area(addr);
+               __memset(ret, KASAN_SHADOW_INIT, shadow_size);
+-              find_vm_area(addr)->flags |= VM_KASAN;
++              vm->flags |= VM_KASAN;
+               kmemleak_ignore(ret);
++
++              if (vm->flags & VM_DEFER_KMEMLEAK)
++                      kmemleak_vmalloc(vm, size, gfp_mask);
++
+               return 0;
+       }
+diff --git a/mm/vmalloc.c b/mm/vmalloc.c
+index e8a807c781107..8375eecc55de5 100644
+--- a/mm/vmalloc.c
++++ b/mm/vmalloc.c
+@@ -3032,7 +3032,8 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align,
+       clear_vm_uninitialized_flag(area);
+       size = PAGE_ALIGN(size);
+-      kmemleak_vmalloc(area, size, gfp_mask);
++      if (!(vm_flags & VM_DEFER_KMEMLEAK))
++              kmemleak_vmalloc(area, size, gfp_mask);
+       return addr;
+-- 
+2.34.1
+
diff --git a/queue-5.15/mtd-spi-nor-fix-mtd-size-for-s3an-flashes.patch b/queue-5.15/mtd-spi-nor-fix-mtd-size-for-s3an-flashes.patch
new file mode 100644 (file)
index 0000000..a590384
--- /dev/null
@@ -0,0 +1,44 @@
+From 46dec7cabf3efe3fb6946e4a3f681f8d7d8f67c9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Dec 2021 16:02:41 +0200
+Subject: mtd: spi-nor: Fix mtd size for s3an flashes
+
+From: Tudor Ambarus <tudor.ambarus@microchip.com>
+
+[ Upstream commit f656b419d41aabafb6b526abc3988dfbf2e5c1ba ]
+
+As it was before the blamed commit, s3an_nor_scan() was called
+after mtd size was set with params->size, and it overwrote the mtd
+size value with '8 * nor->page_size * nor->info->n_sectors' when
+XSR_PAGESIZE was set. With the introduction of
+s3an_post_sfdp_fixups(), we missed to update the mtd size for the
+s3an flashes. Fix the mtd size by updating both nor->params->size,
+(which will update the mtd_info size later on) and nor->mtd.size
+(which is used in spi_nor_set_addr_width()).
+
+Fixes: 641edddb4f43 ("mtd: spi-nor: Add s3an_post_sfdp_fixups()")
+Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
+Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
+Link: https://lore.kernel.org/r/20211207140254.87681-2-tudor.ambarus@microchip.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mtd/spi-nor/xilinx.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mtd/spi-nor/xilinx.c b/drivers/mtd/spi-nor/xilinx.c
+index 1138bdbf41998..75dd13a390404 100644
+--- a/drivers/mtd/spi-nor/xilinx.c
++++ b/drivers/mtd/spi-nor/xilinx.c
+@@ -66,7 +66,8 @@ static int xilinx_nor_setup(struct spi_nor *nor,
+               /* Flash in Power of 2 mode */
+               nor->page_size = (nor->page_size == 264) ? 256 : 512;
+               nor->mtd.writebufsize = nor->page_size;
+-              nor->mtd.size = 8 * nor->page_size * nor->info->n_sectors;
++              nor->params->size = 8 * nor->page_size * nor->info->n_sectors;
++              nor->mtd.size = nor->params->size;
+               nor->mtd.erasesize = 8 * nor->page_size;
+       } else {
+               /* Flash in Default addressing mode */
+-- 
+2.34.1
+
diff --git a/queue-5.15/net-dsa-ocelot-seville-utilize-of_mdiobus_register.patch b/queue-5.15/net-dsa-ocelot-seville-utilize-of_mdiobus_register.patch
new file mode 100644 (file)
index 0000000..3f85203
--- /dev/null
@@ -0,0 +1,47 @@
+From b27e27a718f1ee8af83ae3de7ba533411e8c03d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 28 Nov 2021 17:57:36 -0800
+Subject: net: dsa: ocelot: seville: utilize of_mdiobus_register
+
+From: Colin Foster <colin.foster@in-advantage.com>
+
+[ Upstream commit 5186c4a05b9713138b762a49467a8ab9753cdb36 ]
+
+Switch seville to use of_mdiobus_register(bus, NULL) instead of just
+mdiobus_register. This code is about to be pulled into a separate module
+that can optionally define ports by the device_node.
+
+Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Tested-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/ocelot/seville_vsc9953.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c
+index de1d34a1f1e47..ca8c003b99bc5 100644
+--- a/drivers/net/dsa/ocelot/seville_vsc9953.c
++++ b/drivers/net/dsa/ocelot/seville_vsc9953.c
+@@ -10,6 +10,7 @@
+ #include <linux/pcs-lynx.h>
+ #include <linux/dsa/ocelot.h>
+ #include <linux/iopoll.h>
++#include <linux/of_mdio.h>
+ #include "felix.h"
+ #define MSCC_MIIM_CMD_OPR_WRITE                       BIT(1)
+@@ -1110,7 +1111,7 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot)
+       snprintf(bus->id, MII_BUS_ID_SIZE, "%s-imdio", dev_name(dev));
+       /* Needed in order to initialize the bus mutex lock */
+-      rc = mdiobus_register(bus);
++      rc = of_mdiobus_register(bus, NULL);
+       if (rc < 0) {
+               dev_err(dev, "failed to register MDIO bus\n");
+               return rc;
+-- 
+2.34.1
+
diff --git a/queue-5.15/net-dsa-seville-register-the-mdiobus-under-devres.patch b/queue-5.15/net-dsa-seville-register-the-mdiobus-under-devres.patch
new file mode 100644 (file)
index 0000000..bd1a446
--- /dev/null
@@ -0,0 +1,75 @@
+From 2e8b1dea4d89b51d8a7b247c961a4f8ecf40c208 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 7 Feb 2022 18:15:51 +0200
+Subject: net: dsa: seville: register the mdiobus under devres
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ Upstream commit bd488afc3b39e045ba71aab472233f2a78726e7b ]
+
+As explained in commits:
+74b6d7d13307 ("net: dsa: realtek: register the MDIO bus under devres")
+5135e96a3dd2 ("net: dsa: don't allocate the slave_mii_bus using devres")
+
+mdiobus_free() will panic when called from devm_mdiobus_free() <-
+devres_release_all() <- __device_release_driver(), and that mdiobus was
+not previously unregistered.
+
+The Seville VSC9959 switch is a platform device, so the initial set of
+constraints that I thought would cause this (I2C or SPI buses which call
+->remove on ->shutdown) do not apply. But there is one more which
+applies here.
+
+If the DSA master itself is on a bus that calls ->remove from ->shutdown
+(like dpaa2-eth, which is on the fsl-mc bus), there is a device link
+between the switch and the DSA master, and device_links_unbind_consumers()
+will unbind the seville switch driver on shutdown.
+
+So the same treatment must be applied to all DSA switch drivers, which
+is: either use devres for both the mdiobus allocation and registration,
+or don't use devres at all.
+
+The seville driver has a code structure that could accommodate both the
+mdiobus_unregister and mdiobus_free calls, but it has an external
+dependency upon mscc_miim_setup() from mdio-mscc-miim.c, which calls
+devm_mdiobus_alloc_size() on its behalf. So rather than restructuring
+that, and exporting yet one more symbol mscc_miim_teardown(), let's work
+with devres and replace of_mdiobus_register with the devres variant.
+When we use all-devres, we can ensure that devres doesn't free a
+still-registered bus (it either runs both callbacks, or none).
+
+Fixes: ac3a68d56651 ("net: phy: don't abuse devres in devm_mdiobus_register()")
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/ocelot/seville_vsc9953.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c
+index ca8c003b99bc5..05e4e75c01076 100644
+--- a/drivers/net/dsa/ocelot/seville_vsc9953.c
++++ b/drivers/net/dsa/ocelot/seville_vsc9953.c
+@@ -1111,7 +1111,7 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot)
+       snprintf(bus->id, MII_BUS_ID_SIZE, "%s-imdio", dev_name(dev));
+       /* Needed in order to initialize the bus mutex lock */
+-      rc = of_mdiobus_register(bus, NULL);
++      rc = devm_of_mdiobus_register(dev, bus, NULL);
+       if (rc < 0) {
+               dev_err(dev, "failed to register MDIO bus\n");
+               return rc;
+@@ -1163,7 +1163,8 @@ static void vsc9953_mdio_bus_free(struct ocelot *ocelot)
+               mdio_device_free(pcs->mdio);
+               lynx_pcs_destroy(pcs);
+       }
+-      mdiobus_unregister(felix->imdio);
++
++      /* mdiobus_unregister and mdiobus_free handled by devres */
+ }
+ static const struct felix_info seville_info_vsc9953 = {
+-- 
+2.34.1
+
diff --git a/queue-5.15/net-ethernet-litex-add-the-dependency-on-has_iomem.patch b/queue-5.15/net-ethernet-litex-add-the-dependency-on-has_iomem.patch
new file mode 100644 (file)
index 0000000..aeeeabd
--- /dev/null
@@ -0,0 +1,37 @@
+From c4d8f3ed87d905c6f0edfbff545a3e3177f3c4b7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 8 Feb 2022 09:33:08 +0800
+Subject: net: ethernet: litex: Add the dependency on HAS_IOMEM
+
+From: Cai Huoqing <cai.huoqing@linux.dev>
+
+[ Upstream commit 2427f03fb42f9dc14c53108f2c9b5563eb37e770 ]
+
+The LiteX driver uses devm io function API which
+needs HAS_IOMEM enabled, so add the dependency on HAS_IOMEM.
+
+Fixes: ee7da21ac4c3 ("net: Add driver for LiteX's LiteETH network interface")
+Signed-off-by: Cai Huoqing <cai.huoqing@linux.dev>
+Link: https://lore.kernel.org/r/20220208013308.6563-1-cai.huoqing@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/litex/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/litex/Kconfig b/drivers/net/ethernet/litex/Kconfig
+index f99adbf26ab4e..04345b929d8e5 100644
+--- a/drivers/net/ethernet/litex/Kconfig
++++ b/drivers/net/ethernet/litex/Kconfig
+@@ -17,7 +17,7 @@ if NET_VENDOR_LITEX
+ config LITEX_LITEETH
+       tristate "LiteX Ethernet support"
+-      depends on OF
++      depends on OF && HAS_IOMEM
+       help
+         If you wish to compile a kernel for hardware with a LiteX LiteEth
+         device then you should answer Y to this.
+-- 
+2.34.1
+
diff --git a/queue-5.15/net-mlx5e-ipsec-fix-crypto-offload-for-non-tcp-udp-e.patch b/queue-5.15/net-mlx5e-ipsec-fix-crypto-offload-for-non-tcp-udp-e.patch
new file mode 100644 (file)
index 0000000..416725b
--- /dev/null
@@ -0,0 +1,57 @@
+From 5b90a11281bfa3d7b8ab251e79b9bd7ae0f89647 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 2 Dec 2021 17:43:50 +0200
+Subject: net/mlx5e: IPsec: Fix crypto offload for non TCP/UDP encapsulated
+ traffic
+
+From: Raed Salem <raeds@nvidia.com>
+
+[ Upstream commit 5352859b3bfa0ca188b2f1d2c1436fddc781e3b6 ]
+
+IPsec crypto offload always set the ethernet segment checksum flags with
+the inner L4 header checksum flag enabled for encapsulated IPsec offloaded
+packet regardless of the encapsulated L4 header type, and even if it
+doesn't exists in the first place, this breaks non TCP/UDP traffic as
+such.
+
+Set the inner L4 checksum flag only when the encapsulated L4 header
+protocol is TCP/UDP using software parser swp_inner_l4_offset field as
+indication.
+
+Fixes: 5cfb540ef27b ("net/mlx5e: Set IPsec WAs only in IP's non checksum partial case.")
+Signed-off-by: Raed Salem <raeds@nvidia.com>
+Reviewed-by: Maor Dickman <maord@nvidia.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h    | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h
+index b98db50c3418d..428881e0adcbe 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h
+@@ -131,14 +131,17 @@ static inline bool
+ mlx5e_ipsec_txwqe_build_eseg_csum(struct mlx5e_txqsq *sq, struct sk_buff *skb,
+                                 struct mlx5_wqe_eth_seg *eseg)
+ {
+-      struct xfrm_offload *xo = xfrm_offload(skb);
++      u8 inner_ipproto;
+       if (!mlx5e_ipsec_eseg_meta(eseg))
+               return false;
+       eseg->cs_flags = MLX5_ETH_WQE_L3_CSUM;
+-      if (xo->inner_ipproto) {
+-              eseg->cs_flags |= MLX5_ETH_WQE_L4_INNER_CSUM | MLX5_ETH_WQE_L3_INNER_CSUM;
++      inner_ipproto = xfrm_offload(skb)->inner_ipproto;
++      if (inner_ipproto) {
++              eseg->cs_flags |= MLX5_ETH_WQE_L3_INNER_CSUM;
++              if (inner_ipproto == IPPROTO_TCP || inner_ipproto == IPPROTO_UDP)
++                      eseg->cs_flags |= MLX5_ETH_WQE_L4_INNER_CSUM;
+       } else if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+               eseg->cs_flags |= MLX5_ETH_WQE_L4_CSUM;
+               sq->stats->csum_partial_inner++;
+-- 
+2.34.1
+
diff --git a/queue-5.15/net-mlx5e-ipsec-refactor-checksum-code-in-tx-data-pa.patch b/queue-5.15/net-mlx5e-ipsec-refactor-checksum-code-in-tx-data-pa.patch
new file mode 100644 (file)
index 0000000..57a3c5c
--- /dev/null
@@ -0,0 +1,118 @@
+From 2b302cc6f13d47f69df948b4307c2090490f6488 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Oct 2021 10:10:42 +0300
+Subject: net/mlx5e: IPsec: Refactor checksum code in tx data path
+
+From: Raed Salem <raeds@nvidia.com>
+
+[ Upstream commit 428ffea0711a11efa0c1c4ee1fac27903ed091be ]
+
+Part of code that is related solely to IPsec is always compiled in the
+driver code regardless if the IPsec functionality is enabled or disabled
+in the driver code, this will add unnecessary branch in case IPsec is
+disabled at Tx data path.
+
+Move IPsec related code to IPsec related file such that in case of IPsec
+is disabled and because of unlikely macro the compiler should be able to
+optimize and omit the checksum IPsec code all together from Tx data path
+
+Signed-off-by: Raed Salem <raeds@nvidia.com>
+Reviewed-by: Emeel Hakim <ehakim@nvidia.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../mellanox/mlx5/core/en_accel/ipsec_rxtx.h  | 26 +++++++++++++++++++
+ .../net/ethernet/mellanox/mlx5/core/en_tx.c   | 20 ++------------
+ 2 files changed, 28 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h
+index 5120a59361e6a..b98db50c3418d 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h
+@@ -127,6 +127,25 @@ mlx5e_ipsec_feature_check(struct sk_buff *skb, netdev_features_t features)
+       return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+ }
++static inline bool
++mlx5e_ipsec_txwqe_build_eseg_csum(struct mlx5e_txqsq *sq, struct sk_buff *skb,
++                                struct mlx5_wqe_eth_seg *eseg)
++{
++      struct xfrm_offload *xo = xfrm_offload(skb);
++
++      if (!mlx5e_ipsec_eseg_meta(eseg))
++              return false;
++
++      eseg->cs_flags = MLX5_ETH_WQE_L3_CSUM;
++      if (xo->inner_ipproto) {
++              eseg->cs_flags |= MLX5_ETH_WQE_L4_INNER_CSUM | MLX5_ETH_WQE_L3_INNER_CSUM;
++      } else if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
++              eseg->cs_flags |= MLX5_ETH_WQE_L4_CSUM;
++              sq->stats->csum_partial_inner++;
++      }
++
++      return true;
++}
+ #else
+ static inline
+ void mlx5e_ipsec_offload_handle_rx_skb(struct net_device *netdev,
+@@ -143,6 +162,13 @@ static inline bool mlx5_ipsec_is_rx_flow(struct mlx5_cqe64 *cqe) { return false;
+ static inline netdev_features_t
+ mlx5e_ipsec_feature_check(struct sk_buff *skb, netdev_features_t features)
+ { return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK); }
++
++static inline bool
++mlx5e_ipsec_txwqe_build_eseg_csum(struct mlx5e_txqsq *sq, struct sk_buff *skb,
++                                struct mlx5_wqe_eth_seg *eseg)
++{
++      return false;
++}
+ #endif /* CONFIG_MLX5_EN_IPSEC */
+ #endif /* __MLX5E_IPSEC_RXTX_H__ */
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
+index 188994d091c54..7fd33b356cc8d 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
+@@ -38,6 +38,7 @@
+ #include "en/txrx.h"
+ #include "ipoib/ipoib.h"
+ #include "en_accel/en_accel.h"
++#include "en_accel/ipsec_rxtx.h"
+ #include "en/ptp.h"
+ static void mlx5e_dma_unmap_wqe_err(struct mlx5e_txqsq *sq, u8 num_dma)
+@@ -213,30 +214,13 @@ static inline void mlx5e_insert_vlan(void *start, struct sk_buff *skb, u16 ihs)
+       memcpy(&vhdr->h_vlan_encapsulated_proto, skb->data + cpy1_sz, cpy2_sz);
+ }
+-static void
+-ipsec_txwqe_build_eseg_csum(struct mlx5e_txqsq *sq, struct sk_buff *skb,
+-                          struct mlx5_wqe_eth_seg *eseg)
+-{
+-      struct xfrm_offload *xo = xfrm_offload(skb);
+-
+-      eseg->cs_flags = MLX5_ETH_WQE_L3_CSUM;
+-      if (xo->inner_ipproto) {
+-              eseg->cs_flags |= MLX5_ETH_WQE_L4_INNER_CSUM | MLX5_ETH_WQE_L3_INNER_CSUM;
+-      } else if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+-              eseg->cs_flags |= MLX5_ETH_WQE_L4_CSUM;
+-              sq->stats->csum_partial_inner++;
+-      }
+-}
+-
+ static inline void
+ mlx5e_txwqe_build_eseg_csum(struct mlx5e_txqsq *sq, struct sk_buff *skb,
+                           struct mlx5e_accel_tx_state *accel,
+                           struct mlx5_wqe_eth_seg *eseg)
+ {
+-      if (unlikely(mlx5e_ipsec_eseg_meta(eseg))) {
+-              ipsec_txwqe_build_eseg_csum(sq, skb, eseg);
++      if (unlikely(mlx5e_ipsec_txwqe_build_eseg_csum(sq, skb, eseg)))
+               return;
+-      }
+       if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+               eseg->cs_flags = MLX5_ETH_WQE_L3_CSUM;
+-- 
+2.34.1
+
diff --git a/queue-5.15/nfsd-fix-crash-on-copy_notify-with-special-stateid.patch b/queue-5.15/nfsd-fix-crash-on-copy_notify-with-special-stateid.patch
new file mode 100644 (file)
index 0000000..a409d57
--- /dev/null
@@ -0,0 +1,56 @@
+From c9edbc86b86b26810b16abc0332a574dce6de312 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Jan 2022 14:15:03 -0500
+Subject: nfsd: fix crash on COPY_NOTIFY with special stateid
+
+From: J. Bruce Fields <bfields@redhat.com>
+
+[ Upstream commit 074b07d94e0bb6ddce5690a9b7e2373088e8b33a ]
+
+RTM says "If the special ONE stateid is passed to
+nfs4_preprocess_stateid_op(), it returns status=0 but does not set
+*cstid. nfsd4_copy_notify() depends on stid being set if status=0, and
+thus can crash if the client sends the right COPY_NOTIFY RPC."
+
+RFC 7862 says "The cna_src_stateid MUST refer to either open or locking
+states provided earlier by the server.  If it is invalid, then the
+operation MUST fail."
+
+The RFC doesn't specify an error, and the choice doesn't matter much as
+this is clearly illegal client behavior, but bad_stateid seems
+reasonable.
+
+Simplest is just to guarantee that nfs4_preprocess_stateid_op, called
+with non-NULL cstid, errors out if it can't return a stateid.
+
+Reported-by: rtm@csail.mit.edu
+Fixes: 624322f1adc5 ("NFSD add COPY_NOTIFY operation")
+Signed-off-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Olga Kornievskaia <kolga@netapp.com>
+Tested-by: Olga Kornievskaia <kolga@netapp.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfsd/nfs4state.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 97090ddcfc94d..db4a47a280dc5 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -6042,7 +6042,11 @@ nfs4_preprocess_stateid_op(struct svc_rqst *rqstp,
+               *nfp = NULL;
+       if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) {
+-              status = check_special_stateids(net, fhp, stateid, flags);
++              if (cstid)
++                      status = nfserr_bad_stateid;
++              else
++                      status = check_special_stateids(net, fhp, stateid,
++                                                                      flags);
+               goto done;
+       }
+-- 
+2.34.1
+
diff --git a/queue-5.15/nfsd-fix-verifier-returned-in-stable-writes.patch b/queue-5.15/nfsd-fix-verifier-returned-in-stable-writes.patch
new file mode 100644 (file)
index 0000000..732b87c
--- /dev/null
@@ -0,0 +1,69 @@
+From e4700c4330981a66826104f936ac7368f61898d6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Dec 2021 12:35:43 -0500
+Subject: NFSD: Fix verifier returned in stable WRITEs
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit f11ad7aa653130b71e2e89bed207f387718216d5 ]
+
+RFC 8881 explains the purpose of the write verifier this way:
+
+> The final portion of the result is the field writeverf. This field
+> is the write verifier and is a cookie that the client can use to
+> determine whether a server has changed instance state (e.g., server
+> restart) between a call to WRITE and a subsequent call to either
+> WRITE or COMMIT.
+
+But then it says:
+
+> This cookie MUST be unchanged during a single instance of the
+> NFSv4.1 server and MUST be unique between instances of the NFSv4.1
+> server. If the cookie changes, then the client MUST assume that
+> any data written with an UNSTABLE4 value for committed and an old
+> writeverf in the reply has been lost and will need to be
+> recovered.
+
+RFC 1813 has similar language for NFSv3. NFSv2 does not have a write
+verifier since it doesn't implement the COMMIT procedure.
+
+Since commit 19e0663ff9bc ("nfsd: Ensure sampling of the write
+verifier is atomic with the write"), the Linux NFS server has
+returned a boot-time-based verifier for UNSTABLE WRITEs, but a zero
+verifier for FILE_SYNC and DATA_SYNC WRITEs. FILE_SYNC and DATA_SYNC
+WRITEs are not followed up with a COMMIT, so there's no need for
+clients to compare verifiers for stable writes.
+
+However, by returning a different verifier for stable and unstable
+writes, the above commit puts the Linux NFS server a step farther
+out of compliance with the first MUST above. At least one NFS client
+(FreeBSD) noticed the difference, making this a potential
+regression.
+
+Reported-by: Rick Macklem <rmacklem@uoguelph.ca>
+Link: https://lore.kernel.org/linux-nfs/YQXPR0101MB096857EEACF04A6DF1FC6D9BDD749@YQXPR0101MB0968.CANPRD01.PROD.OUTLOOK.COM/T/
+Fixes: 19e0663ff9bc ("nfsd: Ensure sampling of the write verifier is atomic with the write")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfsd/vfs.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index 78df038434124..271f7c15d6e52 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -993,6 +993,10 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf,
+       iov_iter_kvec(&iter, WRITE, vec, vlen, *cnt);
+       if (flags & RWF_SYNC) {
+               down_write(&nf->nf_rwsem);
++              if (verf)
++                      nfsd_copy_boot_verifier(verf,
++                                      net_generic(SVC_NET(rqstp),
++                                      nfsd_net_id));
+               host_err = vfs_iter_write(file, &iter, &pos, flags);
+               if (host_err < 0)
+                       nfsd_reset_boot_verifier(net_generic(SVC_NET(rqstp),
+-- 
+2.34.1
+
diff --git a/queue-5.15/nfsd-fix-zero-length-nfsv3-writes.patch b/queue-5.15/nfsd-fix-zero-length-nfsv3-writes.patch
new file mode 100644 (file)
index 0000000..e67c3d8
--- /dev/null
@@ -0,0 +1,92 @@
+From 217ab66c79495e3b60a1ef939857bda96f77ccff Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Dec 2021 11:52:06 -0500
+Subject: NFSD: Fix zero-length NFSv3 WRITEs
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 6a2f774424bfdcc2df3e17de0cefe74a4269cad5 ]
+
+The Linux NFS server currently responds to a zero-length NFSv3 WRITE
+request with NFS3ERR_IO. It responds to a zero-length NFSv4 WRITE
+with NFS4_OK and count of zero.
+
+RFC 1813 says of the WRITE procedure's @count argument:
+
+count
+         The number of bytes of data to be written. If count is
+         0, the WRITE will succeed and return a count of 0,
+         barring errors due to permissions checking.
+
+RFC 8881 has similar language for NFSv4, though NFSv4 removed the
+explicit @count argument because that value is already contained in
+the opaque payload array.
+
+The synthetic client pynfs's WRT4 and WRT15 tests do emit zero-
+length WRITEs to exercise this spec requirement. Commit fdec6114ee1f
+("nfsd4: zero-length WRITE should succeed") addressed the same
+problem there with the same fix.
+
+But interestingly the Linux NFS client does not appear to emit zero-
+length WRITEs, instead squelching them. I'm not aware of a test that
+can generate such WRITEs for NFSv3, so I wrote a naive C program to
+generate a zero-length WRITE and test this fix.
+
+Fixes: 8154ef2776aa ("NFSD: Clean up legacy NFS WRITE argument XDR decoders")
+Reported-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfsd/nfs3proc.c | 6 +-----
+ fs/nfsd/nfsproc.c  | 5 -----
+ 2 files changed, 1 insertion(+), 10 deletions(-)
+
+diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
+index 354bbfcd96aae..b540489ea240d 100644
+--- a/fs/nfsd/nfs3proc.c
++++ b/fs/nfsd/nfs3proc.c
+@@ -211,15 +211,11 @@ nfsd3_proc_write(struct svc_rqst *rqstp)
+       fh_copy(&resp->fh, &argp->fh);
+       resp->committed = argp->stable;
+       nvecs = svc_fill_write_vector(rqstp, &argp->payload);
+-      if (!nvecs) {
+-              resp->status = nfserr_io;
+-              goto out;
+-      }
++
+       resp->status = nfsd_write(rqstp, &resp->fh, argp->offset,
+                                 rqstp->rq_vec, nvecs, &cnt,
+                                 resp->committed, resp->verf);
+       resp->count = cnt;
+-out:
+       return rpc_success;
+ }
+diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
+index de282f3273c50..312fd289be583 100644
+--- a/fs/nfsd/nfsproc.c
++++ b/fs/nfsd/nfsproc.c
+@@ -235,10 +235,6 @@ nfsd_proc_write(struct svc_rqst *rqstp)
+               argp->len, argp->offset);
+       nvecs = svc_fill_write_vector(rqstp, &argp->payload);
+-      if (!nvecs) {
+-              resp->status = nfserr_io;
+-              goto out;
+-      }
+       resp->status = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),
+                                 argp->offset, rqstp->rq_vec, nvecs,
+@@ -247,7 +243,6 @@ nfsd_proc_write(struct svc_rqst *rqstp)
+               resp->status = fh_getattr(&resp->fh, &resp->stat);
+       else if (resp->status == nfserr_jukebox)
+               return rpc_drop_reply;
+-out:
+       return rpc_success;
+ }
+-- 
+2.34.1
+
diff --git a/queue-5.15/nfsd-have-legacy-nfsd-write-decoders-use-xdr_stream_.patch b/queue-5.15/nfsd-have-legacy-nfsd-write-decoders-use-xdr_stream_.patch
new file mode 100644 (file)
index 0000000..b310395
--- /dev/null
@@ -0,0 +1,212 @@
+From dc7b1a3ad7b6952acdba2dd9adea2c26f3193146 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Sep 2021 17:06:21 -0400
+Subject: NFSD: Have legacy NFSD WRITE decoders use xdr_stream_subsegment()
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit dae9a6cab8009e526570e7477ce858dcdfeb256e ]
+
+Refactor.
+
+Now that the NFSv2 and NFSv3 XDR decoders have been converted to
+use xdr_streams, the WRITE decoder functions can use
+xdr_stream_subsegment() to extract the WRITE payload into its own
+xdr_buf, just as the NFSv4 WRITE XDR decoder currently does.
+
+That makes it possible to pass the first kvec, pages array + length,
+page_base, and total payload length via a single function parameter.
+
+The payload's page_base is not yet assigned or used, but will be in
+subsequent patches.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfsd/nfs3proc.c         |  3 +--
+ fs/nfsd/nfs3xdr.c          | 12 ++----------
+ fs/nfsd/nfs4proc.c         |  3 +--
+ fs/nfsd/nfsproc.c          |  3 +--
+ fs/nfsd/nfsxdr.c           |  9 +--------
+ fs/nfsd/xdr.h              |  2 +-
+ fs/nfsd/xdr3.h             |  2 +-
+ include/linux/sunrpc/svc.h |  3 +--
+ net/sunrpc/svc.c           | 11 ++++++-----
+ 9 files changed, 15 insertions(+), 33 deletions(-)
+
+diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
+index 9918d6ad23ec9..354bbfcd96aae 100644
+--- a/fs/nfsd/nfs3proc.c
++++ b/fs/nfsd/nfs3proc.c
+@@ -210,8 +210,7 @@ nfsd3_proc_write(struct svc_rqst *rqstp)
+       fh_copy(&resp->fh, &argp->fh);
+       resp->committed = argp->stable;
+-      nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages,
+-                                    &argp->first, cnt);
++      nvecs = svc_fill_write_vector(rqstp, &argp->payload);
+       if (!nvecs) {
+               resp->status = nfserr_io;
+               goto out;
+diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
+index 7a900131d20ca..0ee156b9c9d71 100644
+--- a/fs/nfsd/nfs3xdr.c
++++ b/fs/nfsd/nfs3xdr.c
+@@ -621,9 +621,6 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p)
+       struct xdr_stream *xdr = &rqstp->rq_arg_stream;
+       struct nfsd3_writeargs *args = rqstp->rq_argp;
+       u32 max_blocksize = svc_max_payload(rqstp);
+-      struct kvec *head = rqstp->rq_arg.head;
+-      struct kvec *tail = rqstp->rq_arg.tail;
+-      size_t remaining;
+       if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
+               return 0;
+@@ -641,17 +638,12 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p)
+       /* request sanity */
+       if (args->count != args->len)
+               return 0;
+-      remaining = head->iov_len + rqstp->rq_arg.page_len + tail->iov_len;
+-      remaining -= xdr_stream_pos(xdr);
+-      if (remaining < xdr_align_size(args->len))
+-              return 0;
+       if (args->count > max_blocksize) {
+               args->count = max_blocksize;
+               args->len = max_blocksize;
+       }
+-
+-      args->first.iov_base = xdr->p;
+-      args->first.iov_len = head->iov_len - xdr_stream_pos(xdr);
++      if (!xdr_stream_subsegment(xdr, &args->payload, args->count))
++              return 0;
+       return 1;
+ }
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index 4b9a3b90a41ff..65200910107f3 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -1038,8 +1038,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+       write->wr_how_written = write->wr_stable_how;
+-      nvecs = svc_fill_write_vector(rqstp, write->wr_payload.pages,
+-                                    write->wr_payload.head, write->wr_buflen);
++      nvecs = svc_fill_write_vector(rqstp, &write->wr_payload);
+       WARN_ON_ONCE(nvecs > ARRAY_SIZE(rqstp->rq_vec));
+       status = nfsd_vfs_write(rqstp, &cstate->current_fh, nf,
+diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
+index 19c568b8a527f..de282f3273c50 100644
+--- a/fs/nfsd/nfsproc.c
++++ b/fs/nfsd/nfsproc.c
+@@ -234,8 +234,7 @@ nfsd_proc_write(struct svc_rqst *rqstp)
+               SVCFH_fmt(&argp->fh),
+               argp->len, argp->offset);
+-      nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages,
+-                                    &argp->first, cnt);
++      nvecs = svc_fill_write_vector(rqstp, &argp->payload);
+       if (!nvecs) {
+               resp->status = nfserr_io;
+               goto out;
+diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
+index a06c05fe3b421..26a42f87c2409 100644
+--- a/fs/nfsd/nfsxdr.c
++++ b/fs/nfsd/nfsxdr.c
+@@ -325,10 +325,7 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p)
+ {
+       struct xdr_stream *xdr = &rqstp->rq_arg_stream;
+       struct nfsd_writeargs *args = rqstp->rq_argp;
+-      struct kvec *head = rqstp->rq_arg.head;
+-      struct kvec *tail = rqstp->rq_arg.tail;
+       u32 beginoffset, totalcount;
+-      size_t remaining;
+       if (!svcxdr_decode_fhandle(xdr, &args->fh))
+               return 0;
+@@ -346,12 +343,8 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p)
+               return 0;
+       if (args->len > NFSSVC_MAXBLKSIZE_V2)
+               return 0;
+-      remaining = head->iov_len + rqstp->rq_arg.page_len + tail->iov_len;
+-      remaining -= xdr_stream_pos(xdr);
+-      if (remaining < xdr_align_size(args->len))
++      if (!xdr_stream_subsegment(xdr, &args->payload, args->len))
+               return 0;
+-      args->first.iov_base = xdr->p;
+-      args->first.iov_len = head->iov_len - xdr_stream_pos(xdr);
+       return 1;
+ }
+diff --git a/fs/nfsd/xdr.h b/fs/nfsd/xdr.h
+index f45b4bc93f527..80fd6d7f3404a 100644
+--- a/fs/nfsd/xdr.h
++++ b/fs/nfsd/xdr.h
+@@ -33,7 +33,7 @@ struct nfsd_writeargs {
+       svc_fh                  fh;
+       __u32                   offset;
+       int                     len;
+-      struct kvec             first;
++      struct xdr_buf          payload;
+ };
+ struct nfsd_createargs {
+diff --git a/fs/nfsd/xdr3.h b/fs/nfsd/xdr3.h
+index 933008382bbeb..712c117300cb7 100644
+--- a/fs/nfsd/xdr3.h
++++ b/fs/nfsd/xdr3.h
+@@ -40,7 +40,7 @@ struct nfsd3_writeargs {
+       __u32                   count;
+       int                     stable;
+       __u32                   len;
+-      struct kvec             first;
++      struct xdr_buf          payload;
+ };
+ struct nfsd3_createargs {
+diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
+index 064c96157d1f0..6263410c948a0 100644
+--- a/include/linux/sunrpc/svc.h
++++ b/include/linux/sunrpc/svc.h
+@@ -532,8 +532,7 @@ int                   svc_encode_result_payload(struct svc_rqst *rqstp,
+                                            unsigned int offset,
+                                            unsigned int length);
+ unsigned int     svc_fill_write_vector(struct svc_rqst *rqstp,
+-                                       struct page **pages,
+-                                       struct kvec *first, size_t total);
++                                       struct xdr_buf *payload);
+ char            *svc_fill_symlink_pathname(struct svc_rqst *rqstp,
+                                            struct kvec *first, void *p,
+                                            size_t total);
+diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
+index a3bbe5ce4570f..08ca797bb8a46 100644
+--- a/net/sunrpc/svc.c
++++ b/net/sunrpc/svc.c
+@@ -1676,16 +1676,17 @@ EXPORT_SYMBOL_GPL(svc_encode_result_payload);
+ /**
+  * svc_fill_write_vector - Construct data argument for VFS write call
+  * @rqstp: svc_rqst to operate on
+- * @pages: list of pages containing data payload
+- * @first: buffer containing first section of write payload
+- * @total: total number of bytes of write payload
++ * @payload: xdr_buf containing only the write data payload
+  *
+  * Fills in rqstp::rq_vec, and returns the number of elements.
+  */
+-unsigned int svc_fill_write_vector(struct svc_rqst *rqstp, struct page **pages,
+-                                 struct kvec *first, size_t total)
++unsigned int svc_fill_write_vector(struct svc_rqst *rqstp,
++                                 struct xdr_buf *payload)
+ {
++      struct page **pages = payload->pages;
++      struct kvec *first = payload->head;
+       struct kvec *vec = rqstp->rq_vec;
++      size_t total = payload->len;
+       unsigned int i;
+       /* Some types of transport can present the write payload
+-- 
+2.34.1
+
diff --git a/queue-5.15/ntb_hw_switchtec-fix-bug-with-more-than-32-partition.patch b/queue-5.15/ntb_hw_switchtec-fix-bug-with-more-than-32-partition.patch
new file mode 100644 (file)
index 0000000..66b757e
--- /dev/null
@@ -0,0 +1,74 @@
+From a6e7adb217b0624700bca3962e0b45743c8e17dc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Dec 2021 17:23:30 -0800
+Subject: ntb_hw_switchtec: Fix bug with more than 32 partitions
+
+From: Wesley Sheng <wesley.sheng@microchip.com>
+
+[ Upstream commit 7ff351c86b6b258f387502ab2c9b9d04f82c1c3d ]
+
+Switchtec could support as mush as 48 partitions, but ffs & fls are
+for 32 bit argument, in case of partition index larger than 31, the
+current code could not parse the peer partition index correctly.
+Change to the 64 bit version __ffs64 & fls64 accordingly to fix this
+bug.
+
+Fixes: 3df54c870f52 ("ntb_hw_switchtec: Allow using Switchtec NTB in multi-partition setups")
+Signed-off-by: Wesley Sheng <wesley.sheng@microchip.com>
+Signed-off-by: Kelvin Cao <kelvin.cao@microchip.com>
+Signed-off-by: Jon Mason <jdmason@kudzu.us>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
+index 6603c77c0a848..ec9cb6c81edae 100644
+--- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
++++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
+@@ -840,7 +840,6 @@ static int switchtec_ntb_init_sndev(struct switchtec_ntb *sndev)
+       u64 tpart_vec;
+       int self;
+       u64 part_map;
+-      int bit;
+       sndev->ntb.pdev = sndev->stdev->pdev;
+       sndev->ntb.topo = NTB_TOPO_SWITCH;
+@@ -861,29 +860,28 @@ static int switchtec_ntb_init_sndev(struct switchtec_ntb *sndev)
+       part_map = ioread64(&sndev->mmio_ntb->ep_map);
+       part_map &= ~(1 << sndev->self_partition);
+-      if (!ffs(tpart_vec)) {
++      if (!tpart_vec) {
+               if (sndev->stdev->partition_count != 2) {
+                       dev_err(&sndev->stdev->dev,
+                               "ntb target partition not defined\n");
+                       return -ENODEV;
+               }
+-              bit = ffs(part_map);
+-              if (!bit) {
++              if (!part_map) {
+                       dev_err(&sndev->stdev->dev,
+                               "peer partition is not NT partition\n");
+                       return -ENODEV;
+               }
+-              sndev->peer_partition = bit - 1;
++              sndev->peer_partition = __ffs64(part_map);
+       } else {
+-              if (ffs(tpart_vec) != fls(tpart_vec)) {
++              if (__ffs64(tpart_vec) != (fls64(tpart_vec) - 1)) {
+                       dev_err(&sndev->stdev->dev,
+                               "ntb driver only supports 1 pair of 1-1 ntb mapping\n");
+                       return -ENODEV;
+               }
+-              sndev->peer_partition = ffs(tpart_vec) - 1;
++              sndev->peer_partition = __ffs64(tpart_vec);
+               if (!(part_map & (1ULL << sndev->peer_partition))) {
+                       dev_err(&sndev->stdev->dev,
+                               "ntb target partition is not NT partition\n");
+-- 
+2.34.1
+
diff --git a/queue-5.15/ntb_hw_switchtec-fix-pff-ioread-to-read-into-mmio_pa.patch b/queue-5.15/ntb_hw_switchtec-fix-pff-ioread-to-read-into-mmio_pa.patch
new file mode 100644 (file)
index 0000000..b31d3e4
--- /dev/null
@@ -0,0 +1,40 @@
+From 729fa8b2f7446f9fa327907cfc8370cf84de3d14 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Dec 2021 17:23:29 -0800
+Subject: ntb_hw_switchtec: Fix pff ioread to read into mmio_part_cfg_all
+
+From: Jeremy Pallotta <jmpallotta@gmail.com>
+
+[ Upstream commit 32c3d375b0ed84b6acb51ae5ebef35ff0d649d85 ]
+
+Array mmio_part_cfg_all holds the partition configuration of all
+partitions, with partition number as index. Fix this by reading into
+mmio_part_cfg_all for pff.
+
+Fixes: 0ee28f26f378 ("NTB: switchtec_ntb: Add link management")
+Signed-off-by: Jeremy Pallotta <jmpallotta@gmail.com>
+Signed-off-by: Kelvin Cao <kelvin.cao@microchip.com>
+Signed-off-by: Jon Mason <jdmason@kudzu.us>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ntb/hw/mscc/ntb_hw_switchtec.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
+index 4c6eb61a6ac62..6603c77c0a848 100644
+--- a/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
++++ b/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
+@@ -419,8 +419,8 @@ static void switchtec_ntb_part_link_speed(struct switchtec_ntb *sndev,
+                                         enum ntb_width *width)
+ {
+       struct switchtec_dev *stdev = sndev->stdev;
+-
+-      u32 pff = ioread32(&stdev->mmio_part_cfg[partition].vep_pff_inst_id);
++      u32 pff =
++              ioread32(&stdev->mmio_part_cfg_all[partition].vep_pff_inst_id);
+       u32 linksta = ioread32(&stdev->mmio_pff_csr[pff].pci_cap_region[13]);
+       if (speed)
+-- 
+2.34.1
+
diff --git a/queue-5.15/octeontx2-af-add-kpu-changes-to-parse-ngio-as-separa.patch b/queue-5.15/octeontx2-af-add-kpu-changes-to-parse-ngio-as-separa.patch
new file mode 100644 (file)
index 0000000..c2dfe48
--- /dev/null
@@ -0,0 +1,171 @@
+From ba5e9541fb588ac033a951338d64451681708dee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Jan 2022 12:04:47 +0530
+Subject: octeontx2-af: Add KPU changes to parse NGIO as separate layer
+
+From: Kiran Kumar K <kirankumark@marvell.com>
+
+[ Upstream commit 745166fcf01cecc4f5ff3defc6586868349a43f9 ]
+
+With current KPU profile NGIO is being parsed along with CTAG as
+a single layer. Because of this MCAM/ntuple rules installed with
+ethertype as 0x8842 are not being hit. Adding KPU profile changes
+to parse NGIO in separate ltype and CTAG in separate ltype.
+
+Fixes: f9c49be90c05 ("octeontx2-af: Update the default KPU profile and fixes")
+Signed-off-by: Kiran Kumar K <kirankumark@marvell.com>
+Signed-off-by: Subbaraya Sundeep <sbhatta@marvell.com>
+Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../marvell/octeontx2/af/npc_profile.h        | 70 +++++++++----------
+ 1 file changed, 35 insertions(+), 35 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h b/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h
+index fad5ecda4e647..695123e32ba85 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h
+@@ -186,7 +186,6 @@ enum npc_kpu_parser_state {
+       NPC_S_KPU2_ETAG,
+       NPC_S_KPU2_PREHEADER,
+       NPC_S_KPU2_EXDSA,
+-      NPC_S_KPU2_NGIO,
+       NPC_S_KPU2_CPT_CTAG,
+       NPC_S_KPU2_CPT_QINQ,
+       NPC_S_KPU3_CTAG,
+@@ -213,6 +212,7 @@ enum npc_kpu_parser_state {
+       NPC_S_KPU5_NSH,
+       NPC_S_KPU5_CPT_IP,
+       NPC_S_KPU5_CPT_IP6,
++      NPC_S_KPU5_NGIO,
+       NPC_S_KPU6_IP6_EXT,
+       NPC_S_KPU6_IP6_HOP_DEST,
+       NPC_S_KPU6_IP6_ROUT,
+@@ -1117,15 +1117,6 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = {
+               0x0000,
+               0x0000,
+       },
+-      {
+-              NPC_S_KPU1_ETHER, 0xff,
+-              NPC_ETYPE_CTAG,
+-              0xffff,
+-              NPC_ETYPE_NGIO,
+-              0xffff,
+-              0x0000,
+-              0x0000,
+-      },
+       {
+               NPC_S_KPU1_ETHER, 0xff,
+               NPC_ETYPE_CTAG,
+@@ -1986,6 +1977,15 @@ static struct npc_kpu_profile_cam kpu2_cam_entries[] = {
+               0x0000,
+               0x0000,
+       },
++      {
++              NPC_S_KPU2_CTAG, 0xff,
++              NPC_ETYPE_NGIO,
++              0xffff,
++              0x0000,
++              0x0000,
++              0x0000,
++              0x0000,
++      },
+       {
+               NPC_S_KPU2_CTAG, 0xff,
+               NPC_ETYPE_PPPOE,
+@@ -2877,15 +2877,6 @@ static struct npc_kpu_profile_cam kpu2_cam_entries[] = {
+               0x0000,
+               0x0000,
+       },
+-      {
+-              NPC_S_KPU2_NGIO, 0xff,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-      },
+       {
+               NPC_S_KPU2_CPT_CTAG, 0xff,
+               NPC_ETYPE_IP,
+@@ -5205,6 +5196,15 @@ static struct npc_kpu_profile_cam kpu5_cam_entries[] = {
+               0x0000,
+               0x0000,
+       },
++      {
++              NPC_S_KPU5_NGIO, 0xff,
++              0x0000,
++              0x0000,
++              0x0000,
++              0x0000,
++              0x0000,
++              0x0000,
++      },
+       {
+               NPC_S_NA, 0X00,
+               0x0000,
+@@ -8499,14 +8499,6 @@ static struct npc_kpu_profile_action kpu1_action_entries[] = {
+               0,
+               0, 0, 0, 0,
+       },
+-      {
+-              NPC_ERRLEV_RE, NPC_EC_NOERR,
+-              8, 12, 0, 0, 0,
+-              NPC_S_KPU2_NGIO, 12, 1,
+-              NPC_LID_LA, NPC_LT_LA_ETHER,
+-              0,
+-              0, 0, 0, 0,
+-      },
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+               8, 12, 0, 0, 0,
+@@ -9291,6 +9283,14 @@ static struct npc_kpu_profile_action kpu2_action_entries[] = {
+               0,
+               0, 0, 0, 0,
+       },
++      {
++              NPC_ERRLEV_RE, NPC_EC_NOERR,
++              0, 0, 0, 2, 0,
++              NPC_S_KPU5_NGIO, 6, 1,
++              NPC_LID_LB, NPC_LT_LB_CTAG,
++              0,
++              0, 0, 0, 0,
++      },
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+               8, 0, 6, 2, 0,
+@@ -10083,14 +10083,6 @@ static struct npc_kpu_profile_action kpu2_action_entries[] = {
+               NPC_F_LB_U_UNK_ETYPE | NPC_F_LB_L_EXDSA,
+               0, 0, 0, 0,
+       },
+-      {
+-              NPC_ERRLEV_RE, NPC_EC_NOERR,
+-              0, 0, 0, 0, 1,
+-              NPC_S_NA, 0, 1,
+-              NPC_LID_LC, NPC_LT_LC_NGIO,
+-              0,
+-              0, 0, 0, 0,
+-      },
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+               8, 0, 6, 2, 0,
+@@ -12154,6 +12146,14 @@ static struct npc_kpu_profile_action kpu5_action_entries[] = {
+               0,
+               0, 0, 0, 0,
+       },
++      {
++              NPC_ERRLEV_RE, NPC_EC_NOERR,
++              0, 0, 0, 0, 1,
++              NPC_S_NA, 0, 1,
++              NPC_LID_LC, NPC_LT_LC_NGIO,
++              0,
++              0, 0, 0, 0,
++      },
+       {
+               NPC_ERRLEV_LC, NPC_EC_UNK,
+               0, 0, 0, 0, 1,
+-- 
+2.34.1
+
diff --git a/queue-5.15/octeontx2-af-adjust-la-pointer-for-cpt-parse-header.patch b/queue-5.15/octeontx2-af-adjust-la-pointer-for-cpt-parse-header.patch
new file mode 100644 (file)
index 0000000..5c04bd2
--- /dev/null
@@ -0,0 +1,317 @@
+From d756699201a8172c8b2e5f178933d61be7695883 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Sep 2021 11:28:31 +0530
+Subject: octeontx2-af: Adjust LA pointer for cpt parse header
+
+From: Kiran Kumar K <kirankumark@marvell.com>
+
+[ Upstream commit 85212a127e469c5560daf63a9782755ee4b03619 ]
+
+In case of ltype NPC_LT_LA_CPT_HDR, LA pointer is pointing to the
+start of cpt parse header. Since cpt parse header has veriable
+length padding, this will be a problem for DMAC extraction. Adding
+KPU profile changes to adjust the LA pointer to start at ether header
+in case of cpt parse header by
+   - Adding ptr advance in pkind 58 to a fixed value 40
+   - Adding variable length offset 7 and mask 7 (pad len in
+     CPT_PARSE_HDR).
+Also added the missing static declaration for npc_set_var_len_offset_pkind
+function.
+
+Signed-off-by: Kiran Kumar K <kirankumark@marvell.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../marvell/octeontx2/af/npc_profile.h        | 173 ++++++++----------
+ .../ethernet/marvell/octeontx2/af/rvu_npc.c   |   2 +-
+ 2 files changed, 80 insertions(+), 95 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h b/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h
+index 2b7030886daec..fad5ecda4e647 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h
+@@ -187,6 +187,8 @@ enum npc_kpu_parser_state {
+       NPC_S_KPU2_PREHEADER,
+       NPC_S_KPU2_EXDSA,
+       NPC_S_KPU2_NGIO,
++      NPC_S_KPU2_CPT_CTAG,
++      NPC_S_KPU2_CPT_QINQ,
+       NPC_S_KPU3_CTAG,
+       NPC_S_KPU3_STAG,
+       NPC_S_KPU3_QINQ,
+@@ -1004,11 +1006,11 @@ static struct npc_kpu_profile_action ikpu_action_entries[] = {
+       },
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+-              40, 54, 58, 0, 0,
+-              NPC_S_KPU1_CPT_HDR, 0, 0,
++              12, 16, 20, 0, 0,
++              NPC_S_KPU1_CPT_HDR, 40, 0,
+               NPC_LID_LA, NPC_LT_NA,
+               0,
+-              0, 0, 0, 0,
++              7, 7, 0, 0,
+       },
+       {
+@@ -1846,80 +1848,35 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = {
+       },
+       {
+               NPC_S_KPU1_CPT_HDR, 0xff,
+-              0x0000,
+-              0xffff,
+               NPC_ETYPE_IP,
+               0xffff,
+               0x0000,
+               0x0000,
+-      },
+-      {
+-              NPC_S_KPU1_CPT_HDR, 0xff,
+-              0x0000,
+-              0xffff,
+-              NPC_ETYPE_IP6,
+-              0xffff,
+               0x0000,
+               0x0000,
+       },
+       {
+               NPC_S_KPU1_CPT_HDR, 0xff,
+-              0x0000,
+-              0xffff,
+-              NPC_ETYPE_CTAG,
+-              0xffff,
+-              0x0000,
+-              0x0000,
+-      },
+-      {
+-              NPC_S_KPU1_CPT_HDR, 0xff,
+-              0x0000,
+-              0xffff,
+-              NPC_ETYPE_QINQ,
++              NPC_ETYPE_IP6,
+               0xffff,
+               0x0000,
+               0x0000,
+-      },
+-      {
+-              NPC_S_KPU1_CPT_HDR, 0xff,
+-              0x0000,
+-              0xffff,
+               0x0000,
+               0x0000,
+-              NPC_ETYPE_IP,
+-              0xffff,
+       },
+       {
+               NPC_S_KPU1_CPT_HDR, 0xff,
+-              0x0000,
++              NPC_ETYPE_CTAG,
+               0xffff,
+               0x0000,
+               0x0000,
+-              NPC_ETYPE_IP6,
+-              0xffff,
+-      },
+-      {
+-              NPC_S_KPU1_CPT_HDR, 0xff,
+-              0x0000,
+-              0xffff,
+               0x0000,
+               0x0000,
+-              NPC_ETYPE_CTAG,
+-              0xffff,
+       },
+       {
+               NPC_S_KPU1_CPT_HDR, 0xff,
+-              0x0000,
+-              0xffff,
+-              0x0000,
+-              0x0000,
+               NPC_ETYPE_QINQ,
+               0xffff,
+-      },
+-      {
+-              NPC_S_KPU1_CPT_HDR, 0xff,
+-              0x0000,
+-              0x0000,
+               0x0000,
+               0x0000,
+               0x0000,
+@@ -2929,6 +2886,42 @@ static struct npc_kpu_profile_cam kpu2_cam_entries[] = {
+               0x0000,
+               0x0000,
+       },
++      {
++              NPC_S_KPU2_CPT_CTAG, 0xff,
++              NPC_ETYPE_IP,
++              0xffff,
++              0x0000,
++              0x0000,
++              0x0000,
++              0x0000,
++      },
++      {
++              NPC_S_KPU2_CPT_CTAG, 0xff,
++              NPC_ETYPE_IP6,
++              0xffff,
++              0x0000,
++              0x0000,
++              0x0000,
++              0x0000,
++      },
++      {
++              NPC_S_KPU2_CPT_QINQ, 0xff,
++              NPC_ETYPE_CTAG,
++              0xffff,
++              NPC_ETYPE_IP,
++              0xffff,
++              0x0000,
++              0x0000,
++      },
++      {
++              NPC_S_KPU2_CPT_QINQ, 0xff,
++              NPC_ETYPE_CTAG,
++              0xffff,
++              NPC_ETYPE_IP6,
++              0xffff,
++              0x0000,
++              0x0000,
++      },
+       {
+               NPC_S_NA, 0X00,
+               0x0000,
+@@ -9176,39 +9169,7 @@ static struct npc_kpu_profile_action kpu1_action_entries[] = {
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+               8, 0, 6, 3, 0,
+-              NPC_S_KPU5_CPT_IP, 56, 1,
+-              NPC_LID_LA, NPC_LT_LA_CPT_HDR,
+-              0,
+-              0, 0, 0, 0,
+-      },
+-      {
+-              NPC_ERRLEV_RE, NPC_EC_NOERR,
+-              6, 0, 0, 3, 0,
+-              NPC_S_KPU5_CPT_IP6, 56, 1,
+-              NPC_LID_LA, NPC_LT_LA_CPT_HDR,
+-              0,
+-              0, 0, 0, 0,
+-      },
+-      {
+-              NPC_ERRLEV_RE, NPC_EC_NOERR,
+-              4, 8, 0, 0, 0,
+-              NPC_S_KPU2_CTAG, 54, 1,
+-              NPC_LID_LA, NPC_LT_LA_CPT_HDR,
+-              NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_VLAN,
+-              0, 0, 0, 0,
+-      },
+-      {
+-              NPC_ERRLEV_RE, NPC_EC_NOERR,
+-              4, 8, 0, 0, 0,
+-              NPC_S_KPU2_QINQ, 54, 1,
+-              NPC_LID_LA, NPC_LT_LA_CPT_HDR,
+-              NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_VLAN,
+-              0, 0, 0, 0,
+-      },
+-      {
+-              NPC_ERRLEV_RE, NPC_EC_NOERR,
+-              8, 0, 6, 3, 0,
+-              NPC_S_KPU5_CPT_IP, 60, 1,
++              NPC_S_KPU5_CPT_IP, 14, 1,
+               NPC_LID_LA, NPC_LT_LA_CPT_HDR,
+               0,
+               0, 0, 0, 0,
+@@ -9216,7 +9177,7 @@ static struct npc_kpu_profile_action kpu1_action_entries[] = {
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+               6, 0, 0, 3, 0,
+-              NPC_S_KPU5_CPT_IP6, 60, 1,
++              NPC_S_KPU5_CPT_IP6, 14, 1,
+               NPC_LID_LA, NPC_LT_LA_CPT_HDR,
+               0,
+               0, 0, 0, 0,
+@@ -9224,7 +9185,7 @@ static struct npc_kpu_profile_action kpu1_action_entries[] = {
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+               4, 8, 0, 0, 0,
+-              NPC_S_KPU2_CTAG, 58, 1,
++              NPC_S_KPU2_CPT_CTAG, 12, 1,
+               NPC_LID_LA, NPC_LT_LA_CPT_HDR,
+               NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_VLAN,
+               0, 0, 0, 0,
+@@ -9232,19 +9193,11 @@ static struct npc_kpu_profile_action kpu1_action_entries[] = {
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+               4, 8, 0, 0, 0,
+-              NPC_S_KPU2_QINQ, 58, 1,
++              NPC_S_KPU2_CPT_QINQ, 12, 1,
+               NPC_LID_LA, NPC_LT_LA_CPT_HDR,
+               NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_VLAN,
+               0, 0, 0, 0,
+       },
+-      {
+-              NPC_ERRLEV_RE, NPC_EC_NOERR,
+-              0, 0, 0, 0, 1,
+-              NPC_S_NA, 0, 1,
+-              NPC_LID_LA, NPC_LT_LA_CPT_HDR,
+-              NPC_F_LA_L_UNK_ETYPE,
+-              0, 0, 0, 0,
+-      },
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+               12, 0, 0, 1, 0,
+@@ -10138,6 +10091,38 @@ static struct npc_kpu_profile_action kpu2_action_entries[] = {
+               0,
+               0, 0, 0, 0,
+       },
++      {
++              NPC_ERRLEV_RE, NPC_EC_NOERR,
++              8, 0, 6, 2, 0,
++              NPC_S_KPU5_CPT_IP, 6, 1,
++              NPC_LID_LB, NPC_LT_LB_CTAG,
++              0,
++              0, 0, 0, 0,
++      },
++      {
++              NPC_ERRLEV_RE, NPC_EC_NOERR,
++              6, 0, 0, 2, 0,
++              NPC_S_KPU5_CPT_IP6, 6, 1,
++              NPC_LID_LB, NPC_LT_LB_CTAG,
++              0,
++              0, 0, 0, 0,
++      },
++      {
++              NPC_ERRLEV_RE, NPC_EC_NOERR,
++              8, 0, 6, 2, 0,
++              NPC_S_KPU5_CPT_IP, 10, 1,
++              NPC_LID_LB, NPC_LT_LB_STAG_QINQ,
++              NPC_F_LB_U_MORE_TAG | NPC_F_LB_L_WITH_CTAG,
++              0, 0, 0, 0,
++      },
++      {
++              NPC_ERRLEV_RE, NPC_EC_NOERR,
++              6, 0, 0, 2, 0,
++              NPC_S_KPU5_CPT_IP6, 10, 1,
++              NPC_LID_LB, NPC_LT_LB_STAG_QINQ,
++              NPC_F_LB_U_MORE_TAG | NPC_F_LB_L_WITH_CTAG,
++              0, 0, 0, 0,
++      },
+       {
+               NPC_ERRLEV_LB, NPC_EC_L2_K3,
+               0, 0, 0, 0, 1,
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+index 2f347e937f00a..fbb573c40c1ac 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+@@ -3183,7 +3183,7 @@ int rvu_mbox_handler_npc_get_kex_cfg(struct rvu *rvu, struct msg_req *req,
+       return 0;
+ }
+-int
++static int
+ npc_set_var_len_offset_pkind(struct rvu *rvu, u16 pcifunc, u64 pkind,
+                            u8 var_len_off, u8 var_len_off_mask, u8 shift_dir)
+ {
+-- 
+2.34.1
+
diff --git a/queue-5.15/octeontx2-af-cn10k-rpm-hardware-timestamp-configurat.patch b/queue-5.15/octeontx2-af-cn10k-rpm-hardware-timestamp-configurat.patch
new file mode 100644 (file)
index 0000000..8c637bd
--- /dev/null
@@ -0,0 +1,244 @@
+From c65f283a5c54f53f01323f05361f034ed33c6450 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Sep 2021 17:00:59 +0530
+Subject: octeontx2-af: cn10k: RPM hardware timestamp configuration
+
+From: Hariprasad Kelam <hkelam@marvell.com>
+
+[ Upstream commit d1489208681dfe432609fdaa49b160219c6e221c ]
+
+MAC on CN10K support hardware timestamping such that 8 bytes addition
+header is prepended to incoming packets. This patch does necessary
+configuration to enable Hardware time stamping upon receiving request
+from PF netdev interfaces.
+
+Timestamp configuration is different on MAC (CGX) Octeontx2 silicon
+and MAC (RPM) OcteonTX3 CN10k. Based on silicon variant appropriate
+fn() pointer is called. Refactor MAC specific mbox messages to remove
+unnecessary gaps in mboxids.
+
+Signed-off-by: Hariprasad Kelam <hkelam@marvell.com>
+Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/marvell/octeontx2/af/cgx.c   | 10 ++---
+ .../marvell/octeontx2/af/lmac_common.h        |  5 +++
+ .../net/ethernet/marvell/octeontx2/af/mbox.h  | 41 ++++++++++---------
+ .../net/ethernet/marvell/octeontx2/af/rpm.c   | 17 ++++++++
+ .../net/ethernet/marvell/octeontx2/af/rpm.h   |  3 ++
+ .../ethernet/marvell/octeontx2/af/rvu_cgx.c   |  4 +-
+ .../ethernet/marvell/octeontx2/af/rvu_nix.c   |  4 +-
+ 7 files changed, 58 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
+index 34a089b71e554..d379a35c4618f 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
+@@ -838,9 +838,6 @@ void cgx_lmac_ptp_config(void *cgxd, int lmac_id, bool enable)
+       if (!cgx)
+               return;
+-      if (is_dev_rpm(cgx))
+-              return;
+-
+       if (enable) {
+               /* Enable inbound PTP timestamping */
+               cfg = cgx_read(cgx, lmac_id, CGXX_GMP_GMI_RXX_FRM_CTL);
+@@ -1545,9 +1542,11 @@ static int cgx_lmac_exit(struct cgx *cgx)
+ static void cgx_populate_features(struct cgx *cgx)
+ {
+       if (is_dev_rpm(cgx))
+-              cgx->hw_features =  (RVU_MAC_RPM | RVU_LMAC_FEAT_FC);
++              cgx->hw_features = (RVU_LMAC_FEAT_DMACF | RVU_MAC_RPM |
++                                  RVU_LMAC_FEAT_FC | RVU_LMAC_FEAT_PTP);
+       else
+-              cgx->hw_features = (RVU_LMAC_FEAT_FC | RVU_LMAC_FEAT_PTP);
++              cgx->hw_features = (RVU_LMAC_FEAT_FC  | RVU_LMAC_FEAT_HIGIG2 |
++                                  RVU_LMAC_FEAT_PTP | RVU_LMAC_FEAT_DMACF);
+ }
+ static struct mac_ops cgx_mac_ops    = {
+@@ -1571,6 +1570,7 @@ static struct mac_ops    cgx_mac_ops    = {
+       .mac_get_pause_frm_status =     cgx_lmac_get_pause_frm_status,
+       .mac_enadis_pause_frm =         cgx_lmac_enadis_pause_frm,
+       .mac_pause_frm_config =         cgx_lmac_pause_frm_config,
++      .mac_enadis_ptp_config =        cgx_lmac_ptp_config,
+ };
+ static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h b/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h
+index c38306b3384a7..fc6e7423cbd81 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h
+@@ -102,6 +102,11 @@ struct mac_ops {
+       void                    (*mac_pause_frm_config)(void  *cgxd,
+                                                       int lmac_id,
+                                                       bool enable);
++
++      /* Enable/Disable Inbound PTP */
++      void                    (*mac_enadis_ptp_config)(void  *cgxd,
++                                                       int lmac_id,
++                                                       bool enable);
+ };
+ struct cgx {
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
+index 472eb2a5697a4..c6643c7db1fc4 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
+@@ -154,23 +154,23 @@ M(CGX_PTP_RX_ENABLE,     0x20C, cgx_ptp_rx_enable, msg_req, msg_rsp)     \
+ M(CGX_PTP_RX_DISABLE, 0x20D, cgx_ptp_rx_disable, msg_req, msg_rsp)    \
+ M(CGX_CFG_PAUSE_FRM,  0x20E, cgx_cfg_pause_frm, cgx_pause_frm_cfg,    \
+                              cgx_pause_frm_cfg)                       \
+-M(CGX_FEC_SET,                0x210, cgx_set_fec_param, fec_mode, fec_mode)   \
+-M(CGX_FEC_STATS,      0x211, cgx_fec_stats, msg_req, cgx_fec_stats_rsp) \
+-M(CGX_GET_PHY_FEC_STATS, 0x212, cgx_get_phy_fec_stats, msg_req, msg_rsp) \
+-M(CGX_FW_DATA_GET,    0x213, cgx_get_aux_link_info, msg_req, cgx_fw_data) \
+-M(CGX_SET_LINK_MODE,  0x214, cgx_set_link_mode, cgx_set_link_mode_req,\
+-                             cgx_set_link_mode_rsp)   \
+-M(CGX_FEATURES_GET,   0x215, cgx_features_get, msg_req,               \
+-                             cgx_features_info_msg)                   \
+-M(RPM_STATS,          0x216, rpm_stats, msg_req, rpm_stats_rsp)       \
+-M(CGX_MAC_ADDR_ADD,   0x217, cgx_mac_addr_add, cgx_mac_addr_add_req,    \
+-                             cgx_mac_addr_add_rsp)            \
+-M(CGX_MAC_ADDR_DEL,   0x218, cgx_mac_addr_del, cgx_mac_addr_del_req,    \
++M(CGX_FW_DATA_GET,    0x20F, cgx_get_aux_link_info, msg_req, cgx_fw_data) \
++M(CGX_FEC_SET,                0x210, cgx_set_fec_param, fec_mode, fec_mode) \
++M(CGX_MAC_ADDR_ADD,   0x211, cgx_mac_addr_add, cgx_mac_addr_add_req,    \
++                              cgx_mac_addr_add_rsp)           \
++M(CGX_MAC_ADDR_DEL,   0x212, cgx_mac_addr_del, cgx_mac_addr_del_req,    \
+                              msg_rsp)         \
+-M(CGX_MAC_MAX_ENTRIES_GET, 0x219, cgx_mac_max_entries_get, msg_req,    \
++M(CGX_MAC_MAX_ENTRIES_GET, 0x213, cgx_mac_max_entries_get, msg_req,    \
+                                 cgx_max_dmac_entries_get_rsp)         \
+-M(CGX_MAC_ADDR_RESET, 0x21A, cgx_mac_addr_reset, msg_req, msg_rsp)    \
+-M(CGX_MAC_ADDR_UPDATE,        0x21B, cgx_mac_addr_update, cgx_mac_addr_update_req, \
++M(CGX_FEC_STATS,      0x217, cgx_fec_stats, msg_req, cgx_fec_stats_rsp) \
++M(CGX_SET_LINK_MODE,  0x218, cgx_set_link_mode, cgx_set_link_mode_req,\
++                             cgx_set_link_mode_rsp)   \
++M(CGX_GET_PHY_FEC_STATS, 0x219, cgx_get_phy_fec_stats, msg_req, msg_rsp) \
++M(CGX_FEATURES_GET,   0x21B, cgx_features_get, msg_req,               \
++                             cgx_features_info_msg)                   \
++M(RPM_STATS,          0x21C, rpm_stats, msg_req, rpm_stats_rsp)       \
++M(CGX_MAC_ADDR_RESET, 0x21D, cgx_mac_addr_reset, msg_req, msg_rsp)    \
++M(CGX_MAC_ADDR_UPDATE,        0x21E, cgx_mac_addr_update, cgx_mac_addr_update_req, \
+                              msg_rsp)                                 \
+ /* NPA mbox IDs (range 0x400 - 0x5FF) */                              \
+ M(NPA_LF_ALLOC,               0x400, npa_lf_alloc,                            \
+@@ -577,10 +577,13 @@ struct cgx_mac_addr_update_req {
+ };
+ #define RVU_LMAC_FEAT_FC              BIT_ULL(0) /* pause frames */
+-#define RVU_LMAC_FEAT_PTP             BIT_ULL(1) /* precision time protocol */
+-#define RVU_MAC_VERSION                       BIT_ULL(2)
+-#define RVU_MAC_CGX                   BIT_ULL(3)
+-#define RVU_MAC_RPM                   BIT_ULL(4)
++#define       RVU_LMAC_FEAT_HIGIG2            BIT_ULL(1)
++                      /* flow control from physical link higig2 messages */
++#define RVU_LMAC_FEAT_PTP             BIT_ULL(2) /* precison time protocol */
++#define RVU_LMAC_FEAT_DMACF           BIT_ULL(3) /* DMAC FILTER */
++#define RVU_MAC_VERSION                       BIT_ULL(4)
++#define RVU_MAC_CGX                   BIT_ULL(5)
++#define RVU_MAC_RPM                   BIT_ULL(6)
+ struct cgx_features_info_msg {
+       struct mbox_msghdr hdr;
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c
+index b3803577324e6..c8f20b36adc89 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c
+@@ -29,6 +29,7 @@ static struct mac_ops        rpm_mac_ops   = {
+       .mac_get_pause_frm_status =     rpm_lmac_get_pause_frm_status,
+       .mac_enadis_pause_frm =         rpm_lmac_enadis_pause_frm,
+       .mac_pause_frm_config =         rpm_lmac_pause_frm_config,
++      .mac_enadis_ptp_config =        rpm_lmac_ptp_config,
+ };
+ struct mac_ops *rpm_get_mac_ops(void)
+@@ -267,3 +268,19 @@ int rpm_lmac_internal_loopback(void *rpmd, int lmac_id, bool enable)
+       return 0;
+ }
++
++void rpm_lmac_ptp_config(void *rpmd, int lmac_id, bool enable)
++{
++      rpm_t *rpm = rpmd;
++      u64 cfg;
++
++      if (!is_lmac_valid(rpm, lmac_id))
++              return;
++
++      cfg = rpm_read(rpm, lmac_id, RPMX_CMRX_CFG);
++      if (enable)
++              cfg |= RPMX_RX_TS_PREPEND;
++      else
++              cfg &= ~RPMX_RX_TS_PREPEND;
++      rpm_write(rpm, lmac_id, RPMX_CMRX_CFG, cfg);
++}
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h
+index f0b069442dccb..57c8a687b488a 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h
+@@ -14,6 +14,8 @@
+ #define PCI_DEVID_CN10K_RPM           0xA060
+ /* Registers */
++#define RPMX_CMRX_CFG                 0x00
++#define RPMX_RX_TS_PREPEND              BIT_ULL(22)
+ #define RPMX_CMRX_SW_INT                0x180
+ #define RPMX_CMRX_SW_INT_W1S            0x188
+ #define RPMX_CMRX_SW_INT_ENA_W1S        0x198
+@@ -54,4 +56,5 @@ int rpm_lmac_enadis_pause_frm(void *rpmd, int lmac_id, u8 tx_pause,
+                             u8 rx_pause);
+ int rpm_get_tx_stats(void *rpmd, int lmac_id, int idx, u64 *tx_stat);
+ int rpm_get_rx_stats(void *rpmd, int lmac_id, int idx, u64 *rx_stat);
++void rpm_lmac_ptp_config(void *rpmd, int lmac_id, bool enable);
+ #endif /* RPM_H */
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
+index a5c717ad12c15..5bdbc77aa721d 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
+@@ -696,6 +696,7 @@ static int rvu_cgx_ptp_rx_cfg(struct rvu *rvu, u16 pcifunc, bool enable)
+ {
+       struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
+       int pf = rvu_get_pf(pcifunc);
++      struct mac_ops *mac_ops;
+       u8 cgx_id, lmac_id;
+       void *cgxd;
+@@ -712,7 +713,8 @@ static int rvu_cgx_ptp_rx_cfg(struct rvu *rvu, u16 pcifunc, bool enable)
+       rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
+       cgxd = rvu_cgx_pdata(cgx_id, rvu);
+-      cgx_lmac_ptp_config(cgxd, lmac_id, enable);
++      mac_ops = get_mac_ops(cgxd);
++      mac_ops->mac_enadis_ptp_config(cgxd, lmac_id, true);
+       /* If PTP is enabled then inform NPC that packets to be
+        * parsed by this PF will have their data shifted by 8 bytes
+        * and if PTP is disabled then no shift is required
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+index 8c94e30d0499e..143b554d044bf 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+@@ -4520,6 +4520,7 @@ void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int nixlf)
+       struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
+       struct hwctx_disable_req ctx_req;
+       int pf = rvu_get_pf(pcifunc);
++      struct mac_ops *mac_ops;
+       u8 cgx_id, lmac_id;
+       void *cgxd;
+       int err;
+@@ -4566,7 +4567,8 @@ void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int nixlf)
+       if (pfvf->hw_rx_tstamp_en) {
+               rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
+               cgxd = rvu_cgx_pdata(cgx_id, rvu);
+-              cgx_lmac_ptp_config(cgxd, lmac_id, false);
++              mac_ops = get_mac_ops(cgxd);
++              mac_ops->mac_enadis_ptp_config(cgxd, lmac_id, false);
+               /* Undo NPC config done for PTP */
+               if (npc_config_ts_kpuaction(rvu, pf, pcifunc, false))
+                       dev_err(rvu->dev, "NPC config for PTP failed\n");
+-- 
+2.34.1
+
diff --git a/queue-5.15/octeontx2-af-cn10k-use-appropriate-register-for-lmac.patch b/queue-5.15/octeontx2-af-cn10k-use-appropriate-register-for-lmac.patch
new file mode 100644 (file)
index 0000000..f081996
--- /dev/null
@@ -0,0 +1,224 @@
+From da17cacec32d28275cfb11eaed818739a4c7f746 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Jan 2022 12:04:42 +0530
+Subject: octeontx2-af: cn10k: Use appropriate register for LMAC enable
+
+From: Geetha sowjanya <gakula@marvell.com>
+
+[ Upstream commit fae80edeafbbba5ef9a0423aa5e5515518626433 ]
+
+CN10K platforms uses RPM(0..2)_MTI_MAC100(0..3)_COMMAND_CONFIG
+register for lmac TX/RX enable whereas CN9xxx platforms use
+CGX_CMRX_CONFIG register. This config change was missed when
+adding support for CN10K RPM.
+
+Fixes: 91c6945ea1f9 ("octeontx2-af: cn10k: Add RPM MAC support")
+Signed-off-by: Geetha sowjanya <gakula@marvell.com>
+Signed-off-by: Subbaraya Sundeep <sbhatta@marvell.com>
+Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/marvell/octeontx2/af/cgx.c   |  2 +
+ .../marvell/octeontx2/af/lmac_common.h        |  3 ++
+ .../net/ethernet/marvell/octeontx2/af/rpm.c   | 39 +++++++++++++++++++
+ .../net/ethernet/marvell/octeontx2/af/rpm.h   |  4 ++
+ .../net/ethernet/marvell/octeontx2/af/rvu.h   |  1 +
+ .../ethernet/marvell/octeontx2/af/rvu_cgx.c   | 14 ++++++-
+ .../ethernet/marvell/octeontx2/af/rvu_nix.c   | 10 ++---
+ 7 files changed, 66 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
+index d379a35c4618f..6b335139abe7f 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
+@@ -1571,6 +1571,8 @@ static struct mac_ops    cgx_mac_ops    = {
+       .mac_enadis_pause_frm =         cgx_lmac_enadis_pause_frm,
+       .mac_pause_frm_config =         cgx_lmac_pause_frm_config,
+       .mac_enadis_ptp_config =        cgx_lmac_ptp_config,
++      .mac_rx_tx_enable =             cgx_lmac_rx_tx_enable,
++      .mac_tx_enable =                cgx_lmac_tx_enable,
+ };
+ static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h b/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h
+index fc6e7423cbd81..b33e7d1d0851c 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h
+@@ -107,6 +107,9 @@ struct mac_ops {
+       void                    (*mac_enadis_ptp_config)(void  *cgxd,
+                                                        int lmac_id,
+                                                        bool enable);
++
++      int                     (*mac_rx_tx_enable)(void *cgxd, int lmac_id, bool enable);
++      int                     (*mac_tx_enable)(void *cgxd, int lmac_id, bool enable);
+ };
+ struct cgx {
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c
+index c8f20b36adc89..9ea2f6ac38ec1 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c
+@@ -30,6 +30,8 @@ static struct mac_ops        rpm_mac_ops   = {
+       .mac_enadis_pause_frm =         rpm_lmac_enadis_pause_frm,
+       .mac_pause_frm_config =         rpm_lmac_pause_frm_config,
+       .mac_enadis_ptp_config =        rpm_lmac_ptp_config,
++      .mac_rx_tx_enable =             rpm_lmac_rx_tx_enable,
++      .mac_tx_enable =                rpm_lmac_tx_enable,
+ };
+ struct mac_ops *rpm_get_mac_ops(void)
+@@ -54,6 +56,43 @@ int rpm_get_nr_lmacs(void *rpmd)
+       return hweight8(rpm_read(rpm, 0, CGXX_CMRX_RX_LMACS) & 0xFULL);
+ }
++int rpm_lmac_tx_enable(void *rpmd, int lmac_id, bool enable)
++{
++      rpm_t *rpm = rpmd;
++      u64 cfg, last;
++
++      if (!is_lmac_valid(rpm, lmac_id))
++              return -ENODEV;
++
++      cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG);
++      last = cfg;
++      if (enable)
++              cfg |= RPM_TX_EN;
++      else
++              cfg &= ~(RPM_TX_EN);
++
++      if (cfg != last)
++              rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg);
++      return !!(last & RPM_TX_EN);
++}
++
++int rpm_lmac_rx_tx_enable(void *rpmd, int lmac_id, bool enable)
++{
++      rpm_t *rpm = rpmd;
++      u64 cfg;
++
++      if (!is_lmac_valid(rpm, lmac_id))
++              return -ENODEV;
++
++      cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG);
++      if (enable)
++              cfg |= RPM_RX_EN | RPM_TX_EN;
++      else
++              cfg &= ~(RPM_RX_EN | RPM_TX_EN);
++      rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg);
++      return 0;
++}
++
+ void rpm_lmac_enadis_rx_pause_fwding(void *rpmd, int lmac_id, bool enable)
+ {
+       rpm_t *rpm = rpmd;
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h
+index 57c8a687b488a..ff580311edd03 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h
+@@ -43,6 +43,8 @@
+ #define RPMX_MTI_STAT_DATA_HI_CDC            0x10038
+ #define RPM_LMAC_FWI                  0xa
++#define RPM_TX_EN                     BIT_ULL(0)
++#define RPM_RX_EN                     BIT_ULL(1)
+ /* Function Declarations */
+ int rpm_get_nr_lmacs(void *rpmd);
+@@ -57,4 +59,6 @@ int rpm_lmac_enadis_pause_frm(void *rpmd, int lmac_id, u8 tx_pause,
+ int rpm_get_tx_stats(void *rpmd, int lmac_id, int idx, u64 *tx_stat);
+ int rpm_get_rx_stats(void *rpmd, int lmac_id, int idx, u64 *rx_stat);
+ void rpm_lmac_ptp_config(void *rpmd, int lmac_id, bool enable);
++int rpm_lmac_rx_tx_enable(void *rpmd, int lmac_id, bool enable);
++int rpm_lmac_tx_enable(void *rpmd, int lmac_id, bool enable);
+ #endif /* RPM_H */
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+index 8f81e468be048..a7213db38804b 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+@@ -801,6 +801,7 @@ bool is_mac_feature_supported(struct rvu *rvu, int pf, int feature);
+ u32  rvu_cgx_get_fifolen(struct rvu *rvu);
+ void *rvu_first_cgx_pdata(struct rvu *rvu);
+ int cgxlmac_to_pf(struct rvu *rvu, int cgx_id, int lmac_id);
++int rvu_cgx_config_tx(void *cgxd, int lmac_id, bool enable);
+ int npc_get_nixlf_mcam_index(struct npc_mcam *mcam, u16 pcifunc, int nixlf,
+                            int type);
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
+index 5bdbc77aa721d..28ff67819566c 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
+@@ -442,16 +442,26 @@ void rvu_cgx_enadis_rx_bp(struct rvu *rvu, int pf, bool enable)
+ int rvu_cgx_config_rxtx(struct rvu *rvu, u16 pcifunc, bool start)
+ {
+       int pf = rvu_get_pf(pcifunc);
++      struct mac_ops *mac_ops;
+       u8 cgx_id, lmac_id;
++      void *cgxd;
+       if (!is_cgx_config_permitted(rvu, pcifunc))
+               return LMAC_AF_ERR_PERM_DENIED;
+       rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
++      cgxd = rvu_cgx_pdata(cgx_id, rvu);
++      mac_ops = get_mac_ops(cgxd);
++
++      return mac_ops->mac_rx_tx_enable(cgxd, lmac_id, start);
++}
+-      cgx_lmac_rx_tx_enable(rvu_cgx_pdata(cgx_id, rvu), lmac_id, start);
++int rvu_cgx_config_tx(void *cgxd, int lmac_id, bool enable)
++{
++      struct mac_ops *mac_ops;
+-      return 0;
++      mac_ops = get_mac_ops(cgxd);
++      return mac_ops->mac_tx_enable(cgxd, lmac_id, enable);
+ }
+ void rvu_cgx_disable_dmac_entries(struct rvu *rvu, u16 pcifunc)
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+index 143b554d044bf..603361c94786a 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+@@ -2068,8 +2068,8 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr,
+       /* enable cgx tx if disabled */
+       if (is_pf_cgxmapped(rvu, pf)) {
+               rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
+-              restore_tx_en = !cgx_lmac_tx_enable(rvu_cgx_pdata(cgx_id, rvu),
+-                                                  lmac_id, true);
++              restore_tx_en = !rvu_cgx_config_tx(rvu_cgx_pdata(cgx_id, rvu),
++                                                 lmac_id, true);
+       }
+       cfg = rvu_read64(rvu, blkaddr, NIX_AF_SMQX_CFG(smq));
+@@ -2092,7 +2092,7 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr,
+       rvu_cgx_enadis_rx_bp(rvu, pf, true);
+       /* restore cgx tx state */
+       if (restore_tx_en)
+-              cgx_lmac_tx_enable(rvu_cgx_pdata(cgx_id, rvu), lmac_id, false);
++              rvu_cgx_config_tx(rvu_cgx_pdata(cgx_id, rvu), lmac_id, false);
+       return err;
+ }
+@@ -3878,7 +3878,7 @@ nix_config_link_credits(struct rvu *rvu, int blkaddr, int link,
+       /* Enable cgx tx if disabled for credits to be back */
+       if (is_pf_cgxmapped(rvu, pf)) {
+               rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
+-              restore_tx_en = !cgx_lmac_tx_enable(rvu_cgx_pdata(cgx_id, rvu),
++              restore_tx_en = !rvu_cgx_config_tx(rvu_cgx_pdata(cgx_id, rvu),
+                                                   lmac_id, true);
+       }
+@@ -3918,7 +3918,7 @@ nix_config_link_credits(struct rvu *rvu, int blkaddr, int link,
+       /* Restore state of cgx tx */
+       if (restore_tx_en)
+-              cgx_lmac_tx_enable(rvu_cgx_pdata(cgx_id, rvu), lmac_id, false);
++              rvu_cgx_config_tx(rvu_cgx_pdata(cgx_id, rvu), lmac_id, false);
+       mutex_unlock(&rvu->rsrc_lock);
+       return rc;
+-- 
+2.34.1
+
diff --git a/queue-5.15/octeontx2-af-optimize-kpu1-processing-for-variable-l.patch b/queue-5.15/octeontx2-af-optimize-kpu1-processing-for-variable-l.patch
new file mode 100644 (file)
index 0000000..5fea8cf
--- /dev/null
@@ -0,0 +1,899 @@
+From 1c2588080b177af94c1b01919f945695ede87d0e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Sep 2021 11:48:51 +0530
+Subject: octeontx2-af: Optimize KPU1 processing for variable-length headers
+
+From: Kiran Kumar K <kirankumark@marvell.com>
+
+[ Upstream commit edadeb38dc2fa2550801995b748110c3e5e59557 ]
+
+Optimized KPU1 entry processing for variable-length custom L2 headers
+of size 24B, 90B by
+       - Moving LA LTYPE parsing for 24B and 90B headers to PKIND.
+       - Removing LA flags assignment for 24B and 90B headers.
+       - Reserving a PKIND 55 to parse variable length headers.
+
+Also, new mailbox(NPC_SET_PKIND) added to configure PKIND with
+corresponding variable-length offset, mask, and shift count
+(NPC_AF_KPUX_ENTRYX_ACTION0).
+
+Signed-off-by: Kiran Kumar K <kirankumark@marvell.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/marvell/octeontx2/af/mbox.h  |  20 +-
+ .../net/ethernet/marvell/octeontx2/af/npc.h   |   9 +-
+ .../marvell/octeontx2/af/npc_profile.h        | 382 +++---------------
+ .../net/ethernet/marvell/octeontx2/af/rvu.h   |   5 +
+ .../ethernet/marvell/octeontx2/af/rvu_cgx.c   |   2 +-
+ .../ethernet/marvell/octeontx2/af/rvu_nix.c   |   4 +
+ .../ethernet/marvell/octeontx2/af/rvu_npc.c   |  96 +++++
+ 7 files changed, 195 insertions(+), 323 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
+index 26ad71842b3b2..472eb2a5697a4 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
+@@ -84,7 +84,7 @@ struct mbox_msghdr {
+ #define OTX2_MBOX_REQ_SIG (0xdead)
+ #define OTX2_MBOX_RSP_SIG (0xbeef)
+       u16 sig;         /* Signature, for validating corrupted msgs */
+-#define OTX2_MBOX_VERSION (0x0009)
++#define OTX2_MBOX_VERSION (0x000a)
+       u16 ver;         /* Version of msg's structure for this ID */
+       u16 next_msgoff; /* Offset of next msg within mailbox region */
+       int rc;          /* Msg process'ed response code */
+@@ -229,6 +229,8 @@ M(NPC_DELETE_FLOW,   0x600e, npc_delete_flow,                      \
+ M(NPC_MCAM_READ_ENTRY,          0x600f, npc_mcam_read_entry,                  \
+                                 npc_mcam_read_entry_req,              \
+                                 npc_mcam_read_entry_rsp)              \
++M(NPC_SET_PKIND,        0x6010,   npc_set_pkind,                        \
++                                npc_set_pkind, msg_rsp)               \
+ M(NPC_MCAM_READ_BASE_RULE, 0x6011, npc_read_base_steer_rule,            \
+                                  msg_req, npc_mcam_read_base_rule_rsp)  \
+ M(NPC_MCAM_GET_STATS, 0x6012, npc_mcam_entry_stats,                     \
+@@ -593,6 +595,22 @@ struct rpm_stats_rsp {
+       u64 tx_stats[RPM_TX_STATS_COUNT];
+ };
++struct npc_set_pkind {
++      struct mbox_msghdr hdr;
++#define OTX2_PRIV_FLAGS_DEFAULT  BIT_ULL(0)
++#define OTX2_PRIV_FLAGS_CUSTOM   BIT_ULL(63)
++      u64 mode;
++#define PKIND_TX              BIT_ULL(0)
++#define PKIND_RX              BIT_ULL(1)
++      u8 dir;
++      u8 pkind; /* valid only in case custom flag */
++      u8 var_len_off; /* Offset of custom header length field.
++                       * Valid only for pkind NPC_RX_CUSTOM_PRE_L2_PKIND
++                       */
++      u8 var_len_off_mask; /* Mask for length with in offset */
++      u8 shift_dir; /* shift direction to get length of the header at var_len_off */
++};
++
+ /* NPA mbox message formats */
+ /* NPA mailbox error codes
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc.h b/drivers/net/ethernet/marvell/octeontx2/af/npc.h
+index 3a819b24accc6..6e1192f526089 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/npc.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/npc.h
+@@ -31,9 +31,9 @@ enum npc_kpu_la_ltype {
+       NPC_LT_LA_HIGIG2_ETHER,
+       NPC_LT_LA_IH_NIX_HIGIG2_ETHER,
+       NPC_LT_LA_CUSTOM_L2_90B_ETHER,
+-      NPC_LT_LA_CH_LEN_90B_ETHER,
+       NPC_LT_LA_CPT_HDR,
+       NPC_LT_LA_CUSTOM_L2_24B_ETHER,
++      NPC_LT_LA_CUSTOM_PRE_L2_ETHER,
+       NPC_LT_LA_CUSTOM0 = 0xE,
+       NPC_LT_LA_CUSTOM1 = 0xF,
+ };
+@@ -148,10 +148,11 @@ enum npc_kpu_lh_ltype {
+  * Software assigns pkind for each incoming port such as CGX
+  * Ethernet interfaces, LBK interfaces, etc.
+  */
+-#define NPC_UNRESERVED_PKIND_COUNT NPC_RX_VLAN_EXDSA_PKIND
++#define NPC_UNRESERVED_PKIND_COUNT NPC_RX_CUSTOM_PRE_L2_PKIND
+ enum npc_pkind_type {
+       NPC_RX_LBK_PKIND = 0ULL,
++      NPC_RX_CUSTOM_PRE_L2_PKIND = 55ULL,
+       NPC_RX_VLAN_EXDSA_PKIND = 56ULL,
+       NPC_RX_CHLEN24B_PKIND = 57ULL,
+       NPC_RX_CPT_HDR_PKIND,
+@@ -162,6 +163,10 @@ enum npc_pkind_type {
+       NPC_TX_DEF_PKIND,       /* NIX-TX PKIND */
+ };
++enum npc_interface_type {
++      NPC_INTF_MODE_DEF,
++};
++
+ /* list of known and supported fields in packet header and
+  * fields present in key structure.
+  */
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h b/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h
+index 588822a0cf21e..2b7030886daec 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/npc_profile.h
+@@ -176,9 +176,8 @@ enum npc_kpu_parser_state {
+       NPC_S_KPU1_EXDSA,
+       NPC_S_KPU1_HIGIG2,
+       NPC_S_KPU1_IH_NIX_HIGIG2,
+-      NPC_S_KPU1_CUSTOM_L2_90B,
++      NPC_S_KPU1_CUSTOM_PRE_L2,
+       NPC_S_KPU1_CPT_HDR,
+-      NPC_S_KPU1_CUSTOM_L2_24B,
+       NPC_S_KPU1_VLAN_EXDSA,
+       NPC_S_KPU2_CTAG,
+       NPC_S_KPU2_CTAG2,
+@@ -979,8 +978,8 @@ static struct npc_kpu_profile_action ikpu_action_entries[] = {
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+               12, 16, 20, 0, 0,
+-              NPC_S_KPU1_ETHER, 0, 0,
+-              NPC_LID_LA, NPC_LT_NA,
++              NPC_S_KPU1_CUSTOM_PRE_L2, 0, 1,
++              NPC_LID_LA, NPC_LT_LA_CUSTOM_PRE_L2_ETHER,
+               0,
+               0, 0, 0, 0,
+@@ -996,9 +995,9 @@ static struct npc_kpu_profile_action ikpu_action_entries[] = {
+       },
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+-              36, 40, 44, 0, 0,
+-              NPC_S_KPU1_CUSTOM_L2_24B, 0, 0,
+-              NPC_LID_LA, NPC_LT_NA,
++              12, 16, 20, 0, 0,
++              NPC_S_KPU1_CUSTOM_PRE_L2, 24, 1,
++              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER,
+               0,
+               0, 0, 0, 0,
+@@ -1014,9 +1013,9 @@ static struct npc_kpu_profile_action ikpu_action_entries[] = {
+       },
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+-              102, 106, 110, 0, 0,
+-              NPC_S_KPU1_CUSTOM_L2_90B, 0, 0,
+-              NPC_LID_LA, NPC_LT_NA,
++              12, 16, 20, 0, 0,
++              NPC_S_KPU1_CUSTOM_PRE_L2, 90, 1,
++              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER,
+               0,
+               0, 0, 0, 0,
+@@ -1711,7 +1710,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = {
+               0x0000,
+       },
+       {
+-              NPC_S_KPU1_CUSTOM_L2_90B, 0xff,
++              NPC_S_KPU1_CUSTOM_PRE_L2, 0xff,
+               NPC_ETYPE_IP,
+               0xffff,
+               0x0000,
+@@ -1720,7 +1719,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = {
+               0x0000,
+       },
+       {
+-              NPC_S_KPU1_CUSTOM_L2_90B, 0xff,
++              NPC_S_KPU1_CUSTOM_PRE_L2, 0xff,
+               NPC_ETYPE_IP6,
+               0xffff,
+               0x0000,
+@@ -1729,7 +1728,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = {
+               0x0000,
+       },
+       {
+-              NPC_S_KPU1_CUSTOM_L2_90B, 0xff,
++              NPC_S_KPU1_CUSTOM_PRE_L2, 0xff,
+               NPC_ETYPE_ARP,
+               0xffff,
+               0x0000,
+@@ -1738,7 +1737,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = {
+               0x0000,
+       },
+       {
+-              NPC_S_KPU1_CUSTOM_L2_90B, 0xff,
++              NPC_S_KPU1_CUSTOM_PRE_L2, 0xff,
+               NPC_ETYPE_RARP,
+               0xffff,
+               0x0000,
+@@ -1747,7 +1746,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = {
+               0x0000,
+       },
+       {
+-              NPC_S_KPU1_CUSTOM_L2_90B, 0xff,
++              NPC_S_KPU1_CUSTOM_PRE_L2, 0xff,
+               NPC_ETYPE_PTP,
+               0xffff,
+               0x0000,
+@@ -1756,7 +1755,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = {
+               0x0000,
+       },
+       {
+-              NPC_S_KPU1_CUSTOM_L2_90B, 0xff,
++              NPC_S_KPU1_CUSTOM_PRE_L2, 0xff,
+               NPC_ETYPE_FCOE,
+               0xffff,
+               0x0000,
+@@ -1765,7 +1764,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = {
+               0x0000,
+       },
+       {
+-              NPC_S_KPU1_CUSTOM_L2_90B, 0xff,
++              NPC_S_KPU1_CUSTOM_PRE_L2, 0xff,
+               NPC_ETYPE_CTAG,
+               0xffff,
+               NPC_ETYPE_CTAG,
+@@ -1774,7 +1773,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = {
+               0x0000,
+       },
+       {
+-              NPC_S_KPU1_CUSTOM_L2_90B, 0xff,
++              NPC_S_KPU1_CUSTOM_PRE_L2, 0xff,
+               NPC_ETYPE_CTAG,
+               0xffff,
+               0x0000,
+@@ -1783,7 +1782,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = {
+               0x0000,
+       },
+       {
+-              NPC_S_KPU1_CUSTOM_L2_90B, 0xff,
++              NPC_S_KPU1_CUSTOM_PRE_L2, 0xff,
+               NPC_ETYPE_SBTAG,
+               0xffff,
+               0x0000,
+@@ -1792,7 +1791,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = {
+               0x0000,
+       },
+       {
+-              NPC_S_KPU1_CUSTOM_L2_90B, 0xff,
++              NPC_S_KPU1_CUSTOM_PRE_L2, 0xff,
+               NPC_ETYPE_QINQ,
+               0xffff,
+               0x0000,
+@@ -1801,7 +1800,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = {
+               0x0000,
+       },
+       {
+-              NPC_S_KPU1_CUSTOM_L2_90B, 0xff,
++              NPC_S_KPU1_CUSTOM_PRE_L2, 0xff,
+               NPC_ETYPE_ETAG,
+               0xffff,
+               0x0000,
+@@ -1810,7 +1809,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = {
+               0x0000,
+       },
+       {
+-              NPC_S_KPU1_CUSTOM_L2_90B, 0xff,
++              NPC_S_KPU1_CUSTOM_PRE_L2, 0xff,
+               NPC_ETYPE_MPLSU,
+               0xffff,
+               0x0000,
+@@ -1819,7 +1818,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = {
+               0x0000,
+       },
+       {
+-              NPC_S_KPU1_CUSTOM_L2_90B, 0xff,
++              NPC_S_KPU1_CUSTOM_PRE_L2, 0xff,
+               NPC_ETYPE_MPLSM,
+               0xffff,
+               0x0000,
+@@ -1828,7 +1827,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = {
+               0x0000,
+       },
+       {
+-              NPC_S_KPU1_CUSTOM_L2_90B, 0xff,
++              NPC_S_KPU1_CUSTOM_PRE_L2, 0xff,
+               NPC_ETYPE_NSH,
+               0xffff,
+               0x0000,
+@@ -1837,7 +1836,7 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = {
+               0x0000,
+       },
+       {
+-              NPC_S_KPU1_CUSTOM_L2_90B, 0xff,
++              NPC_S_KPU1_CUSTOM_PRE_L2, 0xff,
+               0x0000,
+               0x0000,
+               0x0000,
+@@ -1926,141 +1925,6 @@ static struct npc_kpu_profile_cam kpu1_cam_entries[] = {
+               0x0000,
+               0x0000,
+       },
+-      {
+-              NPC_S_KPU1_CUSTOM_L2_24B, 0xff,
+-              NPC_ETYPE_IP,
+-              0xffff,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-      },
+-      {
+-              NPC_S_KPU1_CUSTOM_L2_24B, 0xff,
+-              NPC_ETYPE_IP6,
+-              0xffff,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-      },
+-      {
+-              NPC_S_KPU1_CUSTOM_L2_24B, 0xff,
+-              NPC_ETYPE_ARP,
+-              0xffff,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-      },
+-      {
+-              NPC_S_KPU1_CUSTOM_L2_24B, 0xff,
+-              NPC_ETYPE_RARP,
+-              0xffff,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-      },
+-      {
+-              NPC_S_KPU1_CUSTOM_L2_24B, 0xff,
+-              NPC_ETYPE_PTP,
+-              0xffff,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-      },
+-      {
+-              NPC_S_KPU1_CUSTOM_L2_24B, 0xff,
+-              NPC_ETYPE_FCOE,
+-              0xffff,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-      },
+-      {
+-              NPC_S_KPU1_CUSTOM_L2_24B, 0xff,
+-              NPC_ETYPE_CTAG,
+-              0xffff,
+-              NPC_ETYPE_CTAG,
+-              0xffff,
+-              0x0000,
+-              0x0000,
+-      },
+-      {
+-              NPC_S_KPU1_CUSTOM_L2_24B, 0xff,
+-              NPC_ETYPE_CTAG,
+-              0xffff,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-      },
+-      {
+-              NPC_S_KPU1_CUSTOM_L2_24B, 0xff,
+-              NPC_ETYPE_SBTAG,
+-              0xffff,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-      },
+-      {
+-              NPC_S_KPU1_CUSTOM_L2_24B, 0xff,
+-              NPC_ETYPE_QINQ,
+-              0xffff,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-      },
+-      {
+-              NPC_S_KPU1_CUSTOM_L2_24B, 0xff,
+-              NPC_ETYPE_ETAG,
+-              0xffff,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-      },
+-      {
+-              NPC_S_KPU1_CUSTOM_L2_24B, 0xff,
+-              NPC_ETYPE_MPLSU,
+-              0xffff,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-      },
+-      {
+-              NPC_S_KPU1_CUSTOM_L2_24B, 0xff,
+-              NPC_ETYPE_MPLSM,
+-              0xffff,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-      },
+-      {
+-              NPC_S_KPU1_CUSTOM_L2_24B, 0xff,
+-              NPC_ETYPE_NSH,
+-              0xffff,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-      },
+-      {
+-              NPC_S_KPU1_CUSTOM_L2_24B, 0xff,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-              0x0000,
+-      },
+       {
+               NPC_S_KPU1_VLAN_EXDSA, 0xff,
+               NPC_ETYPE_CTAG,
+@@ -9192,121 +9056,121 @@ static struct npc_kpu_profile_action kpu1_action_entries[] = {
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+               8, 0, 6, 3, 0,
+-              NPC_S_KPU5_IP, 104, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER,
++              NPC_S_KPU5_IP, 14, 0,
++              NPC_LID_LA, NPC_LT_NA,
+               0,
+               0, 0, 0, 0,
+       },
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+               6, 0, 0, 3, 0,
+-              NPC_S_KPU5_IP6, 104, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER,
++              NPC_S_KPU5_IP6, 14, 0,
++              NPC_LID_LA, NPC_LT_NA,
+               0,
+               0, 0, 0, 0,
+       },
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+               0, 0, 0, 3, 0,
+-              NPC_S_KPU5_ARP, 104, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER,
++              NPC_S_KPU5_ARP, 14, 0,
++              NPC_LID_LA, NPC_LT_NA,
+               0,
+               0, 0, 0, 0,
+       },
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+               0, 0, 0, 3, 0,
+-              NPC_S_KPU5_RARP, 104, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER,
++              NPC_S_KPU5_RARP, 14, 0,
++              NPC_LID_LA, NPC_LT_NA,
+               0,
+               0, 0, 0, 0,
+       },
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+               0, 0, 0, 3, 0,
+-              NPC_S_KPU5_PTP, 104, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER,
++              NPC_S_KPU5_PTP, 14, 0,
++              NPC_LID_LA, NPC_LT_NA,
+               0,
+               0, 0, 0, 0,
+       },
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+               0, 0, 0, 3, 0,
+-              NPC_S_KPU5_FCOE, 104, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER,
++              NPC_S_KPU5_FCOE, 14, 0,
++              NPC_LID_LA, NPC_LT_NA,
+               0,
+               0, 0, 0, 0,
+       },
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+               8, 12, 0, 0, 0,
+-              NPC_S_KPU2_CTAG2, 102, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER,
+-              NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_VLAN,
++              NPC_S_KPU2_CTAG2, 12, 0,
++              NPC_LID_LA, NPC_LT_NA,
++              0,
+               0, 0, 0, 0,
+       },
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+               4, 8, 0, 0, 0,
+-              NPC_S_KPU2_CTAG, 102, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER,
+-              NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_VLAN,
++              NPC_S_KPU2_CTAG, 12, 0,
++              NPC_LID_LA, NPC_LT_NA,
++              0,
+               0, 0, 0, 0,
+       },
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+               4, 8, 22, 0, 0,
+-              NPC_S_KPU2_SBTAG, 102, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER,
+-              NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_VLAN,
++              NPC_S_KPU2_SBTAG, 12, 0,
++              NPC_LID_LA, NPC_LT_NA,
++              0,
+               0, 0, 0, 0,
+       },
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+               4, 8, 0, 0, 0,
+-              NPC_S_KPU2_QINQ, 102, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER,
+-              NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_VLAN,
++              NPC_S_KPU2_QINQ, 12, 0,
++              NPC_LID_LA, NPC_LT_NA,
++              0,
+               0, 0, 0, 0,
+       },
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+               8, 12, 26, 0, 0,
+-              NPC_S_KPU2_ETAG, 102, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER,
+-              NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_ETAG,
++              NPC_S_KPU2_ETAG, 12, 0,
++              NPC_LID_LA, NPC_LT_NA,
++              0,
+               0, 0, 0, 0,
+       },
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+               2, 6, 10, 2, 0,
+-              NPC_S_KPU4_MPLS, 104, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER,
+-              NPC_F_LA_L_WITH_MPLS,
++              NPC_S_KPU4_MPLS, 14, 0,
++              NPC_LID_LA, NPC_LT_NA,
++              0,
+               0, 0, 0, 0,
+       },
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+               2, 6, 10, 2, 0,
+-              NPC_S_KPU4_MPLS, 104, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER,
+-              NPC_F_LA_L_WITH_MPLS,
++              NPC_S_KPU4_MPLS, 14, 0,
++              NPC_LID_LA, NPC_LT_NA,
++              0,
+               0, 0, 0, 0,
+       },
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+               2, 0, 0, 2, 0,
+-              NPC_S_KPU4_NSH, 104, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER,
+-              NPC_F_LA_L_WITH_NSH,
++              NPC_S_KPU4_NSH, 14, 0,
++              NPC_LID_LA, NPC_LT_NA,
++              0,
+               0, 0, 0, 0,
+       },
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+               0, 0, 0, 0, 1,
+-              NPC_S_NA, 0, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_90B_ETHER,
+-              NPC_F_LA_L_UNK_ETYPE,
++              NPC_S_NA, 0, 0,
++              NPC_LID_LA, NPC_LT_NA,
++              0,
+               0, 0, 0, 0,
+       },
+       {
+@@ -9381,126 +9245,6 @@ static struct npc_kpu_profile_action kpu1_action_entries[] = {
+               NPC_F_LA_L_UNK_ETYPE,
+               0, 0, 0, 0,
+       },
+-      {
+-              NPC_ERRLEV_RE, NPC_EC_NOERR,
+-              8, 0, 6, 3, 0,
+-              NPC_S_KPU5_IP, 38, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER,
+-              0,
+-              0, 0, 0, 0,
+-      },
+-      {
+-              NPC_ERRLEV_RE, NPC_EC_NOERR,
+-              6, 0, 0, 3, 0,
+-              NPC_S_KPU5_IP6, 38, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER,
+-              0,
+-              0, 0, 0, 0,
+-      },
+-      {
+-              NPC_ERRLEV_RE, NPC_EC_NOERR,
+-              0, 0, 0, 3, 0,
+-              NPC_S_KPU5_ARP, 38, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER,
+-              0,
+-              0, 0, 0, 0,
+-      },
+-      {
+-              NPC_ERRLEV_RE, NPC_EC_NOERR,
+-              0, 0, 0, 3, 0,
+-              NPC_S_KPU5_RARP, 38, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER,
+-              0,
+-              0, 0, 0, 0,
+-      },
+-      {
+-              NPC_ERRLEV_RE, NPC_EC_NOERR,
+-              0, 0, 0, 3, 0,
+-              NPC_S_KPU5_PTP, 38, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER,
+-              0,
+-              0, 0, 0, 0,
+-      },
+-      {
+-              NPC_ERRLEV_RE, NPC_EC_NOERR,
+-              0, 0, 0, 3, 0,
+-              NPC_S_KPU5_FCOE, 38, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER,
+-              0,
+-              0, 0, 0, 0,
+-      },
+-      {
+-              NPC_ERRLEV_RE, NPC_EC_NOERR,
+-              8, 12, 0, 0, 0,
+-              NPC_S_KPU2_CTAG2, 36, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER,
+-              NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_VLAN,
+-              0, 0, 0, 0,
+-      },
+-      {
+-              NPC_ERRLEV_RE, NPC_EC_NOERR,
+-              4, 8, 0, 0, 0,
+-              NPC_S_KPU2_CTAG, 36, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER,
+-              NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_VLAN,
+-              0, 0, 0, 0,
+-      },
+-      {
+-              NPC_ERRLEV_RE, NPC_EC_NOERR,
+-              4, 8, 22, 0, 0,
+-              NPC_S_KPU2_SBTAG, 36, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER,
+-              NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_VLAN,
+-              0, 0, 0, 0,
+-      },
+-      {
+-              NPC_ERRLEV_RE, NPC_EC_NOERR,
+-              4, 8, 0, 0, 0,
+-              NPC_S_KPU2_QINQ, 36, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER,
+-              NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_VLAN,
+-              0, 0, 0, 0,
+-      },
+-      {
+-              NPC_ERRLEV_RE, NPC_EC_NOERR,
+-              8, 12, 26, 0, 0,
+-              NPC_S_KPU2_ETAG, 36, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER,
+-              NPC_F_LA_U_HAS_TAG | NPC_F_LA_L_WITH_ETAG,
+-              0, 0, 0, 0,
+-      },
+-      {
+-              NPC_ERRLEV_RE, NPC_EC_NOERR,
+-              2, 6, 10, 2, 0,
+-              NPC_S_KPU4_MPLS, 38, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER,
+-              NPC_F_LA_L_WITH_MPLS,
+-              0, 0, 0, 0,
+-      },
+-      {
+-              NPC_ERRLEV_RE, NPC_EC_NOERR,
+-              2, 6, 10, 2, 0,
+-              NPC_S_KPU4_MPLS, 38, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER,
+-              NPC_F_LA_L_WITH_MPLS,
+-              0, 0, 0, 0,
+-      },
+-      {
+-              NPC_ERRLEV_RE, NPC_EC_NOERR,
+-              2, 0, 0, 2, 0,
+-              NPC_S_KPU4_NSH, 38, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER,
+-              NPC_F_LA_L_WITH_NSH,
+-              0, 0, 0, 0,
+-      },
+-      {
+-              NPC_ERRLEV_RE, NPC_EC_NOERR,
+-              0, 0, 0, 0, 1,
+-              NPC_S_NA, 0, 1,
+-              NPC_LID_LA, NPC_LT_LA_CUSTOM_L2_24B_ETHER,
+-              NPC_F_LA_L_UNK_ETYPE,
+-              0, 0, 0, 0,
+-      },
+       {
+               NPC_ERRLEV_RE, NPC_EC_NOERR,
+               12, 0, 0, 1, 0,
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+index 1d9411232f1da..c3979ec2bb86d 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+@@ -237,6 +237,7 @@ struct rvu_pfvf {
+       bool    cgx_in_use; /* this PF/VF using CGX? */
+       int     cgx_users;  /* number of cgx users - used only by PFs */
++      int     intf_mode;
+       u8      nix_blkaddr; /* BLKADDR_NIX0/1 assigned to this PF */
+       u8      nix_rx_intf; /* NIX0_RX/NIX1_RX interface to NPC */
+       u8      nix_tx_intf; /* NIX0_TX/NIX1_TX interface to NPC */
+@@ -794,6 +795,7 @@ void npc_enable_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
+ void npc_read_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
+                        int blkaddr, u16 src, struct mcam_entry *entry,
+                        u8 *intf, u8 *ena);
++bool is_cgx_config_permitted(struct rvu *rvu, u16 pcifunc);
+ bool is_mac_feature_supported(struct rvu *rvu, int pf, int feature);
+ u32  rvu_cgx_get_fifolen(struct rvu *rvu);
+ void *rvu_first_cgx_pdata(struct rvu *rvu);
+@@ -827,4 +829,7 @@ void rvu_switch_enable(struct rvu *rvu);
+ void rvu_switch_disable(struct rvu *rvu);
+ void rvu_switch_update_rules(struct rvu *rvu, u16 pcifunc);
++int rvu_npc_set_parse_mode(struct rvu *rvu, u16 pcifunc, u64 mode, u8 dir,
++                         u64 pkind, u8 var_len_off, u8 var_len_off_mask,
++                         u8 shift_dir);
+ #endif /* RVU_H */
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
+index 81e8ea9ee30ea..21e5906bcc372 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
+@@ -411,7 +411,7 @@ int rvu_cgx_exit(struct rvu *rvu)
+  * VF's of mapped PF and other PFs are not allowed. This fn() checks
+  * whether a PFFUNC is permitted to do the config or not.
+  */
+-static bool is_cgx_config_permitted(struct rvu *rvu, u16 pcifunc)
++inline bool is_cgx_config_permitted(struct rvu *rvu, u16 pcifunc)
+ {
+       if ((pcifunc & RVU_PFVF_FUNC_MASK) ||
+           !is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc)))
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+index 959266894cf15..f43df4683943d 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+@@ -4555,6 +4555,10 @@ void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int nixlf)
+                       dev_err(rvu->dev, "CQ ctx disable failed\n");
+       }
++      /* reset HW config done for Switch headers */
++      rvu_npc_set_parse_mode(rvu, pcifunc, OTX2_PRIV_FLAGS_DEFAULT,
++                             (PKIND_TX | PKIND_RX), 0, 0, 0, 0);
++
+       nix_ctx_free(rvu, pfvf);
+       nix_free_all_bandprof(rvu, pcifunc);
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+index 87f18e32b4634..2f347e937f00a 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+@@ -3183,6 +3183,102 @@ int rvu_mbox_handler_npc_get_kex_cfg(struct rvu *rvu, struct msg_req *req,
+       return 0;
+ }
++int
++npc_set_var_len_offset_pkind(struct rvu *rvu, u16 pcifunc, u64 pkind,
++                           u8 var_len_off, u8 var_len_off_mask, u8 shift_dir)
++{
++      struct npc_kpu_action0 *act0;
++      u8 shift_count = 0;
++      int blkaddr;
++      u64 val;
++
++      if (!var_len_off_mask)
++              return -EINVAL;
++
++      if (var_len_off_mask != 0xff) {
++              if (shift_dir)
++                      shift_count = __ffs(var_len_off_mask);
++              else
++                      shift_count = (8 - __fls(var_len_off_mask));
++      }
++      blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, pcifunc);
++      if (blkaddr < 0) {
++              dev_err(rvu->dev, "%s: NPC block not implemented\n", __func__);
++              return -EINVAL;
++      }
++      val = rvu_read64(rvu, blkaddr, NPC_AF_PKINDX_ACTION0(pkind));
++      act0 = (struct npc_kpu_action0 *)&val;
++      act0->var_len_shift = shift_count;
++      act0->var_len_right = shift_dir;
++      act0->var_len_mask = var_len_off_mask;
++      act0->var_len_offset = var_len_off;
++      rvu_write64(rvu, blkaddr, NPC_AF_PKINDX_ACTION0(pkind), val);
++      return 0;
++}
++
++int rvu_npc_set_parse_mode(struct rvu *rvu, u16 pcifunc, u64 mode, u8 dir,
++                         u64 pkind, u8 var_len_off, u8 var_len_off_mask,
++                         u8 shift_dir)
++
++{
++      struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
++      int blkaddr, nixlf, rc, intf_mode;
++      int pf = rvu_get_pf(pcifunc);
++      u64 rxpkind, txpkind;
++      u8 cgx_id, lmac_id;
++
++      /* use default pkind to disable edsa/higig */
++      rxpkind = rvu_npc_get_pkind(rvu, pf);
++      txpkind = NPC_TX_DEF_PKIND;
++      intf_mode = NPC_INTF_MODE_DEF;
++
++      if (mode & OTX2_PRIV_FLAGS_CUSTOM) {
++              if (pkind == NPC_RX_CUSTOM_PRE_L2_PKIND) {
++                      rc = npc_set_var_len_offset_pkind(rvu, pcifunc, pkind,
++                                                        var_len_off,
++                                                        var_len_off_mask,
++                                                        shift_dir);
++                      if (rc)
++                              return rc;
++              }
++              rxpkind = pkind;
++              txpkind = pkind;
++      }
++
++      if (dir & PKIND_RX) {
++              /* rx pkind set req valid only for cgx mapped PFs */
++              if (!is_cgx_config_permitted(rvu, pcifunc))
++                      return 0;
++              rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
++
++              rc = cgx_set_pkind(rvu_cgx_pdata(cgx_id, rvu), lmac_id,
++                                 rxpkind);
++              if (rc)
++                      return rc;
++      }
++
++      if (dir & PKIND_TX) {
++              /* Tx pkind set request valid if PCIFUNC has NIXLF attached */
++              rc = nix_get_nixlf(rvu, pcifunc, &nixlf, &blkaddr);
++              if (rc)
++                      return rc;
++
++              rvu_write64(rvu, blkaddr, NIX_AF_LFX_TX_PARSE_CFG(nixlf),
++                          txpkind);
++      }
++
++      pfvf->intf_mode = intf_mode;
++      return 0;
++}
++
++int rvu_mbox_handler_npc_set_pkind(struct rvu *rvu, struct npc_set_pkind *req,
++                                 struct msg_rsp *rsp)
++{
++      return rvu_npc_set_parse_mode(rvu, req->hdr.pcifunc, req->mode,
++                                    req->dir, req->pkind, req->var_len_off,
++                                    req->var_len_off_mask, req->shift_dir);
++}
++
+ int rvu_mbox_handler_npc_read_base_steer_rule(struct rvu *rvu,
+                                             struct msg_req *req,
+                                             struct npc_mcam_read_base_rule_rsp *rsp)
+-- 
+2.34.1
+
diff --git a/queue-5.15/octeontx2-af-reset-ptp-config-in-flr-handler.patch b/queue-5.15/octeontx2-af-reset-ptp-config-in-flr-handler.patch
new file mode 100644 (file)
index 0000000..ed6475a
--- /dev/null
@@ -0,0 +1,95 @@
+From 28c62ab367092dece278e0fcefd6d92a8d2075e6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Sep 2021 17:00:58 +0530
+Subject: octeontx2-af: Reset PTP config in FLR handler
+
+From: Harman Kalra <hkalra@marvell.com>
+
+[ Upstream commit e37e08fffc373206ad4e905c05729ea6bbdcb22c ]
+
+Upon receiving ptp config request from netdev interface , Octeontx2 MAC
+block CGX is configured to append timestamp to every incoming packet
+and NPC config is updated with DMAC offset change.
+
+Currently this configuration is not reset in FLR handler. This patch
+resets the same.
+
+Signed-off-by: Harman Kalra <hkalra@marvell.com>
+Signed-off-by: Hariprasad Kelam <hkelam@marvell.com>
+Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/marvell/octeontx2/af/rvu.h    |  1 +
+ .../net/ethernet/marvell/octeontx2/af/rvu_cgx.c    |  3 +++
+ .../net/ethernet/marvell/octeontx2/af/rvu_nix.c    | 14 ++++++++++++++
+ 3 files changed, 18 insertions(+)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+index c3979ec2bb86d..8f81e468be048 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+@@ -220,6 +220,7 @@ struct rvu_pfvf {
+       u16             maxlen;
+       u16             minlen;
++      bool            hw_rx_tstamp_en; /* Is rx_tstamp enabled */
+       u8              mac_addr[ETH_ALEN]; /* MAC address of this PF/VF */
+       u8              default_mac[ETH_ALEN]; /* MAC address from FWdata */
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
+index 21e5906bcc372..a5c717ad12c15 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
+@@ -694,6 +694,7 @@ int rvu_mbox_handler_cgx_promisc_disable(struct rvu *rvu, struct msg_req *req,
+ static int rvu_cgx_ptp_rx_cfg(struct rvu *rvu, u16 pcifunc, bool enable)
+ {
++      struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
+       int pf = rvu_get_pf(pcifunc);
+       u8 cgx_id, lmac_id;
+       void *cgxd;
+@@ -718,6 +719,8 @@ static int rvu_cgx_ptp_rx_cfg(struct rvu *rvu, u16 pcifunc, bool enable)
+        */
+       if (npc_config_ts_kpuaction(rvu, pf, pcifunc, enable))
+               return -EINVAL;
++      /* This flag is required to clean up CGX conf if app gets killed */
++      pfvf->hw_rx_tstamp_en = enable;
+       return 0;
+ }
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+index f43df4683943d..8c94e30d0499e 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+@@ -4519,6 +4519,9 @@ void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int nixlf)
+ {
+       struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
+       struct hwctx_disable_req ctx_req;
++      int pf = rvu_get_pf(pcifunc);
++      u8 cgx_id, lmac_id;
++      void *cgxd;
+       int err;
+       ctx_req.hdr.pcifunc = pcifunc;
+@@ -4559,6 +4562,17 @@ void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int nixlf)
+       rvu_npc_set_parse_mode(rvu, pcifunc, OTX2_PRIV_FLAGS_DEFAULT,
+                              (PKIND_TX | PKIND_RX), 0, 0, 0, 0);
++      /* Disabling CGX and NPC config done for PTP */
++      if (pfvf->hw_rx_tstamp_en) {
++              rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
++              cgxd = rvu_cgx_pdata(cgx_id, rvu);
++              cgx_lmac_ptp_config(cgxd, lmac_id, false);
++              /* Undo NPC config done for PTP */
++              if (npc_config_ts_kpuaction(rvu, pf, pcifunc, false))
++                      dev_err(rvu->dev, "NPC config for PTP failed\n");
++              pfvf->hw_rx_tstamp_en = false;
++      }
++
+       nix_ctx_free(rvu, pfvf);
+       nix_free_all_bandprof(rvu, pcifunc);
+-- 
+2.34.1
+
diff --git a/queue-5.15/of-net-move-of_net-under-net.patch b/queue-5.15/of-net-move-of_net-under-net.patch
new file mode 100644 (file)
index 0000000..1df69c9
--- /dev/null
@@ -0,0 +1,175 @@
+From 1e3b771b0bea4fb43311d4c05276592aed68a1b3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Oct 2021 18:06:54 -0700
+Subject: of: net: move of_net under net/
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit e330fb14590c5c80f7195c3d8c9b4bcf79e1a5cd ]
+
+Rob suggests to move of_net.c from under drivers/of/ somewhere
+to the networking code.
+
+Suggested-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Reviewed-by: Rob Herring <robh@kernel.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/amd/Kconfig    | 2 +-
+ drivers/net/ethernet/arc/Kconfig    | 4 ++--
+ drivers/net/ethernet/ezchip/Kconfig | 2 +-
+ drivers/net/ethernet/litex/Kconfig  | 2 +-
+ drivers/net/ethernet/mscc/Kconfig   | 2 +-
+ drivers/of/Kconfig                  | 4 ----
+ drivers/of/Makefile                 | 1 -
+ include/linux/of_net.h              | 2 +-
+ net/core/Makefile                   | 1 +
+ net/core/net-sysfs.c                | 2 +-
+ {drivers/of => net/core}/of_net.c   | 0
+ 11 files changed, 9 insertions(+), 13 deletions(-)
+ rename {drivers/of => net/core}/of_net.c (100%)
+
+diff --git a/drivers/net/ethernet/amd/Kconfig b/drivers/net/ethernet/amd/Kconfig
+index 4786f0504691d..899c8a2a34b6b 100644
+--- a/drivers/net/ethernet/amd/Kconfig
++++ b/drivers/net/ethernet/amd/Kconfig
+@@ -168,7 +168,7 @@ config SUNLANCE
+ config AMD_XGBE
+       tristate "AMD 10GbE Ethernet driver"
+-      depends on ((OF_NET && OF_ADDRESS) || ACPI || PCI) && HAS_IOMEM
++      depends on (OF_ADDRESS || ACPI || PCI) && HAS_IOMEM
+       depends on X86 || ARM64 || COMPILE_TEST
+       depends on PTP_1588_CLOCK_OPTIONAL
+       select BITREVERSE
+diff --git a/drivers/net/ethernet/arc/Kconfig b/drivers/net/ethernet/arc/Kconfig
+index 92a79c4ffa2c7..0a67612af2281 100644
+--- a/drivers/net/ethernet/arc/Kconfig
++++ b/drivers/net/ethernet/arc/Kconfig
+@@ -26,7 +26,7 @@ config ARC_EMAC_CORE
+ config ARC_EMAC
+       tristate "ARC EMAC support"
+       select ARC_EMAC_CORE
+-      depends on OF_IRQ && OF_NET
++      depends on OF_IRQ
+       depends on ARC || COMPILE_TEST
+       help
+         On some legacy ARC (Synopsys) FPGA boards such as ARCAngel4/ML50x
+@@ -36,7 +36,7 @@ config ARC_EMAC
+ config EMAC_ROCKCHIP
+       tristate "Rockchip EMAC support"
+       select ARC_EMAC_CORE
+-      depends on OF_IRQ && OF_NET && REGULATOR
++      depends on OF_IRQ && REGULATOR
+       depends on ARCH_ROCKCHIP || COMPILE_TEST
+       help
+         Support for Rockchip RK3036/RK3066/RK3188 EMAC ethernet controllers.
+diff --git a/drivers/net/ethernet/ezchip/Kconfig b/drivers/net/ethernet/ezchip/Kconfig
+index 38aa824efb25d..9241b9b1c7a36 100644
+--- a/drivers/net/ethernet/ezchip/Kconfig
++++ b/drivers/net/ethernet/ezchip/Kconfig
+@@ -18,7 +18,7 @@ if NET_VENDOR_EZCHIP
+ config EZCHIP_NPS_MANAGEMENT_ENET
+       tristate "EZchip NPS management enet support"
+-      depends on OF_IRQ && OF_NET
++      depends on OF_IRQ
+       depends on HAS_IOMEM
+       help
+         Simple LAN device for debug or management purposes.
+diff --git a/drivers/net/ethernet/litex/Kconfig b/drivers/net/ethernet/litex/Kconfig
+index 63bf01d28f0cf..f99adbf26ab4e 100644
+--- a/drivers/net/ethernet/litex/Kconfig
++++ b/drivers/net/ethernet/litex/Kconfig
+@@ -17,7 +17,7 @@ if NET_VENDOR_LITEX
+ config LITEX_LITEETH
+       tristate "LiteX Ethernet support"
+-      depends on OF_NET
++      depends on OF
+       help
+         If you wish to compile a kernel for hardware with a LiteX LiteEth
+         device then you should answer Y to this.
+diff --git a/drivers/net/ethernet/mscc/Kconfig b/drivers/net/ethernet/mscc/Kconfig
+index b6a73d151dec1..8dd8c7f425d2c 100644
+--- a/drivers/net/ethernet/mscc/Kconfig
++++ b/drivers/net/ethernet/mscc/Kconfig
+@@ -28,7 +28,7 @@ config MSCC_OCELOT_SWITCH
+       depends on BRIDGE || BRIDGE=n
+       depends on NET_SWITCHDEV
+       depends on HAS_IOMEM
+-      depends on OF_NET
++      depends on OF
+       select MSCC_OCELOT_SWITCH_LIB
+       select GENERIC_PHY
+       help
+diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
+index 3dfeae8912dfc..80b5fd44ab1c7 100644
+--- a/drivers/of/Kconfig
++++ b/drivers/of/Kconfig
+@@ -70,10 +70,6 @@ config OF_IRQ
+       def_bool y
+       depends on !SPARC && IRQ_DOMAIN
+-config OF_NET
+-      depends on NETDEVICES
+-      def_bool y
+-
+ config OF_RESERVED_MEM
+       def_bool OF_EARLY_FLATTREE
+diff --git a/drivers/of/Makefile b/drivers/of/Makefile
+index c13b982084a3a..e0360a44306e2 100644
+--- a/drivers/of/Makefile
++++ b/drivers/of/Makefile
+@@ -7,7 +7,6 @@ obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o
+ obj-$(CONFIG_OF_PROMTREE) += pdt.o
+ obj-$(CONFIG_OF_ADDRESS)  += address.o
+ obj-$(CONFIG_OF_IRQ)    += irq.o
+-obj-$(CONFIG_OF_NET)  += of_net.o
+ obj-$(CONFIG_OF_UNITTEST) += unittest.o
+ obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o
+ obj-$(CONFIG_OF_RESOLVE)  += resolver.o
+diff --git a/include/linux/of_net.h b/include/linux/of_net.h
+index daef3b0d9270d..cf31188329b5a 100644
+--- a/include/linux/of_net.h
++++ b/include/linux/of_net.h
+@@ -8,7 +8,7 @@
+ #include <linux/phy.h>
+-#ifdef CONFIG_OF_NET
++#ifdef CONFIG_OF
+ #include <linux/of.h>
+ struct net_device;
+diff --git a/net/core/Makefile b/net/core/Makefile
+index 35ced6201814c..4268846f2f475 100644
+--- a/net/core/Makefile
++++ b/net/core/Makefile
+@@ -36,3 +36,4 @@ obj-$(CONFIG_FAILOVER) += failover.o
+ obj-$(CONFIG_NET_SOCK_MSG) += skmsg.o
+ obj-$(CONFIG_BPF_SYSCALL) += sock_map.o
+ obj-$(CONFIG_BPF_SYSCALL) += bpf_sk_storage.o
++obj-$(CONFIG_OF)      += of_net.o
+diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
+index a4ae652633844..d7f9ee830d34c 100644
+--- a/net/core/net-sysfs.c
++++ b/net/core/net-sysfs.c
+@@ -1927,7 +1927,7 @@ static struct class net_class __ro_after_init = {
+       .get_ownership = net_get_ownership,
+ };
+-#ifdef CONFIG_OF_NET
++#ifdef CONFIG_OF
+ static int of_dev_node_match(struct device *dev, const void *data)
+ {
+       for (; dev; dev = dev->parent) {
+diff --git a/drivers/of/of_net.c b/net/core/of_net.c
+similarity index 100%
+rename from drivers/of/of_net.c
+rename to net/core/of_net.c
+-- 
+2.34.1
+
diff --git a/queue-5.15/pci-aardvark-fix-checking-for-mem-resource-type.patch b/queue-5.15/pci-aardvark-fix-checking-for-mem-resource-type.patch
new file mode 100644 (file)
index 0000000..60227ab
--- /dev/null
@@ -0,0 +1,53 @@
+From 46d73b32b068ce6b85ceb8b58672b792209f0a71 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Nov 2021 17:01:47 +0100
+Subject: PCI: aardvark: Fix checking for MEM resource type
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+[ Upstream commit 2070b2ddea89f5b604fac3d27ade5cb6d19a5706 ]
+
+IORESOURCE_MEM_64 is not a resource type but a type flag.
+
+Remove incorrect check for type IORESOURCE_MEM_64.
+
+Link: https://lore.kernel.org/r/20211125160148.26029-2-kabel@kernel.org
+Fixes: 64f160e19e92 ("PCI: aardvark: Configure PCIe resources from 'ranges' DT property")
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/pci-aardvark.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
+index 85323cbc4888a..b2217e2b3efde 100644
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1537,8 +1537,7 @@ static int advk_pcie_probe(struct platform_device *pdev)
+                * only PIO for issuing configuration transfers which does
+                * not use PCIe window configuration.
+                */
+-              if (type != IORESOURCE_MEM && type != IORESOURCE_MEM_64 &&
+-                  type != IORESOURCE_IO)
++              if (type != IORESOURCE_MEM && type != IORESOURCE_IO)
+                       continue;
+               /*
+@@ -1546,8 +1545,7 @@ static int advk_pcie_probe(struct platform_device *pdev)
+                * configuration is set to transparent memory access so it
+                * does not need window configuration.
+                */
+-              if ((type == IORESOURCE_MEM || type == IORESOURCE_MEM_64) &&
+-                  entry->offset == 0)
++              if (type == IORESOURCE_MEM && entry->offset == 0)
+                       continue;
+               /*
+-- 
+2.34.1
+
diff --git a/queue-5.15/pci-dwc-do-not-remap-invalid-res.patch b/queue-5.15/pci-dwc-do-not-remap-invalid-res.patch
new file mode 100644 (file)
index 0000000..f9e1ab9
--- /dev/null
@@ -0,0 +1,49 @@
+From b711eba342a4123837e5695fd5bdf2d44f0980cb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Nov 2021 11:02:43 -0700
+Subject: PCI: dwc: Do not remap invalid res
+
+From: Tim Harvey <tharvey@gateworks.com>
+
+[ Upstream commit 6e5ebc96ec651b67131f816d7e3bf286c635e749 ]
+
+On imx6 and perhaps others when pcie probes you get a:
+imx6q-pcie 33800000.pcie: invalid resource
+
+This occurs because the atu is not specified in the DT and as such it
+should not be remapped.
+
+Link: https://lore.kernel.org/r/20211101180243.23761-1-tharvey@gateworks.com
+Fixes: 281f1f99cf3a ("PCI: dwc: Detect number of iATU windows")
+Signed-off-by: Tim Harvey <tharvey@gateworks.com>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Rob Herring <robh@kernel.org>
+Acked-by: Richard Zhu <hongxing.zhu@nxp.com>
+Cc: Richard Zhu <hongxing.zhu@nxp.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/dwc/pcie-designware.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
+index a945f0c0e73dc..3254f60d1713f 100644
+--- a/drivers/pci/controller/dwc/pcie-designware.c
++++ b/drivers/pci/controller/dwc/pcie-designware.c
+@@ -671,10 +671,11 @@ void dw_pcie_iatu_detect(struct dw_pcie *pci)
+               if (!pci->atu_base) {
+                       struct resource *res =
+                               platform_get_resource_byname(pdev, IORESOURCE_MEM, "atu");
+-                      if (res)
++                      if (res) {
+                               pci->atu_size = resource_size(res);
+-                      pci->atu_base = devm_ioremap_resource(dev, res);
+-                      if (IS_ERR(pci->atu_base))
++                              pci->atu_base = devm_ioremap_resource(dev, res);
++                      }
++                      if (!pci->atu_base || IS_ERR(pci->atu_base))
+                               pci->atu_base = pci->dbi_base + DEFAULT_DBI_ATU_OFFSET;
+               }
+-- 
+2.34.1
+
diff --git a/queue-5.15/pci-mediatek-gen3-disable-dvfsrc-voltage-request.patch b/queue-5.15/pci-mediatek-gen3-disable-dvfsrc-voltage-request.patch
new file mode 100644 (file)
index 0000000..5d95307
--- /dev/null
@@ -0,0 +1,59 @@
+From 62d0e01932a8fa42f4df8fc7031d95c567076c95 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Oct 2021 14:36:02 +0800
+Subject: PCI: mediatek-gen3: Disable DVFSRC voltage request
+
+From: Jianjun Wang <jianjun.wang@mediatek.com>
+
+[ Upstream commit ab344fd43f2958726d17d651c0cb692c67dca382 ]
+
+When the DVFSRC (dynamic voltage and frequency scaling resource collector)
+feature is not implemented, the PCIe hardware will assert a voltage request
+signal when exit from the L1 PM Substates to request a specific Vcore
+voltage, but cannot receive the voltage ready signal, which will cause
+the link to fail to exit the L1 PM Substates.
+
+Disable DVFSRC voltage request by default, we need to find a common way to
+enable it in the future.
+
+Link: https://lore.kernel.org/r/20211015063602.29058-1-jianjun.wang@mediatek.com
+Fixes: d3bf75b579b9 ("PCI: mediatek-gen3: Add MediaTek Gen3 driver for MT8192")
+Tested-by: Qizhong Cheng <qizhong.cheng@mediatek.com>
+Signed-off-by: Jianjun Wang <jianjun.wang@mediatek.com>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Tzung-Bi Shih <tzungbi@google.com>
+Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/pcie-mediatek-gen3.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/pci/controller/pcie-mediatek-gen3.c b/drivers/pci/controller/pcie-mediatek-gen3.c
+index 17c59b0d6978b..21207df680ccf 100644
+--- a/drivers/pci/controller/pcie-mediatek-gen3.c
++++ b/drivers/pci/controller/pcie-mediatek-gen3.c
+@@ -79,6 +79,9 @@
+ #define PCIE_ICMD_PM_REG              0x198
+ #define PCIE_TURN_OFF_LINK            BIT(4)
++#define PCIE_MISC_CTRL_REG            0x348
++#define PCIE_DISABLE_DVFSRC_VLT_REQ   BIT(1)
++
+ #define PCIE_TRANS_TABLE_BASE_REG     0x800
+ #define PCIE_ATR_SRC_ADDR_MSB_OFFSET  0x4
+ #define PCIE_ATR_TRSL_ADDR_LSB_OFFSET 0x8
+@@ -297,6 +300,11 @@ static int mtk_pcie_startup_port(struct mtk_pcie_port *port)
+       val &= ~PCIE_INTX_ENABLE;
+       writel_relaxed(val, port->base + PCIE_INT_ENABLE_REG);
++      /* Disable DVFSRC voltage request */
++      val = readl_relaxed(port->base + PCIE_MISC_CTRL_REG);
++      val |= PCIE_DISABLE_DVFSRC_VLT_REQ;
++      writel_relaxed(val, port->base + PCIE_MISC_CTRL_REG);
++
+       /* Assert all reset signals */
+       val = readl_relaxed(port->base + PCIE_RST_CTRL_REG);
+       val |= PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB | PCIE_PE_RSTB;
+-- 
+2.34.1
+
diff --git a/queue-5.15/pci-mvebu-check-for-errors-from-pci_bridge_emul_init.patch b/queue-5.15/pci-mvebu-check-for-errors-from-pci_bridge_emul_init.patch
new file mode 100644 (file)
index 0000000..5c518f3
--- /dev/null
@@ -0,0 +1,68 @@
+From 178def09eba8b9c46f1965f13a1a62f96d8851a6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Nov 2021 13:45:52 +0100
+Subject: PCI: mvebu: Check for errors from pci_bridge_emul_init() call
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+[ Upstream commit 5d18d702e5c9309f4195653475c7a7fdde4ca71f ]
+
+Function pci_bridge_emul_init() may fail so correctly check for errors.
+
+Link: https://lore.kernel.org/r/20211125124605.25915-3-pali@kernel.org
+Fixes: 1f08673eef12 ("PCI: mvebu: Convert to PCI emulated bridge config space")
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/pci-mvebu.c | 15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
+index 2dc6890dbcaa2..f4971fc72a772 100644
+--- a/drivers/pci/controller/pci-mvebu.c
++++ b/drivers/pci/controller/pci-mvebu.c
+@@ -570,7 +570,7 @@ static struct pci_bridge_emul_ops mvebu_pci_bridge_emul_ops = {
+  * Initialize the configuration space of the PCI-to-PCI bridge
+  * associated with the given PCIe interface.
+  */
+-static void mvebu_pci_bridge_emul_init(struct mvebu_pcie_port *port)
++static int mvebu_pci_bridge_emul_init(struct mvebu_pcie_port *port)
+ {
+       struct pci_bridge_emul *bridge = &port->bridge;
+       u32 pcie_cap = mvebu_readl(port, PCIE_CAP_PCIEXP);
+@@ -597,7 +597,7 @@ static void mvebu_pci_bridge_emul_init(struct mvebu_pcie_port *port)
+       bridge->data = port;
+       bridge->ops = &mvebu_pci_bridge_emul_ops;
+-      pci_bridge_emul_init(bridge, PCI_BRIDGE_EMUL_NO_PREFETCHABLE_BAR);
++      return pci_bridge_emul_init(bridge, PCI_BRIDGE_EMUL_NO_PREFETCHABLE_BAR);
+ }
+ static inline struct mvebu_pcie *sys_to_pcie(struct pci_sys_data *sys)
+@@ -1120,9 +1120,18 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
+                       continue;
+               }
++              ret = mvebu_pci_bridge_emul_init(port);
++              if (ret < 0) {
++                      dev_err(dev, "%s: cannot init emulated bridge\n",
++                              port->name);
++                      devm_iounmap(dev, port->base);
++                      port->base = NULL;
++                      mvebu_pcie_powerdown(port);
++                      continue;
++              }
++
+               mvebu_pcie_setup_hw(port);
+               mvebu_pcie_set_local_dev_nr(port, 1);
+-              mvebu_pci_bridge_emul_init(port);
+       }
+       pcie->nports = i;
+-- 
+2.34.1
+
diff --git a/queue-5.15/pci-mvebu-do-not-modify-pci-io-type-bits-in-conf_wri.patch b/queue-5.15/pci-mvebu-do-not-modify-pci-io-type-bits-in-conf_wri.patch
new file mode 100644 (file)
index 0000000..ab7c741
--- /dev/null
@@ -0,0 +1,51 @@
+From 015f57afefad3987a4eee9233cc0dfb1b04301b5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Nov 2021 13:45:57 +0100
+Subject: PCI: mvebu: Do not modify PCI IO type bits in conf_write
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+[ Upstream commit 2cf150216e5b5619d7c25180ccf2cc8ac7bebc13 ]
+
+PCI IO type bits are already initialized in mvebu_pci_bridge_emul_init()
+function and only when IO support is enabled. These type bits are read-only
+and pci-bridge-emul.c code already does not allow to modify them from upper
+layers.
+
+When IO support is disabled then all IO registers should be read-only and
+return zeros. Therefore do not modify PCI IO type bits in
+mvebu_pci_bridge_emul_base_conf_write() callback.
+
+Link: https://lore.kernel.org/r/20211125124605.25915-8-pali@kernel.org
+Fixes: 1f08673eef12 ("PCI: mvebu: Convert to PCI emulated bridge config space")
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/pci-mvebu.c | 7 -------
+ 1 file changed, 7 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
+index f4971fc72a772..5d5f23b1d355b 100644
+--- a/drivers/pci/controller/pci-mvebu.c
++++ b/drivers/pci/controller/pci-mvebu.c
+@@ -497,13 +497,6 @@ mvebu_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge,
+       }
+       case PCI_IO_BASE:
+-              /*
+-               * We keep bit 1 set, it is a read-only bit that
+-               * indicates we support 32 bits addressing for the
+-               * I/O
+-               */
+-              conf->iobase |= PCI_IO_RANGE_TYPE_32;
+-              conf->iolimit |= PCI_IO_RANGE_TYPE_32;
+               mvebu_pcie_handle_iobase_change(port);
+               break;
+-- 
+2.34.1
+
diff --git a/queue-5.15/pci-mvebu-fix-configuring-secondary-bus-of-pcie-root.patch b/queue-5.15/pci-mvebu-fix-configuring-secondary-bus-of-pcie-root.patch
new file mode 100644 (file)
index 0000000..74a4db0
--- /dev/null
@@ -0,0 +1,178 @@
+From c9d78dd383d16577ce4e7d6b784b9246ca965ce6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Nov 2021 13:46:01 +0100
+Subject: PCI: mvebu: Fix configuring secondary bus of PCIe Root Port via
+ emulated bridge
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+[ Upstream commit 91a8d79fc797d3486ae978beebdfc55261c7d65b ]
+
+It looks like that mvebu PCIe controller has for each PCIe link fully
+independent PCIe host bridge and so every PCIe Root Port is isolated not
+only on its own bus but also isolated from each others. But in past device
+tree structure was defined to put all PCIe Root Ports (as PCI Bridge
+devices) into one root bus 0 and this bus is emulated by pci-mvebu.c
+driver.
+
+Probably reason for this decision was incorrect understanding of PCIe
+topology of these Armada SoCs and also reason of misunderstanding how is
+PCIe controller generating Type 0 and Type 1 config requests (it is fully
+different compared to other drivers). Probably incorrect setup leaded to
+very surprised things like having PCIe Root Port (PCI Bridge device, with
+even incorrect Device Class set to Memory Controller) and the PCIe device
+behind the Root Port on the same PCI bus, which obviously was needed to
+somehow hack (as these two devices cannot be in reality on the same bus).
+
+Properly set mvebu local bus number and mvebu local device number based on
+PCI Bridge secondary bus number configuration. Also correctly report
+configured secondary bus number in config space. And explain in driver
+comment why this setup is correct.
+
+Link: https://lore.kernel.org/r/20211125124605.25915-12-pali@kernel.org
+Fixes: 1f08673eef12 ("PCI: mvebu: Convert to PCI emulated bridge config space")
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/pci-mvebu.c | 99 +++++++++++++++++++++++++++++-
+ 1 file changed, 97 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
+index 2e69455400288..76f35d0773b79 100644
+--- a/drivers/pci/controller/pci-mvebu.c
++++ b/drivers/pci/controller/pci-mvebu.c
+@@ -125,6 +125,11 @@ static bool mvebu_pcie_link_up(struct mvebu_pcie_port *port)
+       return !(mvebu_readl(port, PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN);
+ }
++static u8 mvebu_pcie_get_local_bus_nr(struct mvebu_pcie_port *port)
++{
++      return (mvebu_readl(port, PCIE_STAT_OFF) & PCIE_STAT_BUS) >> 8;
++}
++
+ static void mvebu_pcie_set_local_bus_nr(struct mvebu_pcie_port *port, int nr)
+ {
+       u32 stat;
+@@ -437,6 +442,20 @@ mvebu_pci_bridge_emul_base_conf_read(struct pci_bridge_emul *bridge,
+               *value = mvebu_readl(port, PCIE_CMD_OFF);
+               break;
++      case PCI_PRIMARY_BUS: {
++              /*
++               * From the whole 32bit register we support reading from HW only
++               * secondary bus number which is mvebu local bus number.
++               * Other bits are retrieved only from emulated config buffer.
++               */
++              __le32 *cfgspace = (__le32 *)&bridge->conf;
++              u32 val = le32_to_cpu(cfgspace[PCI_PRIMARY_BUS / 4]);
++              val &= ~0xff00;
++              val |= mvebu_pcie_get_local_bus_nr(port) << 8;
++              *value = val;
++              break;
++      }
++
+       default:
+               return PCI_BRIDGE_EMUL_NOT_HANDLED;
+       }
+@@ -520,7 +539,8 @@ mvebu_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge,
+               break;
+       case PCI_PRIMARY_BUS:
+-              mvebu_pcie_set_local_bus_nr(port, conf->secondary_bus);
++              if (mask & 0xff00)
++                      mvebu_pcie_set_local_bus_nr(port, conf->secondary_bus);
+               break;
+       default:
+@@ -1135,8 +1155,83 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
+                       continue;
+               }
++              /*
++               * PCIe topology exported by mvebu hw is quite complicated. In
++               * reality has something like N fully independent host bridges
++               * where each host bridge has one PCIe Root Port (which acts as
++               * PCI Bridge device). Each host bridge has its own independent
++               * internal registers, independent access to PCI config space,
++               * independent interrupt lines, independent window and memory
++               * access configuration. But additionally there is some kind of
++               * peer-to-peer support between PCIe devices behind different
++               * host bridges limited just to forwarding of memory and I/O
++               * transactions (forwarding of error messages and config cycles
++               * is not supported). So we could say there are N independent
++               * PCIe Root Complexes.
++               *
++               * For this kind of setup DT should have been structured into
++               * N independent PCIe controllers / host bridges. But instead
++               * structure in past was defined to put PCIe Root Ports of all
++               * host bridges into one bus zero, like in classic multi-port
++               * Root Complex setup with just one host bridge.
++               *
++               * This means that pci-mvebu.c driver provides "virtual" bus 0
++               * on which registers all PCIe Root Ports (PCI Bridge devices)
++               * specified in DT by their BDF addresses and virtually routes
++               * PCI config access of each PCI bridge device to specific PCIe
++               * host bridge.
++               *
++               * Normally PCI Bridge should choose between Type 0 and Type 1
++               * config requests based on primary and secondary bus numbers
++               * configured on the bridge itself. But because mvebu PCI Bridge
++               * does not have registers for primary and secondary bus numbers
++               * in its config space, it determinates type of config requests
++               * via its own custom way.
++               *
++               * There are two options how mvebu determinate type of config
++               * request.
++               *
++               * 1. If Secondary Bus Number Enable bit is not set or is not
++               * available (applies for pre-XP PCIe controllers) then Type 0
++               * is used if target bus number equals Local Bus Number (bits
++               * [15:8] in register 0x1a04) and target device number differs
++               * from Local Device Number (bits [20:16] in register 0x1a04).
++               * Type 1 is used if target bus number differs from Local Bus
++               * Number. And when target bus number equals Local Bus Number
++               * and target device equals Local Device Number then request is
++               * routed to Local PCI Bridge (PCIe Root Port).
++               *
++               * 2. If Secondary Bus Number Enable bit is set (bit 7 in
++               * register 0x1a2c) then mvebu hw determinate type of config
++               * request like compliant PCI Bridge based on primary bus number
++               * which is configured via Local Bus Number (bits [15:8] in
++               * register 0x1a04) and secondary bus number which is configured
++               * via Secondary Bus Number (bits [7:0] in register 0x1a2c).
++               * Local PCI Bridge (PCIe Root Port) is available on primary bus
++               * as device with Local Device Number (bits [20:16] in register
++               * 0x1a04).
++               *
++               * Secondary Bus Number Enable bit is disabled by default and
++               * option 2. is not available on pre-XP PCIe controllers. Hence
++               * this driver always use option 1.
++               *
++               * Basically it means that primary and secondary buses shares
++               * one virtual number configured via Local Bus Number bits and
++               * Local Device Number bits determinates if accessing primary
++               * or secondary bus. Set Local Device Number to 1 and redirect
++               * all writes of PCI Bridge Secondary Bus Number register to
++               * Local Bus Number (bits [15:8] in register 0x1a04).
++               *
++               * So when accessing devices on buses behind secondary bus
++               * number it would work correctly. And also when accessing
++               * device 0 at secondary bus number via config space would be
++               * correctly routed to secondary bus. Due to issues described
++               * in mvebu_pcie_setup_hw(), PCI Bridges at primary bus (zero)
++               * are not accessed directly via PCI config space but rarher
++               * indirectly via kernel emulated PCI bridge driver.
++               */
+               mvebu_pcie_setup_hw(port);
+-              mvebu_pcie_set_local_dev_nr(port, 1);
++              mvebu_pcie_set_local_dev_nr(port, 0);
+       }
+       pcie->nports = i;
+-- 
+2.34.1
+
diff --git a/queue-5.15/pci-mvebu-fix-device-enumeration-regression.patch b/queue-5.15/pci-mvebu-fix-device-enumeration-regression.patch
new file mode 100644 (file)
index 0000000..b240bd4
--- /dev/null
@@ -0,0 +1,54 @@
+From cab752723e0ebbff90a251a9321da6dd9de87b15 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Feb 2022 12:02:28 +0100
+Subject: PCI: mvebu: Fix device enumeration regression
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+[ Upstream commit c49ae619905eebd3f54598a84e4cd2bd58ba8fe9 ]
+
+Jan reported that on Turris Omnia (Armada 385), no PCIe devices were
+detected after upgrading from v5.16.1 to v5.16.3 and identified the cause
+as the backport of 91a8d79fc797 ("PCI: mvebu: Fix configuring secondary bus
+of PCIe Root Port via emulated bridge"), which appeared in v5.17-rc1.
+
+91a8d79fc797 was incorrectly applied from mailing list patch [1] to the
+linux git repository [2] probably due to resolving merge conflicts
+incorrectly. Fix it now.
+
+[1] https://lore.kernel.org/r/20211125124605.25915-12-pali@kernel.org
+[2] https://git.kernel.org/linus/91a8d79fc797
+
+[bhelgaas: commit log]
+BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=215540
+Fixes: 91a8d79fc797 ("PCI: mvebu: Fix configuring secondary bus of PCIe Root Port via emulated bridge")
+Link: https://lore.kernel.org/r/20220214110228.25825-1-pali@kernel.org
+Link: https://lore.kernel.org/r/20220127234917.GA150851@bhelgaas
+Reported-by: Jan Palus <jpalus@fastmail.com>
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/pci-mvebu.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
+index 357e9a293edf7..2a3bf82aa4e26 100644
+--- a/drivers/pci/controller/pci-mvebu.c
++++ b/drivers/pci/controller/pci-mvebu.c
+@@ -1288,7 +1288,8 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
+                * indirectly via kernel emulated PCI bridge driver.
+                */
+               mvebu_pcie_setup_hw(port);
+-              mvebu_pcie_set_local_dev_nr(port, 0);
++              mvebu_pcie_set_local_dev_nr(port, 1);
++              mvebu_pcie_set_local_bus_nr(port, 0);
+       }
+       pcie->nports = i;
+-- 
+2.34.1
+
diff --git a/queue-5.15/pci-mvebu-fix-support-for-bus-mastering-and-pci_comm.patch b/queue-5.15/pci-mvebu-fix-support-for-bus-mastering-and-pci_comm.patch
new file mode 100644 (file)
index 0000000..c3da179
--- /dev/null
@@ -0,0 +1,139 @@
+From c1cd69bad5e26cfa593e3dd2b0951a5a6757dbf7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Nov 2021 13:45:56 +0100
+Subject: PCI: mvebu: Fix support for bus mastering and PCI_COMMAND on emulated
+ bridge
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+[ Upstream commit e42b85583719adb87ab88dc7bcd41b38011f7d11 ]
+
+According to PCI specifications bits [0:2] of Command Register, this should
+be by default disabled on reset. So explicitly disable these bits at early
+beginning of driver initialization.
+
+Also remove code which unconditionally enables all 3 bits and let kernel
+code (via pci_set_master() function) to handle bus mastering of PCI Bridge
+via emulated PCI_COMMAND on emulated bridge.
+
+Adjust existing functions mvebu_pcie_handle_iobase_change() and
+mvebu_pcie_handle_membase_change() to handle PCI_IO_BASE and PCI_MEM_BASE
+registers correctly even when bus mastering on emulated bridge is disabled.
+
+Link: https://lore.kernel.org/r/20211125124605.25915-7-pali@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/pci-mvebu.c | 52 ++++++++++++++++++------------
+ 1 file changed, 32 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
+index 5d5f23b1d355b..2e69455400288 100644
+--- a/drivers/pci/controller/pci-mvebu.c
++++ b/drivers/pci/controller/pci-mvebu.c
+@@ -215,16 +215,14 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
+ {
+       u32 cmd, mask;
+-      /* Point PCIe unit MBUS decode windows to DRAM space. */
+-      mvebu_pcie_setup_wins(port);
+-
+-      /* Master + slave enable. */
++      /* Disable Root Bridge I/O space, memory space and bus mastering. */
+       cmd = mvebu_readl(port, PCIE_CMD_OFF);
+-      cmd |= PCI_COMMAND_IO;
+-      cmd |= PCI_COMMAND_MEMORY;
+-      cmd |= PCI_COMMAND_MASTER;
++      cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+       mvebu_writel(port, cmd, PCIE_CMD_OFF);
++      /* Point PCIe unit MBUS decode windows to DRAM space. */
++      mvebu_pcie_setup_wins(port);
++
+       /* Enable interrupt lines A-D. */
+       mask = mvebu_readl(port, PCIE_MASK_OFF);
+       mask |= PCIE_MASK_ENABLE_INTS;
+@@ -371,8 +369,7 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
+       /* Are the new iobase/iolimit values invalid? */
+       if (conf->iolimit < conf->iobase ||
+-          conf->iolimitupper < conf->iobaseupper ||
+-          !(conf->command & PCI_COMMAND_IO)) {
++          conf->iolimitupper < conf->iobaseupper) {
+               mvebu_pcie_set_window(port, port->io_target, port->io_attr,
+                                     &desired, &port->iowin);
+               return;
+@@ -409,8 +406,7 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
+       struct pci_bridge_emul_conf *conf = &port->bridge.conf;
+       /* Are the new membase/memlimit values invalid? */
+-      if (conf->memlimit < conf->membase ||
+-          !(conf->command & PCI_COMMAND_MEMORY)) {
++      if (conf->memlimit < conf->membase) {
+               mvebu_pcie_set_window(port, port->mem_target, port->mem_attr,
+                                     &desired, &port->memwin);
+               return;
+@@ -430,6 +426,24 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
+                             &port->memwin);
+ }
++static pci_bridge_emul_read_status_t
++mvebu_pci_bridge_emul_base_conf_read(struct pci_bridge_emul *bridge,
++                                   int reg, u32 *value)
++{
++      struct mvebu_pcie_port *port = bridge->data;
++
++      switch (reg) {
++      case PCI_COMMAND:
++              *value = mvebu_readl(port, PCIE_CMD_OFF);
++              break;
++
++      default:
++              return PCI_BRIDGE_EMUL_NOT_HANDLED;
++      }
++
++      return PCI_BRIDGE_EMUL_HANDLED;
++}
++
+ static pci_bridge_emul_read_status_t
+ mvebu_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
+                                    int reg, u32 *value)
+@@ -484,17 +498,14 @@ mvebu_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge,
+       switch (reg) {
+       case PCI_COMMAND:
+-      {
+-              if (!mvebu_has_ioport(port))
+-                      conf->command &= ~PCI_COMMAND_IO;
+-
+-              if ((old ^ new) & PCI_COMMAND_IO)
+-                      mvebu_pcie_handle_iobase_change(port);
+-              if ((old ^ new) & PCI_COMMAND_MEMORY)
+-                      mvebu_pcie_handle_membase_change(port);
++              if (!mvebu_has_ioport(port)) {
++                      conf->command = cpu_to_le16(
++                              le16_to_cpu(conf->command) & ~PCI_COMMAND_IO);
++                      new &= ~PCI_COMMAND_IO;
++              }
++              mvebu_writel(port, new, PCIE_CMD_OFF);
+               break;
+-      }
+       case PCI_IO_BASE:
+               mvebu_pcie_handle_iobase_change(port);
+@@ -554,6 +565,7 @@ mvebu_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,
+ }
+ static struct pci_bridge_emul_ops mvebu_pci_bridge_emul_ops = {
++      .read_base = mvebu_pci_bridge_emul_base_conf_read,
+       .write_base = mvebu_pci_bridge_emul_base_conf_write,
+       .read_pcie = mvebu_pci_bridge_emul_pcie_conf_read,
+       .write_pcie = mvebu_pci_bridge_emul_pcie_conf_write,
+-- 
+2.34.1
+
diff --git a/queue-5.15/pci-mvebu-fix-support-for-devcap2-devctl2-and-lnkctl.patch b/queue-5.15/pci-mvebu-fix-support-for-devcap2-devctl2-and-lnkctl.patch
new file mode 100644 (file)
index 0000000..5ac4c2b
--- /dev/null
@@ -0,0 +1,72 @@
+From 3f0266995f3f4cab2d36e5211a27f52dfda9dc69 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Nov 2021 13:46:05 +0100
+Subject: PCI: mvebu: Fix support for DEVCAP2, DEVCTL2 and LNKCTL2 registers on
+ emulated bridge
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+[ Upstream commit 4ab34548c55fbbb3898306a47dfaccd4860e1ccb ]
+
+Armada XP and new hardware supports access to DEVCAP2, DEVCTL2 and LNKCTL2
+configuration registers of PCIe core via PCIE_CAP_PCIEXP. So export them
+via emulated software root bridge.
+
+Pre-XP hardware does not support these registers and returns zeros.
+
+Link: https://lore.kernel.org/r/20211125124605.25915-16-pali@kernel.org
+Fixes: 1f08673eef12 ("PCI: mvebu: Convert to PCI emulated bridge config space")
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/pci-mvebu.c | 23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+
+diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
+index b690768d5a413..357e9a293edf7 100644
+--- a/drivers/pci/controller/pci-mvebu.c
++++ b/drivers/pci/controller/pci-mvebu.c
+@@ -524,6 +524,18 @@ mvebu_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
+               *value = mvebu_readl(port, PCIE_RC_RTSTA);
+               break;
++      case PCI_EXP_DEVCAP2:
++              *value = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_DEVCAP2);
++              break;
++
++      case PCI_EXP_DEVCTL2:
++              *value = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_DEVCTL2);
++              break;
++
++      case PCI_EXP_LNKCTL2:
++              *value = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_LNKCTL2);
++              break;
++
+       default:
+               return PCI_BRIDGE_EMUL_NOT_HANDLED;
+       }
+@@ -615,6 +627,17 @@ mvebu_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,
+               if (new & PCI_EXP_RTSTA_PME)
+                       mvebu_writel(port, ~PCIE_INT_PM_PME, PCIE_INT_CAUSE_OFF);
+               break;
++
++      case PCI_EXP_DEVCTL2:
++              mvebu_writel(port, new, PCIE_CAP_PCIEXP + PCI_EXP_DEVCTL2);
++              break;
++
++      case PCI_EXP_LNKCTL2:
++              mvebu_writel(port, new, PCIE_CAP_PCIEXP + PCI_EXP_LNKCTL2);
++              break;
++
++      default:
++              break;
+       }
+ }
+-- 
+2.34.1
+
diff --git a/queue-5.15/pci-mvebu-fix-support-for-pci_bridge_ctl_bus_reset-o.patch b/queue-5.15/pci-mvebu-fix-support-for-pci_bridge_ctl_bus_reset-o.patch
new file mode 100644 (file)
index 0000000..cfe07c9
--- /dev/null
@@ -0,0 +1,85 @@
+From 56821d5f9eb0c346487dd3ee17db4e0a90a79cd7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Nov 2021 13:46:02 +0100
+Subject: PCI: mvebu: Fix support for PCI_BRIDGE_CTL_BUS_RESET on emulated
+ bridge
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+[ Upstream commit d75404cc08832206f173668bd35391c581fea121 ]
+
+Hardware supports PCIe Hot Reset via PCIE_CTRL_OFF register. Use it for
+implementing PCI_BRIDGE_CTL_BUS_RESET bit of PCI_BRIDGE_CONTROL register on
+emulated bridge.
+
+With this change the function pci_reset_secondary_bus() starts working and
+can reset connected PCIe card.
+
+Link: https://lore.kernel.org/r/20211125124605.25915-13-pali@kernel.org
+Fixes: 1f08673eef12 ("PCI: mvebu: Convert to PCI emulated bridge config space")
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/pci-mvebu.c | 28 ++++++++++++++++++++++++++++
+ 1 file changed, 28 insertions(+)
+
+diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
+index e2d4bd8442a80..3563301e772ae 100644
+--- a/drivers/pci/controller/pci-mvebu.c
++++ b/drivers/pci/controller/pci-mvebu.c
+@@ -56,6 +56,7 @@
+ #define PCIE_CTRL_OFF         0x1a00
+ #define  PCIE_CTRL_X1_MODE            0x0001
+ #define  PCIE_CTRL_RC_MODE            BIT(1)
++#define  PCIE_CTRL_MASTER_HOT_RESET   BIT(24)
+ #define PCIE_STAT_OFF         0x1a04
+ #define  PCIE_STAT_BUS                  0xff00
+ #define  PCIE_STAT_DEV                  0x1f0000
+@@ -462,6 +463,22 @@ mvebu_pci_bridge_emul_base_conf_read(struct pci_bridge_emul *bridge,
+               break;
+       }
++      case PCI_INTERRUPT_LINE: {
++              /*
++               * From the whole 32bit register we support reading from HW only
++               * one bit: PCI_BRIDGE_CTL_BUS_RESET.
++               * Other bits are retrieved only from emulated config buffer.
++               */
++              __le32 *cfgspace = (__le32 *)&bridge->conf;
++              u32 val = le32_to_cpu(cfgspace[PCI_INTERRUPT_LINE / 4]);
++              if (mvebu_readl(port, PCIE_CTRL_OFF) & PCIE_CTRL_MASTER_HOT_RESET)
++                      val |= PCI_BRIDGE_CTL_BUS_RESET << 16;
++              else
++                      val &= ~(PCI_BRIDGE_CTL_BUS_RESET << 16);
++              *value = val;
++              break;
++      }
++
+       default:
+               return PCI_BRIDGE_EMUL_NOT_HANDLED;
+       }
+@@ -549,6 +566,17 @@ mvebu_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge,
+                       mvebu_pcie_set_local_bus_nr(port, conf->secondary_bus);
+               break;
++      case PCI_INTERRUPT_LINE:
++              if (mask & (PCI_BRIDGE_CTL_BUS_RESET << 16)) {
++                      u32 ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
++                      if (new & (PCI_BRIDGE_CTL_BUS_RESET << 16))
++                              ctrl |= PCIE_CTRL_MASTER_HOT_RESET;
++                      else
++                              ctrl &= ~PCIE_CTRL_MASTER_HOT_RESET;
++                      mvebu_writel(port, ctrl, PCIE_CTRL_OFF);
++              }
++              break;
++
+       default:
+               break;
+       }
+-- 
+2.34.1
+
diff --git a/queue-5.15/pci-mvebu-fix-support-for-pci_exp_devctl-on-emulated.patch b/queue-5.15/pci-mvebu-fix-support-for-pci_exp_devctl-on-emulated.patch
new file mode 100644 (file)
index 0000000..5a0173c
--- /dev/null
@@ -0,0 +1,57 @@
+From e8364538eda6dfec69915ff903c7cb944a35b3ec Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Nov 2021 13:46:03 +0100
+Subject: PCI: mvebu: Fix support for PCI_EXP_DEVCTL on emulated bridge
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+[ Upstream commit ecae073e393e65ee7be7ebf3fdd5258ab99f1636 ]
+
+Comment in Armada 370 functional specification is misleading.
+PCI_EXP_DEVCTL_*RE bits are supported and configures receiving of error
+interrupts.
+
+Link: https://lore.kernel.org/r/20211125124605.25915-14-pali@kernel.org
+Fixes: 1f08673eef12 ("PCI: mvebu: Convert to PCI emulated bridge config space")
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/pci-mvebu.c | 11 +----------
+ 1 file changed, 1 insertion(+), 10 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
+index 3563301e772ae..6100608e6413e 100644
+--- a/drivers/pci/controller/pci-mvebu.c
++++ b/drivers/pci/controller/pci-mvebu.c
+@@ -498,9 +498,7 @@ mvebu_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
+               break;
+       case PCI_EXP_DEVCTL:
+-              *value = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_DEVCTL) &
+-                               ~(PCI_EXP_DEVCTL_URRE | PCI_EXP_DEVCTL_FERE |
+-                                 PCI_EXP_DEVCTL_NFERE | PCI_EXP_DEVCTL_CERE);
++              *value = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_DEVCTL);
+               break;
+       case PCI_EXP_LNKCAP:
+@@ -590,13 +588,6 @@ mvebu_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,
+       switch (reg) {
+       case PCI_EXP_DEVCTL:
+-              /*
+-               * Armada370 data says these bits must always
+-               * be zero when in root complex mode.
+-               */
+-              new &= ~(PCI_EXP_DEVCTL_URRE | PCI_EXP_DEVCTL_FERE |
+-                       PCI_EXP_DEVCTL_NFERE | PCI_EXP_DEVCTL_CERE);
+-
+               mvebu_writel(port, new, PCIE_CAP_PCIEXP + PCI_EXP_DEVCTL);
+               break;
+-- 
+2.34.1
+
diff --git a/queue-5.15/pci-mvebu-fix-support-for-pci_exp_rtsta-on-emulated-.patch b/queue-5.15/pci-mvebu-fix-support-for-pci_exp_rtsta-on-emulated-.patch
new file mode 100644 (file)
index 0000000..9e08b5a
--- /dev/null
@@ -0,0 +1,57 @@
+From 6d8289c482bed6356d99847dd4a9c9d5333dcfe6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Nov 2021 13:46:04 +0100
+Subject: PCI: mvebu: Fix support for PCI_EXP_RTSTA on emulated bridge
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+[ Upstream commit 838ff44a398ff47fe9b924961d91aee325821220 ]
+
+PME Status bit in Root Status Register (PCIE_RC_RTSTA_OFF) is read-only and
+can be cleared only by writing 0b to the Interrupt Cause RW0C register
+(PCIE_INT_CAUSE_OFF).
+
+Link: https://lore.kernel.org/r/20211125124605.25915-15-pali@kernel.org
+Fixes: 1f08673eef12 ("PCI: mvebu: Convert to PCI emulated bridge config space")
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/pci-mvebu.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
+index 6100608e6413e..b690768d5a413 100644
+--- a/drivers/pci/controller/pci-mvebu.c
++++ b/drivers/pci/controller/pci-mvebu.c
+@@ -51,6 +51,8 @@
+        PCIE_CONF_FUNC(PCI_FUNC(devfn)) | PCIE_CONF_REG(where) | \
+        PCIE_CONF_ADDR_EN)
+ #define PCIE_CONF_DATA_OFF    0x18fc
++#define PCIE_INT_CAUSE_OFF    0x1900
++#define  PCIE_INT_PM_PME              BIT(28)
+ #define PCIE_MASK_OFF         0x1910
+ #define  PCIE_MASK_ENABLE_INTS          0x0f000000
+ #define PCIE_CTRL_OFF         0x1a00
+@@ -604,7 +606,14 @@ mvebu_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,
+               break;
+       case PCI_EXP_RTSTA:
+-              mvebu_writel(port, new, PCIE_RC_RTSTA);
++              /*
++               * PME Status bit in Root Status Register (PCIE_RC_RTSTA)
++               * is read-only and can be cleared only by writing 0b to the
++               * Interrupt Cause RW0C register (PCIE_INT_CAUSE_OFF). So
++               * clear PME via Interrupt Cause.
++               */
++              if (new & PCI_EXP_RTSTA_PME)
++                      mvebu_writel(port, ~PCIE_INT_PM_PME, PCIE_INT_CAUSE_OFF);
+               break;
+       }
+ }
+-- 
+2.34.1
+
diff --git a/queue-5.15/pci-mvebu-setup-pcie-controller-to-root-complex-mode.patch b/queue-5.15/pci-mvebu-setup-pcie-controller-to-root-complex-mode.patch
new file mode 100644 (file)
index 0000000..7bcbf94
--- /dev/null
@@ -0,0 +1,52 @@
+From c5e9291e77d095617cf854eb997495ab25fb7032 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Nov 2021 13:45:59 +0100
+Subject: PCI: mvebu: Setup PCIe controller to Root Complex mode
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+[ Upstream commit df08ac016124bd88b8598ac0599d7b89c0642774 ]
+
+This driver operates only in Root Complex mode, so ensure that hardware is
+properly configured in Root Complex mode.
+
+Link: https://lore.kernel.org/r/20211125124605.25915-10-pali@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/pci-mvebu.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
+index 76f35d0773b79..e2d4bd8442a80 100644
+--- a/drivers/pci/controller/pci-mvebu.c
++++ b/drivers/pci/controller/pci-mvebu.c
+@@ -55,6 +55,7 @@
+ #define  PCIE_MASK_ENABLE_INTS          0x0f000000
+ #define PCIE_CTRL_OFF         0x1a00
+ #define  PCIE_CTRL_X1_MODE            0x0001
++#define  PCIE_CTRL_RC_MODE            BIT(1)
+ #define PCIE_STAT_OFF         0x1a04
+ #define  PCIE_STAT_BUS                  0xff00
+ #define  PCIE_STAT_DEV                  0x1f0000
+@@ -218,7 +219,12 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
+ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
+ {
+-      u32 cmd, mask;
++      u32 ctrl, cmd, mask;
++
++      /* Setup PCIe controller to Root Complex mode. */
++      ctrl = mvebu_readl(port, PCIE_CTRL_OFF);
++      ctrl |= PCIE_CTRL_RC_MODE;
++      mvebu_writel(port, ctrl, PCIE_CTRL_OFF);
+       /* Disable Root Bridge I/O space, memory space and bus mastering. */
+       cmd = mvebu_readl(port, PCIE_CMD_OFF);
+-- 
+2.34.1
+
diff --git a/queue-5.15/pci-rcar-check-if-device-is-runtime-suspended-instea.patch b/queue-5.15/pci-rcar-check-if-device-is-runtime-suspended-instea.patch
new file mode 100644 (file)
index 0000000..13ff854
--- /dev/null
@@ -0,0 +1,74 @@
+From 425dfa4266c95b8e8d978a8a6f5c78859da268b6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Nov 2021 21:46:41 +0100
+Subject: PCI: rcar: Check if device is runtime suspended instead of
+ __clk_is_enabled()
+
+From: Marek Vasut <marek.vasut+renesas@gmail.com>
+
+[ Upstream commit d2a14b54989e9ccea8401895fdfbc213bd1f56af ]
+
+Replace __clk_is_enabled() with pm_runtime_suspended(),
+as __clk_is_enabled() was checking the wrong bus clock
+and caused the following build error too:
+  arm-linux-gnueabi-ld: drivers/pci/controller/pcie-rcar-host.o: in function `rcar_pcie_aarch32_abort_handler':
+  pcie-rcar-host.c:(.text+0xdd0): undefined reference to `__clk_is_enabled'
+
+Link: https://lore.kernel.org/r/20211115204641.12941-1-marek.vasut@gmail.com
+Fixes: a115b1bd3af0 ("PCI: rcar: Add L1 link state fix into data abort hook")
+Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Acked-by: Randy Dunlap <rdunlap@infradead.org>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+Cc: Geert Uytterhoeven <geert+renesas@glider.be>
+Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: Stephen Boyd <sboyd@kernel.org>
+Cc: Wolfram Sang <wsa@the-dreams.de>
+Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Cc: linux-renesas-soc@vger.kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/pcie-rcar-host.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/pci/controller/pcie-rcar-host.c b/drivers/pci/controller/pcie-rcar-host.c
+index 8f3131844e777..bfb13f358d073 100644
+--- a/drivers/pci/controller/pcie-rcar-host.c
++++ b/drivers/pci/controller/pcie-rcar-host.c
+@@ -52,10 +52,10 @@ struct rcar_msi {
+  */
+ static void __iomem *pcie_base;
+ /*
+- * Static copy of bus clock pointer, so we can check whether the clock
+- * is enabled or not.
++ * Static copy of PCIe device pointer, so we can check whether the
++ * device is runtime suspended or not.
+  */
+-static struct clk *pcie_bus_clk;
++static struct device *pcie_dev;
+ #endif
+ /* Structure representing the PCIe interface */
+@@ -794,7 +794,7 @@ static int rcar_pcie_get_resources(struct rcar_pcie_host *host)
+ #ifdef CONFIG_ARM
+       /* Cache static copy for L1 link state fixup hook on aarch32 */
+       pcie_base = pcie->base;
+-      pcie_bus_clk = host->bus_clk;
++      pcie_dev = pcie->dev;
+ #endif
+       return 0;
+@@ -1064,7 +1064,7 @@ static int rcar_pcie_aarch32_abort_handler(unsigned long addr,
+       spin_lock_irqsave(&pmsr_lock, flags);
+-      if (!pcie_base || !__clk_is_enabled(pcie_bus_clk)) {
++      if (!pcie_base || pm_runtime_suspended(pcie_dev)) {
+               ret = 1;
+               goto unlock_exit;
+       }
+-- 
+2.34.1
+
diff --git a/queue-5.15/revert-nfsd-skip-some-unnecessary-stats-in-the-v4-ca.patch b/queue-5.15/revert-nfsd-skip-some-unnecessary-stats-in-the-v4-ca.patch
new file mode 100644 (file)
index 0000000..faf09b8
--- /dev/null
@@ -0,0 +1,141 @@
+From 734fdfab434e21dd26ca2555ca1866732e62c3ae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Dec 2021 14:22:28 -0500
+Subject: Revert "nfsd: skip some unnecessary stats in the v4 case"
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 58f258f65267542959487dbe8b5641754411843d ]
+
+On the wire, I observed NFSv4 OPEN(CREATE) operations sometimes
+returning a reasonable-looking value in the cinfo.before field and
+zero in the cinfo.after field.
+
+RFC 8881 Section 10.8.1 says:
+> When a client is making changes to a given directory, it needs to
+> determine whether there have been changes made to the directory by
+> other clients.  It does this by using the change attribute as
+> reported before and after the directory operation in the associated
+> change_info4 value returned for the operation.
+
+and
+
+> ... The post-operation change
+> value needs to be saved as the basis for future change_info4
+> comparisons.
+
+A good quality client implementation therefore saves the zero
+cinfo.after value. During a subsequent OPEN operation, it will
+receive a different non-zero value in the cinfo.before field for
+that directory, and it will incorrectly believe the directory has
+changed, triggering an undesirable directory cache invalidation.
+
+There are filesystem types where fs_supports_change_attribute()
+returns false, tmpfs being one. On NFSv4 mounts, this means the
+fh_getattr() call site in fill_pre_wcc() and fill_post_wcc() is
+never invoked. Subsequently, nfsd4_change_attribute() is invoked
+with an uninitialized @stat argument.
+
+In fill_pre_wcc(), @stat contains stale stack garbage, which is
+then placed on the wire. In fill_post_wcc(), ->fh_post_wc is all
+zeroes, so zero is placed on the wire. Both of these values are
+meaningless.
+
+This fix can be applied immediately to stable kernels. Once there
+are more regression tests in this area, this optimization can be
+attempted again.
+
+Fixes: 428a23d2bf0c ("nfsd: skip some unnecessary stats in the v4 case")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfsd/nfs3xdr.c | 44 +++++++++++++++++---------------------------
+ 1 file changed, 17 insertions(+), 27 deletions(-)
+
+diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
+index 0ee156b9c9d71..48d4f99b7f901 100644
+--- a/fs/nfsd/nfs3xdr.c
++++ b/fs/nfsd/nfs3xdr.c
+@@ -487,11 +487,6 @@ svcxdr_encode_wcc_data(struct svc_rqst *rqstp, struct xdr_stream *xdr,
+       return true;
+ }
+-static bool fs_supports_change_attribute(struct super_block *sb)
+-{
+-      return sb->s_flags & SB_I_VERSION || sb->s_export_op->fetch_iversion;
+-}
+-
+ /*
+  * Fill in the pre_op attr for the wcc data
+  */
+@@ -500,26 +495,24 @@ void fill_pre_wcc(struct svc_fh *fhp)
+       struct inode    *inode;
+       struct kstat    stat;
+       bool v4 = (fhp->fh_maxsize == NFS4_FHSIZE);
++      __be32 err;
+       if (fhp->fh_no_wcc || fhp->fh_pre_saved)
+               return;
+       inode = d_inode(fhp->fh_dentry);
+-      if (fs_supports_change_attribute(inode->i_sb) || !v4) {
+-              __be32 err = fh_getattr(fhp, &stat);
+-
+-              if (err) {
+-                      /* Grab the times from inode anyway */
+-                      stat.mtime = inode->i_mtime;
+-                      stat.ctime = inode->i_ctime;
+-                      stat.size  = inode->i_size;
+-              }
+-              fhp->fh_pre_mtime = stat.mtime;
+-              fhp->fh_pre_ctime = stat.ctime;
+-              fhp->fh_pre_size  = stat.size;
++      err = fh_getattr(fhp, &stat);
++      if (err) {
++              /* Grab the times from inode anyway */
++              stat.mtime = inode->i_mtime;
++              stat.ctime = inode->i_ctime;
++              stat.size  = inode->i_size;
+       }
+       if (v4)
+               fhp->fh_pre_change = nfsd4_change_attribute(&stat, inode);
++      fhp->fh_pre_mtime = stat.mtime;
++      fhp->fh_pre_ctime = stat.ctime;
++      fhp->fh_pre_size  = stat.size;
+       fhp->fh_pre_saved = true;
+ }
+@@ -530,6 +523,7 @@ void fill_post_wcc(struct svc_fh *fhp)
+ {
+       bool v4 = (fhp->fh_maxsize == NFS4_FHSIZE);
+       struct inode *inode = d_inode(fhp->fh_dentry);
++      __be32 err;
+       if (fhp->fh_no_wcc)
+               return;
+@@ -537,16 +531,12 @@ void fill_post_wcc(struct svc_fh *fhp)
+       if (fhp->fh_post_saved)
+               printk("nfsd: inode locked twice during operation.\n");
+-      fhp->fh_post_saved = true;
+-
+-      if (fs_supports_change_attribute(inode->i_sb) || !v4) {
+-              __be32 err = fh_getattr(fhp, &fhp->fh_post_attr);
+-
+-              if (err) {
+-                      fhp->fh_post_saved = false;
+-                      fhp->fh_post_attr.ctime = inode->i_ctime;
+-              }
+-      }
++      err = fh_getattr(fhp, &fhp->fh_post_attr);
++      if (err) {
++              fhp->fh_post_saved = false;
++              fhp->fh_post_attr.ctime = inode->i_ctime;
++      } else
++              fhp->fh_post_saved = true;
+       if (v4)
+               fhp->fh_post_change =
+                       nfsd4_change_attribute(&fhp->fh_post_attr, inode);
+-- 
+2.34.1
+
diff --git a/queue-5.15/riscv-mm-add-xip_fixup-for-phys_ram_base.patch b/queue-5.15/riscv-mm-add-xip_fixup-for-phys_ram_base.patch
new file mode 100644 (file)
index 0000000..69e8356
--- /dev/null
@@ -0,0 +1,36 @@
+From 1e9ce2f8c6f2a297421032201a14f3051b1509ec Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Feb 2022 13:13:37 -0800
+Subject: riscv/mm: Add XIP_FIXUP for phys_ram_base
+
+From: Palmer Dabbelt <palmer@rivosinc.com>
+
+[ Upstream commit 4b1c70aa8ed8249608bb991380cb8ff423edf49e ]
+
+This manifests as a crash early in boot on VexRiscv.
+
+Signed-off-by: Myrtle Shah <gatecat@ds0.me>
+[Palmer: split commit]
+Fixes: 6d7f91d914bc ("riscv: Get rid of CONFIG_PHYS_RAM_BASE in kernel physical address conversion")
+Cc: stable@vger.kernel.org
+Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/riscv/mm/init.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
+index 5e7decd875258..3de593b26850e 100644
+--- a/arch/riscv/mm/init.c
++++ b/arch/riscv/mm/init.c
+@@ -451,6 +451,7 @@ static uintptr_t __init best_map_size(phys_addr_t base, phys_addr_t size)
+ }
+ #ifdef CONFIG_XIP_KERNEL
++#define phys_ram_base  (*(phys_addr_t *)XIP_FIXUP(&phys_ram_base))
+ /* called from head.S with MMU off */
+ asmlinkage void __init __copy_data(void)
+ {
+-- 
+2.34.1
+
diff --git a/queue-5.15/selftests-vm-make-charge_reserved_hugetlb.sh-work-wi.patch b/queue-5.15/selftests-vm-make-charge_reserved_hugetlb.sh-work-wi.patch
new file mode 100644 (file)
index 0000000..1965037
--- /dev/null
@@ -0,0 +1,165 @@
+From 70fa62e465eafb27d1c50b411a8ef74a7eff2c27 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Jan 2022 14:07:58 -0800
+Subject: selftests/vm: make charge_reserved_hugetlb.sh work with existing
+ cgroup setting
+
+From: Waiman Long <longman@redhat.com>
+
+[ Upstream commit 209376ed2a8431ccb4c40fdcef11194fc1e749b0 ]
+
+The hugetlb cgroup reservation test charge_reserved_hugetlb.sh assume
+that no cgroup filesystems are mounted before running the test.  That is
+not true in many cases.  As a result, the test fails to run.  Fix that
+by querying the current cgroup mount setting and using the existing
+cgroup setup instead before attempting to freshly mount a cgroup
+filesystem.
+
+Similar change is also made for hugetlb_reparenting_test.sh as well,
+though it still has problem if cgroup v2 isn't used.
+
+The patched test scripts were run on a centos 8 based system to verify
+that they ran properly.
+
+Link: https://lkml.kernel.org/r/20220106201359.1646575-1-longman@redhat.com
+Fixes: 29750f71a9b4 ("hugetlb_cgroup: add hugetlb_cgroup reservation tests")
+Signed-off-by: Waiman Long <longman@redhat.com>
+Acked-by: Mina Almasry <almasrymina@google.com>
+Cc: Shuah Khan <shuah@kernel.org>
+Cc: Mike Kravetz <mike.kravetz@oracle.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../selftests/vm/charge_reserved_hugetlb.sh   | 34 +++++++++++--------
+ .../selftests/vm/hugetlb_reparenting_test.sh  | 21 +++++++-----
+ .../selftests/vm/write_hugetlb_memory.sh      |  2 +-
+ 3 files changed, 34 insertions(+), 23 deletions(-)
+
+diff --git a/tools/testing/selftests/vm/charge_reserved_hugetlb.sh b/tools/testing/selftests/vm/charge_reserved_hugetlb.sh
+index fe8fcfb334e06..a5cb4b09a46c4 100644
+--- a/tools/testing/selftests/vm/charge_reserved_hugetlb.sh
++++ b/tools/testing/selftests/vm/charge_reserved_hugetlb.sh
+@@ -24,19 +24,23 @@ if [[ "$1" == "-cgroup-v2" ]]; then
+   reservation_usage_file=rsvd.current
+ fi
+-cgroup_path=/dev/cgroup/memory
+-if [[ ! -e $cgroup_path ]]; then
+-  mkdir -p $cgroup_path
+-  if [[ $cgroup2 ]]; then
++if [[ $cgroup2 ]]; then
++  cgroup_path=$(mount -t cgroup2 | head -1 | awk -e '{print $3}')
++  if [[ -z "$cgroup_path" ]]; then
++    cgroup_path=/dev/cgroup/memory
+     mount -t cgroup2 none $cgroup_path
+-  else
++    do_umount=1
++  fi
++  echo "+hugetlb" >$cgroup_path/cgroup.subtree_control
++else
++  cgroup_path=$(mount -t cgroup | grep ",hugetlb" | awk -e '{print $3}')
++  if [[ -z "$cgroup_path" ]]; then
++    cgroup_path=/dev/cgroup/memory
+     mount -t cgroup memory,hugetlb $cgroup_path
++    do_umount=1
+   fi
+ fi
+-
+-if [[ $cgroup2 ]]; then
+-  echo "+hugetlb" >/dev/cgroup/memory/cgroup.subtree_control
+-fi
++export cgroup_path
+ function cleanup() {
+   if [[ $cgroup2 ]]; then
+@@ -108,7 +112,7 @@ function setup_cgroup() {
+ function wait_for_hugetlb_memory_to_get_depleted() {
+   local cgroup="$1"
+-  local path="/dev/cgroup/memory/$cgroup/hugetlb.${MB}MB.$reservation_usage_file"
++  local path="$cgroup_path/$cgroup/hugetlb.${MB}MB.$reservation_usage_file"
+   # Wait for hugetlbfs memory to get depleted.
+   while [ $(cat $path) != 0 ]; do
+     echo Waiting for hugetlb memory to get depleted.
+@@ -121,7 +125,7 @@ function wait_for_hugetlb_memory_to_get_reserved() {
+   local cgroup="$1"
+   local size="$2"
+-  local path="/dev/cgroup/memory/$cgroup/hugetlb.${MB}MB.$reservation_usage_file"
++  local path="$cgroup_path/$cgroup/hugetlb.${MB}MB.$reservation_usage_file"
+   # Wait for hugetlbfs memory to get written.
+   while [ $(cat $path) != $size ]; do
+     echo Waiting for hugetlb memory reservation to reach size $size.
+@@ -134,7 +138,7 @@ function wait_for_hugetlb_memory_to_get_written() {
+   local cgroup="$1"
+   local size="$2"
+-  local path="/dev/cgroup/memory/$cgroup/hugetlb.${MB}MB.$fault_usage_file"
++  local path="$cgroup_path/$cgroup/hugetlb.${MB}MB.$fault_usage_file"
+   # Wait for hugetlbfs memory to get written.
+   while [ $(cat $path) != $size ]; do
+     echo Waiting for hugetlb memory to reach size $size.
+@@ -574,5 +578,7 @@ for populate in "" "-o"; do
+   done     # populate
+ done       # method
+-umount $cgroup_path
+-rmdir $cgroup_path
++if [[ $do_umount ]]; then
++  umount $cgroup_path
++  rmdir $cgroup_path
++fi
+diff --git a/tools/testing/selftests/vm/hugetlb_reparenting_test.sh b/tools/testing/selftests/vm/hugetlb_reparenting_test.sh
+index 4a9a3afe9fd4d..bf2d2a684edfd 100644
+--- a/tools/testing/selftests/vm/hugetlb_reparenting_test.sh
++++ b/tools/testing/selftests/vm/hugetlb_reparenting_test.sh
+@@ -18,19 +18,24 @@ if [[ "$1" == "-cgroup-v2" ]]; then
+   usage_file=current
+ fi
+-CGROUP_ROOT='/dev/cgroup/memory'
+-MNT='/mnt/huge/'
+-if [[ ! -e $CGROUP_ROOT ]]; then
+-  mkdir -p $CGROUP_ROOT
+-  if [[ $cgroup2 ]]; then
++if [[ $cgroup2 ]]; then
++  CGROUP_ROOT=$(mount -t cgroup2 | head -1 | awk -e '{print $3}')
++  if [[ -z "$CGROUP_ROOT" ]]; then
++    CGROUP_ROOT=/dev/cgroup/memory
+     mount -t cgroup2 none $CGROUP_ROOT
+-    sleep 1
+-    echo "+hugetlb +memory" >$CGROUP_ROOT/cgroup.subtree_control
+-  else
++    do_umount=1
++  fi
++  echo "+hugetlb +memory" >$CGROUP_ROOT/cgroup.subtree_control
++else
++  CGROUP_ROOT=$(mount -t cgroup | grep ",hugetlb" | awk -e '{print $3}')
++  if [[ -z "$CGROUP_ROOT" ]]; then
++    CGROUP_ROOT=/dev/cgroup/memory
+     mount -t cgroup memory,hugetlb $CGROUP_ROOT
++    do_umount=1
+   fi
+ fi
++MNT='/mnt/huge/'
+ function get_machine_hugepage_size() {
+   hpz=$(grep -i hugepagesize /proc/meminfo)
+diff --git a/tools/testing/selftests/vm/write_hugetlb_memory.sh b/tools/testing/selftests/vm/write_hugetlb_memory.sh
+index d3d0d108924d4..70a02301f4c27 100644
+--- a/tools/testing/selftests/vm/write_hugetlb_memory.sh
++++ b/tools/testing/selftests/vm/write_hugetlb_memory.sh
+@@ -14,7 +14,7 @@ want_sleep=$8
+ reserve=$9
+ echo "Putting task in cgroup '$cgroup'"
+-echo $$ > /dev/cgroup/memory/"$cgroup"/cgroup.procs
++echo $$ > ${cgroup_path:-/dev/cgroup/memory}/"$cgroup"/cgroup.procs
+ echo "Method is $method"
+-- 
+2.34.1
+
index 00e8d391ad8dc9fb892fd77956413fe24be17b02..adece2a912f2489f6c8d121c4b07b86cabdc36c9 100644 (file)
@@ -40,3 +40,96 @@ ata-pata_hpt37x-fix-pci-clock-detection.patch
 drm-amdgpu-check-vm-ready-by-amdgpu_vm-evicting-flag.patch
 tracing-add-ustring-operation-to-filtering-string-po.patch
 ipv6-fix-skb-drops-in-igmp6_event_query-and-igmp6_ev.patch
+nfsd-have-legacy-nfsd-write-decoders-use-xdr_stream_.patch
+nfsd-fix-zero-length-nfsv3-writes.patch
+io_uring-fix-no-lock-protection-for-ctx-cq_extra.patch
+tools-resolve_btf_ids-close-elf-file-on-error.patch
+mtd-spi-nor-fix-mtd-size-for-s3an-flashes.patch
+bpf-arm64-use-emit_addr_mov_i64-for-bpf_pseudo_func.patch
+mips-fix-local_-add-sub-_return-on-mips64.patch
+signal-in-get_signal-test-for-signal_group_exit-ever.patch
+pci-mediatek-gen3-disable-dvfsrc-voltage-request.patch
+pci-rcar-check-if-device-is-runtime-suspended-instea.patch
+pci-dwc-do-not-remap-invalid-res.patch
+pci-aardvark-fix-checking-for-mem-resource-type.patch
+kvm-vmx-don-t-unblock-vcpu-w-posted-irq-if-irqs-are-.patch
+kvm-s390-ensure-kvm_arch_no_poll-is-read-once-when-b.patch
+kvm-vmx-read-posted-interrupt-control-exactly-once-p.patch
+kvm-x86-ensure-that-dirty-pdptrs-are-loaded.patch
+kvm-x86-handle-32-bit-wrap-of-eip-for-emultype_skip-.patch
+kvm-x86-exit-to-userspace-if-emulation-prepared-a-co.patch
+i3c-fix-incorrect-address-slot-lookup-on-64-bit.patch
+i3c-master-mipi-i3c-hci-fix-a-potentially-infinite-l.patch
+tracing-do-not-let-synth_events-block-other-dyn_even.patch
+input-ti_am335x_tsc-set-adcrefm-for-x-configuration.patch
+input-ti_am335x_tsc-fix-stepconfig-setup-for-z2.patch
+pci-mvebu-check-for-errors-from-pci_bridge_emul_init.patch
+pci-mvebu-do-not-modify-pci-io-type-bits-in-conf_wri.patch
+pci-mvebu-fix-support-for-bus-mastering-and-pci_comm.patch
+pci-mvebu-fix-configuring-secondary-bus-of-pcie-root.patch
+pci-mvebu-setup-pcie-controller-to-root-complex-mode.patch
+pci-mvebu-fix-support-for-pci_bridge_ctl_bus_reset-o.patch
+pci-mvebu-fix-support-for-pci_exp_devctl-on-emulated.patch
+pci-mvebu-fix-support-for-pci_exp_rtsta-on-emulated-.patch
+pci-mvebu-fix-support-for-devcap2-devctl2-and-lnkctl.patch
+nfsd-fix-verifier-returned-in-stable-writes.patch
+revert-nfsd-skip-some-unnecessary-stats-in-the-v4-ca.patch
+nfsd-fix-crash-on-copy_notify-with-special-stateid.patch
+x86-hyperv-properly-deal-with-empty-cpumasks-in-hype.patch
+drm-i915-don-t-call-free_mmap_offset-when-purging.patch
+sunrpc-fix-sockaddr-handling-in-the-svc_xprt_create_.patch
+sunrpc-fix-sockaddr-handling-in-svcsock_accept_class.patch
+drm-sun4i-dw-hdmi-fix-missing-put_device-call-in-sun.patch
+drm-atomic-check-new_crtc_state-active-to-determine-.patch
+ntb_hw_switchtec-fix-pff-ioread-to-read-into-mmio_pa.patch
+ntb_hw_switchtec-fix-bug-with-more-than-32-partition.patch
+drm-amdkfd-check-for-null-pointer-after-calling-kmem.patch
+drm-amdgpu-use-spin_lock_irqsave-to-avoid-deadlock-b.patch
+i3c-master-dw-check-return-of-dw_i3c_master_get_free.patch
+dma-buf-cma_heap-fix-mutex-locking-section.patch
+tracing-uprobes-check-the-return-value-of-kstrdup-fo.patch
+tracing-probes-check-the-return-value-of-kstrndup-fo.patch
+mm-defer-kmemleak-object-creation-of-module_alloc.patch
+kasan-fix-quarantine-conflicting-with-init_on_free.patch
+selftests-vm-make-charge_reserved_hugetlb.sh-work-wi.patch
+hugetlbfs-fix-off-by-one-error-in-hugetlb_vmdelete_l.patch
+drm-amdgpu-display-only-set-vblank_disable_immediate.patch
+drm-amdgpu-filter-out-radeon-pci-device-ids.patch
+drm-amdgpu-filter-out-radeon-secondary-ids-as-well.patch
+drm-amd-display-use-adjusted-dcn301-watermarks.patch
+drm-amd-display-move-fpu-associated-dsc-code-to-dml-.patch
+drm-amd-display-move-fpu-associated-dcn301-code-to-d.patch
+drm-amd-display-wrap-dcn301_calculate_wm_and_dlg-for.patch
+ethtool-fix-link-extended-state-for-big-endian.patch
+octeontx2-af-optimize-kpu1-processing-for-variable-l.patch
+octeontx2-af-reset-ptp-config-in-flr-handler.patch
+octeontx2-af-cn10k-rpm-hardware-timestamp-configurat.patch
+octeontx2-af-cn10k-use-appropriate-register-for-lmac.patch
+octeontx2-af-adjust-la-pointer-for-cpt-parse-header.patch
+octeontx2-af-add-kpu-changes-to-parse-ngio-as-separa.patch
+net-mlx5e-ipsec-refactor-checksum-code-in-tx-data-pa.patch
+net-mlx5e-ipsec-fix-crypto-offload-for-non-tcp-udp-e.patch
+bpf-use-u64_stats_t-in-struct-bpf_prog_stats.patch
+bpf-fix-possible-race-in-inc_misses_counter.patch
+drm-amd-display-update-watermark-values-for-dcn301.patch
+drm-mxsfb-set-fallback-bus-format-when-the-bridge-do.patch
+drm-mxsfb-fix-null-pointer-dereference.patch
+riscv-mm-add-xip_fixup-for-phys_ram_base.patch
+drm-i915-display-split-out-dpt-out-of-intel_display..patch
+drm-i915-display-move-drrs-code-its-own-file.patch
+drm-i915-disable-drrs-on-ivb-hsw-port-a.patch
+drm-i915-workaround-broken-bios-dbuf-configuration-o.patch
+gve-recording-rx-queue-before-sending-to-napi.patch
+net-dsa-ocelot-seville-utilize-of_mdiobus_register.patch
+net-dsa-seville-register-the-mdiobus-under-devres.patch
+ibmvnic-don-t-release-napi-in-__ibmvnic_open.patch
+of-net-move-of_net-under-net.patch
+net-ethernet-litex-add-the-dependency-on-has_iomem.patch
+drm-mediatek-mtk_dsi-reset-the-dsi0-hardware.patch
+drm-mediatek-mtk_dsi-avoid-eprobe_defer-loop-with-ex.patch
+cifs-protect-session-channel-fields-with-chan_lock.patch
+cifs-fix-confusing-unneeded-warning-message-on-smb2..patch
+drm-amd-display-fix-stream-link_enc-unassigned-durin.patch
+bnxt_en-fix-occasional-ethtool-t-loopback-test-failu.patch
+drm-amd-display-for-vblank_disable_immediate-check-p.patch
+pci-mvebu-fix-device-enumeration-regression.patch
diff --git a/queue-5.15/signal-in-get_signal-test-for-signal_group_exit-ever.patch b/queue-5.15/signal-in-get_signal-test-for-signal_group_exit-ever.patch
new file mode 100644 (file)
index 0000000..4aa97ef
--- /dev/null
@@ -0,0 +1,72 @@
+From 9a43fb8534a89e366276e4f0db677e26bcc4381f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Nov 2021 11:55:57 -0600
+Subject: signal: In get_signal test for signal_group_exit every time through
+ the loop
+
+From: Eric W. Biederman <ebiederm@xmission.com>
+
+[ Upstream commit e7f7c99ba911f56bc338845c1cd72954ba591707 ]
+
+Recently while investigating a problem with rr and signals I noticed
+that siglock is dropped in ptrace_signal and get_signal does not jump
+to relock.
+
+Looking farther to see if the problem is anywhere else I see that
+do_signal_stop also returns if signal_group_exit is true.  I believe
+that test can now never be true, but it is a bit hard to trace
+through and be certain.
+
+Testing signal_group_exit is not expensive, so move the test for
+signal_group_exit into the for loop inside of get_signal to ensure
+the test is never skipped improperly.
+
+This has been a potential problem since I added the test for
+signal_group_exit was added.
+
+Fixes: 35634ffa1751 ("signal: Always notice exiting tasks")
+Reviewed-by: Kees Cook <keescook@chromium.org>
+Link: https://lkml.kernel.org/r/875yssekcd.fsf_-_@email.froward.int.ebiederm.org
+Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/signal.c | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/kernel/signal.c b/kernel/signal.c
+index aea93d6a5520a..6e3dbb3d12170 100644
+--- a/kernel/signal.c
++++ b/kernel/signal.c
+@@ -2710,19 +2710,19 @@ bool get_signal(struct ksignal *ksig)
+               goto relock;
+       }
+-      /* Has this task already been marked for death? */
+-      if (signal_group_exit(signal)) {
+-              ksig->info.si_signo = signr = SIGKILL;
+-              sigdelset(&current->pending.signal, SIGKILL);
+-              trace_signal_deliver(SIGKILL, SEND_SIG_NOINFO,
+-                              &sighand->action[SIGKILL - 1]);
+-              recalc_sigpending();
+-              goto fatal;
+-      }
+-
+       for (;;) {
+               struct k_sigaction *ka;
++              /* Has this task already been marked for death? */
++              if (signal_group_exit(signal)) {
++                      ksig->info.si_signo = signr = SIGKILL;
++                      sigdelset(&current->pending.signal, SIGKILL);
++                      trace_signal_deliver(SIGKILL, SEND_SIG_NOINFO,
++                              &sighand->action[SIGKILL - 1]);
++                      recalc_sigpending();
++                      goto fatal;
++              }
++
+               if (unlikely(current->jobctl & JOBCTL_STOP_PENDING) &&
+                   do_signal_stop(0))
+                       goto relock;
+-- 
+2.34.1
+
diff --git a/queue-5.15/sunrpc-fix-sockaddr-handling-in-svcsock_accept_class.patch b/queue-5.15/sunrpc-fix-sockaddr-handling-in-svcsock_accept_class.patch
new file mode 100644 (file)
index 0000000..f86f334
--- /dev/null
@@ -0,0 +1,50 @@
+From a3c493d60861155b19c3e4e058d6bab3bd9e89a5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Jan 2022 16:59:54 -0500
+Subject: SUNRPC: Fix sockaddr handling in svcsock_accept_class trace points
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 16720861675393a35974532b3c837d9fd7bfe08c ]
+
+Avoid potentially hazardous memory copying and the needless use of
+"%pIS" -- in the kernel, an RPC service listener is always bound to
+ANYADDR. Having the network namespace is helpful when recording
+errors, though.
+
+Fixes: a0469f46faab ("SUNRPC: Replace dprintk call sites in TCP state change callouts")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/trace/events/sunrpc.h | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h
+index 1213c078dcca5..7c48613c18304 100644
+--- a/include/trace/events/sunrpc.h
++++ b/include/trace/events/sunrpc.h
+@@ -2112,17 +2112,17 @@ DECLARE_EVENT_CLASS(svcsock_accept_class,
+       TP_STRUCT__entry(
+               __field(long, status)
+               __string(service, service)
+-              __array(unsigned char, addr, sizeof(struct sockaddr_in6))
++              __field(unsigned int, netns_ino)
+       ),
+       TP_fast_assign(
+               __entry->status = status;
+               __assign_str(service, service);
+-              memcpy(__entry->addr, &xprt->xpt_local, sizeof(__entry->addr));
++              __entry->netns_ino = xprt->xpt_net->ns.inum;
+       ),
+-      TP_printk("listener=%pISpc service=%s status=%ld",
+-              __entry->addr, __get_str(service), __entry->status
++      TP_printk("addr=listener service=%s status=%ld",
++              __get_str(service), __entry->status
+       )
+ );
+-- 
+2.34.1
+
diff --git a/queue-5.15/sunrpc-fix-sockaddr-handling-in-the-svc_xprt_create_.patch b/queue-5.15/sunrpc-fix-sockaddr-handling-in-the-svc_xprt_create_.patch
new file mode 100644 (file)
index 0000000..b9171d6
--- /dev/null
@@ -0,0 +1,86 @@
+From 4a24e50d596d171764ca86ffc50b289f786fcf49 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 9 Jan 2022 13:26:51 -0500
+Subject: SUNRPC: Fix sockaddr handling in the svc_xprt_create_error trace
+ point
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit dc6c6fb3d639756a532bcc47d4a9bf9f3965881b ]
+
+While testing, I got an unexpected KASAN splat:
+
+Jan 08 13:50:27 oracle-102.nfsv4.dev kernel: BUG: KASAN: stack-out-of-bounds in trace_event_raw_event_svc_xprt_create_err+0x190/0x210 [sunrpc]
+Jan 08 13:50:27 oracle-102.nfsv4.dev kernel: Read of size 28 at addr ffffc9000008f728 by task mount.nfs/4628
+
+The memcpy() in the TP_fast_assign section of this trace point
+copies the size of the destination buffer in order that the buffer
+won't be overrun.
+
+In other similar trace points, the source buffer for this memcpy is
+a "struct sockaddr_storage" so the actual length of the source
+buffer is always long enough to prevent the memcpy from reading
+uninitialized or unallocated memory.
+
+However, for this trace point, the source buffer can be as small as
+a "struct sockaddr_in". For AF_INET sockaddrs, the memcpy() reads
+memory that follows the source buffer, which is not always valid
+memory.
+
+To avoid copying past the end of the passed-in sockaddr, make the
+source address's length available to the memcpy(). It would be a
+little nicer if the tracing infrastructure was more friendly about
+storing socket addresses that are not AF_INET, but I could not find
+a way to make printk("%pIS") work with a dynamic array.
+
+Reported-by: KASAN
+Fixes: 4b8f380e46e4 ("SUNRPC: Tracepoint to record errors in svc_xpo_create()")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/trace/events/sunrpc.h | 5 +++--
+ net/sunrpc/svc_xprt.c         | 2 +-
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h
+index daaf407e9e494..1213c078dcca5 100644
+--- a/include/trace/events/sunrpc.h
++++ b/include/trace/events/sunrpc.h
+@@ -1727,10 +1727,11 @@ TRACE_EVENT(svc_xprt_create_err,
+               const char *program,
+               const char *protocol,
+               struct sockaddr *sap,
++              size_t salen,
+               const struct svc_xprt *xprt
+       ),
+-      TP_ARGS(program, protocol, sap, xprt),
++      TP_ARGS(program, protocol, sap, salen, xprt),
+       TP_STRUCT__entry(
+               __field(long, error)
+@@ -1743,7 +1744,7 @@ TRACE_EVENT(svc_xprt_create_err,
+               __entry->error = PTR_ERR(xprt);
+               __assign_str(program, program);
+               __assign_str(protocol, protocol);
+-              memcpy(__entry->addr, sap, sizeof(__entry->addr));
++              memcpy(__entry->addr, sap, min(salen, sizeof(__entry->addr)));
+       ),
+       TP_printk("addr=%pISpc program=%s protocol=%s error=%ld",
+diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
+index 6316bd2b8f37b..d4b663401be14 100644
+--- a/net/sunrpc/svc_xprt.c
++++ b/net/sunrpc/svc_xprt.c
+@@ -243,7 +243,7 @@ static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl,
+       xprt = xcl->xcl_ops->xpo_create(serv, net, sap, len, flags);
+       if (IS_ERR(xprt))
+               trace_svc_xprt_create_err(serv->sv_program->pg_name,
+-                                        xcl->xcl_name, sap, xprt);
++                                        xcl->xcl_name, sap, len, xprt);
+       return xprt;
+ }
+-- 
+2.34.1
+
diff --git a/queue-5.15/tools-resolve_btf_ids-close-elf-file-on-error.patch b/queue-5.15/tools-resolve_btf_ids-close-elf-file-on-error.patch
new file mode 100644 (file)
index 0000000..9fc317c
--- /dev/null
@@ -0,0 +1,46 @@
+From a49a2ca69a0401a0d8b0ae8ffec12b00497be3f1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 23 Nov 2021 16:23:13 -0800
+Subject: tools/resolve_btf_ids: Close ELF file on error
+
+From: Andrii Nakryiko <andrii@kernel.org>
+
+[ Upstream commit 1144ab9bdf3430e1b5b3f22741e5283841951add ]
+
+Fix one case where we don't do explicit clean up.
+
+Fixes: fbbb68de80a4 ("bpf: Add resolve_btfids tool to resolve BTF IDs in ELF object")
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Link: https://lore.kernel.org/bpf/20211124002325.1737739-2-andrii@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/bpf/resolve_btfids/main.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/tools/bpf/resolve_btfids/main.c b/tools/bpf/resolve_btfids/main.c
+index de6365b53c9ca..45e0d640618ac 100644
+--- a/tools/bpf/resolve_btfids/main.c
++++ b/tools/bpf/resolve_btfids/main.c
+@@ -166,7 +166,7 @@ static struct btf_id *btf_id__find(struct rb_root *root, const char *name)
+       return NULL;
+ }
+-static struct btf_id*
++static struct btf_id *
+ btf_id__add(struct rb_root *root, char *name, bool unique)
+ {
+       struct rb_node **p = &root->rb_node;
+@@ -720,7 +720,8 @@ int main(int argc, const char **argv)
+               if (no_fail)
+                       return 0;
+               pr_err("FAILED to find needed sections\n");
+-              return -1;
++              err = 0;
++              goto out;
+       }
+       if (symbols_collect(&obj))
+-- 
+2.34.1
+
diff --git a/queue-5.15/tracing-do-not-let-synth_events-block-other-dyn_even.patch b/queue-5.15/tracing-do-not-let-synth_events-block-other-dyn_even.patch
new file mode 100644 (file)
index 0000000..609f47a
--- /dev/null
@@ -0,0 +1,60 @@
+From 9c608dfc3f117e01e7f09aac60f58fb724c40c3b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Sep 2021 15:38:21 -0700
+Subject: tracing: Do not let synth_events block other dyn_event systems during
+ create
+
+From: Beau Belgrave <beaub@linux.microsoft.com>
+
+[ Upstream commit 4f67cca70c0f615e9cfe6ac42244f3416ec60877 ]
+
+synth_events is returning -EINVAL if the dyn_event create command does
+not contain ' \t'. This prevents other systems from getting called back.
+synth_events needs to return -ECANCELED in these cases when the command
+is not targeting the synth_event system.
+
+Link: https://lore.kernel.org/linux-trace-devel/20210930223821.11025-1-beaub@linux.microsoft.com
+
+Fixes: c9e759b1e8456 ("tracing: Rework synthetic event command parsing")
+Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org>
+Signed-off-by: Beau Belgrave <beaub@linux.microsoft.com>
+Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/trace/trace_events_synth.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/kernel/trace/trace_events_synth.c b/kernel/trace/trace_events_synth.c
+index 22db3ce95e74f..8c26092db8dee 100644
+--- a/kernel/trace/trace_events_synth.c
++++ b/kernel/trace/trace_events_synth.c
+@@ -2053,6 +2053,13 @@ static int create_synth_event(const char *raw_command)
+       last_cmd_set(raw_command);
++      name = raw_command;
++
++      /* Don't try to process if not our system */
++      if (name[0] != 's' || name[1] != ':')
++              return -ECANCELED;
++      name += 2;
++
+       p = strpbrk(raw_command, " \t");
+       if (!p) {
+               synth_err(SYNTH_ERR_INVALID_CMD, 0);
+@@ -2061,12 +2068,6 @@ static int create_synth_event(const char *raw_command)
+       fields = skip_spaces(p);
+-      name = raw_command;
+-
+-      if (name[0] != 's' || name[1] != ':')
+-              return -ECANCELED;
+-      name += 2;
+-
+       /* This interface accepts group name prefix */
+       if (strchr(name, '/')) {
+               len = str_has_prefix(name, SYNTH_SYSTEM "/");
+-- 
+2.34.1
+
diff --git a/queue-5.15/tracing-probes-check-the-return-value-of-kstrndup-fo.patch b/queue-5.15/tracing-probes-check-the-return-value-of-kstrndup-fo.patch
new file mode 100644 (file)
index 0000000..d0acf26
--- /dev/null
@@ -0,0 +1,40 @@
+From 64c4015f91558604095df1e75eefd70bcf37cc6b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Dec 2021 10:26:46 +0800
+Subject: tracing/probes: check the return value of kstrndup() for pbuf
+
+From: Xiaoke Wang <xkernel.wang@foxmail.com>
+
+[ Upstream commit 1c1857d400355e96f0fe8b32adc6fa7594d03b52 ]
+
+kstrndup() is a memory allocation-related function, it returns NULL when
+some internal memory errors happen. It is better to check the return
+value of it so to catch the memory error in time.
+
+Link: https://lkml.kernel.org/r/tencent_4D6E270731456EB88712ED7F13883C334906@qq.com
+
+Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
+Fixes: a42e3c4de964 ("tracing/probe: Add immediate string parameter support")
+Signed-off-by: Xiaoke Wang <xkernel.wang@foxmail.com>
+Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/trace/trace_probe.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c
+index 3ed2a3f372972..bb4605b60de79 100644
+--- a/kernel/trace/trace_probe.c
++++ b/kernel/trace/trace_probe.c
+@@ -356,6 +356,8 @@ static int __parse_imm_string(char *str, char **pbuf, int offs)
+               return -EINVAL;
+       }
+       *pbuf = kstrndup(str, len - 1, GFP_KERNEL);
++      if (!*pbuf)
++              return -ENOMEM;
+       return 0;
+ }
+-- 
+2.34.1
+
diff --git a/queue-5.15/tracing-uprobes-check-the-return-value-of-kstrdup-fo.patch b/queue-5.15/tracing-uprobes-check-the-return-value-of-kstrdup-fo.patch
new file mode 100644 (file)
index 0000000..aa74d00
--- /dev/null
@@ -0,0 +1,43 @@
+From ac0ec9e7013ce804238e9dfbb81ec708b0d918e5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Dec 2021 09:28:02 +0800
+Subject: tracing/uprobes: Check the return value of kstrdup() for tu->filename
+
+From: Xiaoke Wang <xkernel.wang@foxmail.com>
+
+[ Upstream commit 8c7224245557707c613f130431cafbaaa4889615 ]
+
+kstrdup() returns NULL when some internal memory errors happen, it is
+better to check the return value of it so to catch the memory error in
+time.
+
+Link: https://lkml.kernel.org/r/tencent_3C2E330722056D7891D2C83F29C802734B06@qq.com
+
+Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
+Fixes: 33ea4b24277b ("perf/core: Implement the 'perf_uprobe' PMU")
+Signed-off-by: Xiaoke Wang <xkernel.wang@foxmail.com>
+Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/trace/trace_uprobe.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
+index f5f0039d31e5a..78ec1c16ccf4b 100644
+--- a/kernel/trace/trace_uprobe.c
++++ b/kernel/trace/trace_uprobe.c
+@@ -1619,6 +1619,11 @@ create_local_trace_uprobe(char *name, unsigned long offs,
+       tu->path = path;
+       tu->ref_ctr_offset = ref_ctr_offset;
+       tu->filename = kstrdup(name, GFP_KERNEL);
++      if (!tu->filename) {
++              ret = -ENOMEM;
++              goto error;
++      }
++
+       init_trace_event_call(tu);
+       ptype = is_ret_probe(tu) ? PROBE_PRINT_RETURN : PROBE_PRINT_NORMAL;
+-- 
+2.34.1
+
diff --git a/queue-5.15/x86-hyperv-properly-deal-with-empty-cpumasks-in-hype.patch b/queue-5.15/x86-hyperv-properly-deal-with-empty-cpumasks-in-hype.patch
new file mode 100644 (file)
index 0000000..c1be206
--- /dev/null
@@ -0,0 +1,141 @@
+From a06817129afef53ebfa4ce59b9eb25fa74f343ef Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Jan 2022 10:46:11 +0100
+Subject: x86/hyperv: Properly deal with empty cpumasks in
+ hyperv_flush_tlb_multi()
+
+From: Vitaly Kuznetsov <vkuznets@redhat.com>
+
+[ Upstream commit 51500b71d500f251037ed339047a4d9e7d7e295b ]
+
+KASAN detected the following issue:
+
+ BUG: KASAN: slab-out-of-bounds in hyperv_flush_tlb_multi+0xf88/0x1060
+ Read of size 4 at addr ffff8880011ccbc0 by task kcompactd0/33
+
+ CPU: 1 PID: 33 Comm: kcompactd0 Not tainted 5.14.0-39.el9.x86_64+debug #1
+ Hardware name: Microsoft Corporation Virtual Machine/Virtual Machine,
+     BIOS Hyper-V UEFI Release v4.0 12/17/2019
+ Call Trace:
+  dump_stack_lvl+0x57/0x7d
+  print_address_description.constprop.0+0x1f/0x140
+  ? hyperv_flush_tlb_multi+0xf88/0x1060
+  __kasan_report.cold+0x7f/0x11e
+  ? hyperv_flush_tlb_multi+0xf88/0x1060
+  kasan_report+0x38/0x50
+  hyperv_flush_tlb_multi+0xf88/0x1060
+  flush_tlb_mm_range+0x1b1/0x200
+  ptep_clear_flush+0x10e/0x150
+...
+ Allocated by task 0:
+  kasan_save_stack+0x1b/0x40
+  __kasan_kmalloc+0x7c/0x90
+  hv_common_init+0xae/0x115
+  hyperv_init+0x97/0x501
+  apic_intr_mode_init+0xb3/0x1e0
+  x86_late_time_init+0x92/0xa2
+  start_kernel+0x338/0x3eb
+  secondary_startup_64_no_verify+0xc2/0xcb
+
+ The buggy address belongs to the object at ffff8880011cc800
+  which belongs to the cache kmalloc-1k of size 1024
+ The buggy address is located 960 bytes inside of
+  1024-byte region [ffff8880011cc800, ffff8880011ccc00)
+
+'hyperv_flush_tlb_multi+0xf88/0x1060' points to
+hv_cpu_number_to_vp_number() and '960 bytes' means we're trying to get
+VP_INDEX for CPU#240. 'nr_cpus' here is exactly 240 so we're trying to
+access past hv_vp_index's last element. This can (and will) happen
+when 'cpus' mask is empty and cpumask_last() will return '>=nr_cpus'.
+
+Commit ad0a6bad4475 ("x86/hyperv: check cpu mask after interrupt has
+been disabled") tried to deal with empty cpumask situation but
+apparently didn't fully fix the issue.
+
+'cpus' cpumask which is passed to hyperv_flush_tlb_multi() is
+'mm_cpumask(mm)' (which is '&mm->cpu_bitmap'). This mask changes every
+time the particular mm is scheduled/unscheduled on some CPU (see
+switch_mm_irqs_off()), disabling IRQs on the CPU which is performing remote
+TLB flush has zero influence on whether the particular process can get
+scheduled/unscheduled on _other_ CPUs so e.g. in the case where the mm was
+scheduled on one other CPU and got unscheduled during
+hyperv_flush_tlb_multi()'s execution will lead to cpumask becoming empty.
+
+It doesn't seem that there's a good way to protect 'mm_cpumask(mm)'
+from changing during hyperv_flush_tlb_multi()'s execution. It would be
+possible to copy it in the very beginning of the function but this is a
+waste. It seems we can deal with changing cpumask just fine.
+
+When 'cpus' cpumask changes during hyperv_flush_tlb_multi()'s
+execution, there are two possible issues:
+- 'Under-flushing': we will not flush TLB on a CPU which got added to
+the mask while hyperv_flush_tlb_multi() was already running. This is
+not a problem as this is equal to mm getting scheduled on that CPU
+right after TLB flush.
+- 'Over-flushing': we may flush TLB on a CPU which is already cleared
+from the mask. First, extra TLB flush preserves correctness. Second,
+Hyper-V's TLB flush hypercall takes 'mm->pgd' argument so Hyper-V may
+avoid the flush if CR3 doesn't match.
+
+Fix the immediate issue with cpumask_last()/hv_cpu_number_to_vp_number()
+and remove the pointless cpumask_empty() check from the beginning of the
+function as it really doesn't protect anything. Also, avoid the hypercall
+altogether when 'flush->processor_mask' ends up being empty.
+
+Fixes: ad0a6bad4475 ("x86/hyperv: check cpu mask after interrupt has been disabled")
+Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
+Reviewed-by: Michael Kelley <mikelley@microsoft.com>
+Link: https://lore.kernel.org/r/20220106094611.1404218-1-vkuznets@redhat.com
+Signed-off-by: Wei Liu <wei.liu@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/hyperv/mmu.c | 19 +++++++++----------
+ 1 file changed, 9 insertions(+), 10 deletions(-)
+
+diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c
+index bd13736d0c054..0ad2378fe6ad7 100644
+--- a/arch/x86/hyperv/mmu.c
++++ b/arch/x86/hyperv/mmu.c
+@@ -68,15 +68,6 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus,
+       local_irq_save(flags);
+-      /*
+-       * Only check the mask _after_ interrupt has been disabled to avoid the
+-       * mask changing under our feet.
+-       */
+-      if (cpumask_empty(cpus)) {
+-              local_irq_restore(flags);
+-              return;
+-      }
+-
+       flush_pcpu = (struct hv_tlb_flush **)
+                    this_cpu_ptr(hyperv_pcpu_input_arg);
+@@ -115,7 +106,9 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus,
+                * must. We will also check all VP numbers when walking the
+                * supplied CPU set to remain correct in all cases.
+                */
+-              if (hv_cpu_number_to_vp_number(cpumask_last(cpus)) >= 64)
++              cpu = cpumask_last(cpus);
++
++              if (cpu < nr_cpumask_bits && hv_cpu_number_to_vp_number(cpu) >= 64)
+                       goto do_ex_hypercall;
+               for_each_cpu(cpu, cpus) {
+@@ -131,6 +124,12 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus,
+                       __set_bit(vcpu, (unsigned long *)
+                                 &flush->processor_mask);
+               }
++
++              /* nothing to flush if 'processor_mask' ends up being empty */
++              if (!flush->processor_mask) {
++                      local_irq_restore(flags);
++                      return;
++              }
+       }
+       /*
+-- 
+2.34.1
+