]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.15
authorSasha Levin <sashal@kernel.org>
Sun, 4 Dec 2022 02:26:49 +0000 (21:26 -0500)
committerSasha Levin <sashal@kernel.org>
Sun, 4 Dec 2022 02:26:49 +0000 (21:26 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
21 files changed:
queue-5.15/asoc-ops-fix-bounds-check-for-_sx-controls.patch [new file with mode: 0644]
queue-5.15/iommu-vt-d-fix-pci-device-refcount-leak-in-dmar_dev_.patch [new file with mode: 0644]
queue-5.15/iommu-vt-d-fix-pci-device-refcount-leak-in-has_exter.patch [new file with mode: 0644]
queue-5.15/ipv4-fix-route-deletion-when-nexthop-info-is-not-spe.patch [new file with mode: 0644]
queue-5.15/ipv4-handle-attempt-to-delete-multipath-route-when-f.patch [new file with mode: 0644]
queue-5.15/kconfig.debug-provide-a-little-extra-frame_warn-leew.patch [new file with mode: 0644]
queue-5.15/mm-__isolate_lru_page_prepare-in-isolate_migratepage.patch [new file with mode: 0644]
queue-5.15/mm-migrate-fix-thp-s-mapcount-on-isolation.patch [new file with mode: 0644]
queue-5.15/nvme-fix-srcu-protection-of-nvme_ns_head-list.patch [new file with mode: 0644]
queue-5.15/parisc-increase-frame_warn-to-2048-bytes-on-parisc.patch [new file with mode: 0644]
queue-5.15/pinctrl-single-fix-potential-division-by-zero.patch [new file with mode: 0644]
queue-5.15/riscv-fix-race-when-vmap-stack-overflow.patch [new file with mode: 0644]
queue-5.15/riscv-kexec-fixup-crash_smp_send_stop-without-multi-.patch [new file with mode: 0644]
queue-5.15/riscv-kexec-fixup-irq-controller-broken-in-kexec-cra.patch [new file with mode: 0644]
queue-5.15/riscv-sync-efi-page-table-s-kernel-mappings-before-s.patch [new file with mode: 0644]
queue-5.15/selftests-net-add-delete-nexthop-route-warning-test.patch [new file with mode: 0644]
queue-5.15/selftests-net-fix-nexthop-warning-cleanup-double-ip-.patch [new file with mode: 0644]
queue-5.15/serial-stm32-deassert-transmit-enable-on-rs485_confi.patch [new file with mode: 0644]
queue-5.15/serial-stm32-factor-out-gpio-rts-toggling-into-separ.patch [new file with mode: 0644]
queue-5.15/serial-stm32-use-tc-interrupt-to-deassert-gpio-rts-i.patch [new file with mode: 0644]
queue-5.15/series

diff --git a/queue-5.15/asoc-ops-fix-bounds-check-for-_sx-controls.patch b/queue-5.15/asoc-ops-fix-bounds-check-for-_sx-controls.patch
new file mode 100644 (file)
index 0000000..647a8a3
--- /dev/null
@@ -0,0 +1,39 @@
+From fe0bc28b7cf4f765ad2632f0f5947bfc10444c46 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 May 2022 14:41:36 +0100
+Subject: ASoC: ops: Fix bounds check for _sx controls
+
+From: Mark Brown <broonie@kernel.org>
+
+[ Upstream commit 698813ba8c580efb356ace8dbf55f61dac6063a8 ]
+
+For _sx controls the semantics of the max field is not the usual one, max
+is the number of steps rather than the maximum value. This means that our
+check in snd_soc_put_volsw_sx() needs to just check against the maximum
+value.
+
+Fixes: 4f1e50d6a9cf9c1b ("ASoC: ops: Reject out of bounds values in snd_soc_put_volsw_sx()")
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Link: https://lore.kernel.org/r/20220511134137.169575-1-broonie@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/soc-ops.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c
+index e73360e9de8f..b8a169d3b830 100644
+--- a/sound/soc/soc-ops.c
++++ b/sound/soc/soc-ops.c
+@@ -433,7 +433,7 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
+       val = ucontrol->value.integer.value[0];
+       if (mc->platform_max && val > mc->platform_max)
+               return -EINVAL;
+-      if (val > max - min)
++      if (val > max)
+               return -EINVAL;
+       if (val < 0)
+               return -EINVAL;
+-- 
+2.35.1
+
diff --git a/queue-5.15/iommu-vt-d-fix-pci-device-refcount-leak-in-dmar_dev_.patch b/queue-5.15/iommu-vt-d-fix-pci-device-refcount-leak-in-dmar_dev_.patch
new file mode 100644 (file)
index 0000000..e0e26f7
--- /dev/null
@@ -0,0 +1,43 @@
+From 4855387092177c8f95cc4e1976f74f6f82d690b1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Dec 2022 12:01:27 +0800
+Subject: iommu/vt-d: Fix PCI device refcount leak in dmar_dev_scope_init()
+
+From: Xiongfeng Wang <wangxiongfeng2@huawei.com>
+
+[ Upstream commit 4bedbbd782ebbe7287231fea862c158d4f08a9e3 ]
+
+for_each_pci_dev() is implemented by pci_get_device(). The comment of
+pci_get_device() says that it will increase the reference count for the
+returned pci_dev and also decrease the reference count for the input
+pci_dev @from if it is not NULL.
+
+If we break for_each_pci_dev() loop with pdev not NULL, we need to call
+pci_dev_put() to decrease the reference count. Add the missing
+pci_dev_put() for the error path to avoid reference count leak.
+
+Fixes: 2e4552893038 ("iommu/vt-d: Unify the way to process DMAR device scope array")
+Signed-off-by: Xiongfeng Wang <wangxiongfeng2@huawei.com>
+Link: https://lore.kernel.org/r/20221121113649.190393-3-wangxiongfeng2@huawei.com
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/intel/dmar.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
+index f026bd269cb0..bff2420fc3e1 100644
+--- a/drivers/iommu/intel/dmar.c
++++ b/drivers/iommu/intel/dmar.c
+@@ -822,6 +822,7 @@ int __init dmar_dev_scope_init(void)
+                       info = dmar_alloc_pci_notify_info(dev,
+                                       BUS_NOTIFY_ADD_DEVICE);
+                       if (!info) {
++                              pci_dev_put(dev);
+                               return dmar_dev_scope_status;
+                       } else {
+                               dmar_pci_bus_add_dev(info);
+-- 
+2.35.1
+
diff --git a/queue-5.15/iommu-vt-d-fix-pci-device-refcount-leak-in-has_exter.patch b/queue-5.15/iommu-vt-d-fix-pci-device-refcount-leak-in-has_exter.patch
new file mode 100644 (file)
index 0000000..a4205f6
--- /dev/null
@@ -0,0 +1,47 @@
+From 98d0ccdcd2a8cc412e0286cffb740e9cdf62f137 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Dec 2022 12:01:26 +0800
+Subject: iommu/vt-d: Fix PCI device refcount leak in has_external_pci()
+
+From: Xiongfeng Wang <wangxiongfeng2@huawei.com>
+
+[ Upstream commit afca9e19cc720bfafc75dc5ce429c185ca93f31d ]
+
+for_each_pci_dev() is implemented by pci_get_device(). The comment of
+pci_get_device() says that it will increase the reference count for the
+returned pci_dev and also decrease the reference count for the input
+pci_dev @from if it is not NULL.
+
+If we break for_each_pci_dev() loop with pdev not NULL, we need to call
+pci_dev_put() to decrease the reference count. Add the missing
+pci_dev_put() before 'return true' to avoid reference count leak.
+
+Fixes: 89a6079df791 ("iommu/vt-d: Force IOMMU on for platform opt in hint")
+Signed-off-by: Xiongfeng Wang <wangxiongfeng2@huawei.com>
+Link: https://lore.kernel.org/r/20221121113649.190393-2-wangxiongfeng2@huawei.com
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/intel/iommu.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
+index fa0cf1c3775d..751ff91af0ff 100644
+--- a/drivers/iommu/intel/iommu.c
++++ b/drivers/iommu/intel/iommu.c
+@@ -4241,8 +4241,10 @@ static inline bool has_external_pci(void)
+       struct pci_dev *pdev = NULL;
+       for_each_pci_dev(pdev)
+-              if (pdev->external_facing)
++              if (pdev->external_facing) {
++                      pci_dev_put(pdev);
+                       return true;
++              }
+       return false;
+ }
+-- 
+2.35.1
+
diff --git a/queue-5.15/ipv4-fix-route-deletion-when-nexthop-info-is-not-spe.patch b/queue-5.15/ipv4-fix-route-deletion-when-nexthop-info-is-not-spe.patch
new file mode 100644 (file)
index 0000000..189dc3e
--- /dev/null
@@ -0,0 +1,118 @@
+From d7be1e434afec50b15bb2a923c64eb2103d9f31f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Nov 2022 23:09:32 +0200
+Subject: ipv4: Fix route deletion when nexthop info is not specified
+
+From: Ido Schimmel <idosch@nvidia.com>
+
+[ Upstream commit d5082d386eee7e8ec46fa8581932c81a4961dcef ]
+
+When the kernel receives a route deletion request from user space it
+tries to delete a route that matches the route attributes specified in
+the request.
+
+If only prefix information is specified in the request, the kernel
+should delete the first matching FIB alias regardless of its associated
+FIB info. However, an error is currently returned when the FIB info is
+backed by a nexthop object:
+
+ # ip nexthop add id 1 via 192.0.2.2 dev dummy10
+ # ip route add 198.51.100.0/24 nhid 1
+ # ip route del 198.51.100.0/24
+ RTNETLINK answers: No such process
+
+Fix by matching on such a FIB info when legacy nexthop attributes are
+not specified in the request. An earlier check already covers the case
+where a nexthop ID is specified in the request.
+
+Add tests that cover these flows. Before the fix:
+
+ # ./fib_nexthops.sh -t ipv4_fcnal
+ ...
+ TEST: Delete route when not specifying nexthop attributes           [FAIL]
+
+ Tests passed:  11
+ Tests failed:   1
+
+After the fix:
+
+ # ./fib_nexthops.sh -t ipv4_fcnal
+ ...
+ TEST: Delete route when not specifying nexthop attributes           [ OK ]
+
+ Tests passed:  12
+ Tests failed:   0
+
+No regressions in other tests:
+
+ # ./fib_nexthops.sh
+ ...
+ Tests passed: 228
+ Tests failed:   0
+
+ # ./fib_tests.sh
+ ...
+ Tests passed: 186
+ Tests failed:   0
+
+Cc: stable@vger.kernel.org
+Reported-by: Jonas Gorski <jonas.gorski@gmail.com>
+Tested-by: Jonas Gorski <jonas.gorski@gmail.com>
+Fixes: 493ced1ac47c ("ipv4: Allow routes to use nexthop objects")
+Fixes: 6bf92d70e690 ("net: ipv4: fix route with nexthop object delete warning")
+Fixes: 61b91eb33a69 ("ipv4: Handle attempt to delete multipath route when fib_info contains an nh reference")
+Signed-off-by: Ido Schimmel <idosch@nvidia.com>
+Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Link: https://lore.kernel.org/r/20221124210932.2470010-1-idosch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/fib_semantics.c                    |  8 +++++---
+ tools/testing/selftests/net/fib_nexthops.sh | 11 +++++++++++
+ 2 files changed, 16 insertions(+), 3 deletions(-)
+
+diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
+index c35afa20f6d0..af64ae689b13 100644
+--- a/net/ipv4/fib_semantics.c
++++ b/net/ipv4/fib_semantics.c
+@@ -886,9 +886,11 @@ int fib_nh_match(struct net *net, struct fib_config *cfg, struct fib_info *fi,
+               return 1;
+       }
+-      /* cannot match on nexthop object attributes */
+-      if (fi->nh)
+-              return 1;
++      if (fi->nh) {
++              if (cfg->fc_oif || cfg->fc_gw_family || cfg->fc_mp)
++                      return 1;
++              return 0;
++      }
+       if (cfg->fc_oif || cfg->fc_gw_family) {
+               struct fib_nh *nh;
+diff --git a/tools/testing/selftests/net/fib_nexthops.sh b/tools/testing/selftests/net/fib_nexthops.sh
+index 4280c9b6ee2d..0c066ba579d4 100755
+--- a/tools/testing/selftests/net/fib_nexthops.sh
++++ b/tools/testing/selftests/net/fib_nexthops.sh
+@@ -1164,6 +1164,17 @@ ipv4_fcnal()
+       run_cmd "$IP ro add 172.16.101.0/24 nhid 21"
+       run_cmd "$IP ro del 172.16.101.0/24 nexthop via 172.16.1.7 dev veth1 nexthop via 172.16.1.8 dev veth1"
+       log_test $? 2 "Delete multipath route with only nh id based entry"
++
++      run_cmd "$IP nexthop add id 22 via 172.16.1.6 dev veth1"
++      run_cmd "$IP ro add 172.16.102.0/24 nhid 22"
++      run_cmd "$IP ro del 172.16.102.0/24 dev veth1"
++      log_test $? 2 "Delete route when specifying only nexthop device"
++
++      run_cmd "$IP ro del 172.16.102.0/24 via 172.16.1.6"
++      log_test $? 2 "Delete route when specifying only gateway"
++
++      run_cmd "$IP ro del 172.16.102.0/24"
++      log_test $? 0 "Delete route when not specifying nexthop attributes"
+ }
+ ipv4_grp_fcnal()
+-- 
+2.35.1
+
diff --git a/queue-5.15/ipv4-handle-attempt-to-delete-multipath-route-when-f.patch b/queue-5.15/ipv4-handle-attempt-to-delete-multipath-route-when-f.patch
new file mode 100644 (file)
index 0000000..5980bf7
--- /dev/null
@@ -0,0 +1,75 @@
+From 1aa0cf3032041bd7f09fc507e0185cc2f4e976c0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Oct 2022 10:48:49 -0600
+Subject: ipv4: Handle attempt to delete multipath route when fib_info contains
+ an nh reference
+
+From: David Ahern <dsahern@kernel.org>
+
+[ Upstream commit 61b91eb33a69c3be11b259c5ea484505cd79f883 ]
+
+Gwangun Jung reported a slab-out-of-bounds access in fib_nh_match:
+    fib_nh_match+0xf98/0x1130 linux-6.0-rc7/net/ipv4/fib_semantics.c:961
+    fib_table_delete+0x5f3/0xa40 linux-6.0-rc7/net/ipv4/fib_trie.c:1753
+    inet_rtm_delroute+0x2b3/0x380 linux-6.0-rc7/net/ipv4/fib_frontend.c:874
+
+Separate nexthop objects are mutually exclusive with the legacy
+multipath spec. Fix fib_nh_match to return if the config for the
+to be deleted route contains a multipath spec while the fib_info
+is using a nexthop object.
+
+Fixes: 493ced1ac47c ("ipv4: Allow routes to use nexthop objects")
+Fixes: 6bf92d70e690 ("net: ipv4: fix route with nexthop object delete warning")
+Reported-by: Gwangun Jung <exsociety@gmail.com>
+Signed-off-by: David Ahern <dsahern@kernel.org>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Tested-by: Ido Schimmel <idosch@nvidia.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: d5082d386eee ("ipv4: Fix route deletion when nexthop info is not specified")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/fib_semantics.c                    | 8 ++++----
+ tools/testing/selftests/net/fib_nexthops.sh | 5 +++++
+ 2 files changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
+index 55de6fa83dea..c35afa20f6d0 100644
+--- a/net/ipv4/fib_semantics.c
++++ b/net/ipv4/fib_semantics.c
+@@ -886,13 +886,13 @@ int fib_nh_match(struct net *net, struct fib_config *cfg, struct fib_info *fi,
+               return 1;
+       }
++      /* cannot match on nexthop object attributes */
++      if (fi->nh)
++              return 1;
++
+       if (cfg->fc_oif || cfg->fc_gw_family) {
+               struct fib_nh *nh;
+-              /* cannot match on nexthop object attributes */
+-              if (fi->nh)
+-                      return 1;
+-
+               nh = fib_info_nh(fi, 0);
+               if (cfg->fc_encap) {
+                       if (fib_encap_match(net, cfg->fc_encap_type,
+diff --git a/tools/testing/selftests/net/fib_nexthops.sh b/tools/testing/selftests/net/fib_nexthops.sh
+index 4afc4b20c546..4280c9b6ee2d 100755
+--- a/tools/testing/selftests/net/fib_nexthops.sh
++++ b/tools/testing/selftests/net/fib_nexthops.sh
+@@ -1159,6 +1159,11 @@ ipv4_fcnal()
+       log_test $rc 0 "Delete nexthop route warning"
+       run_cmd "$IP route delete 172.16.101.1/32 nhid 12"
+       run_cmd "$IP nexthop del id 12"
++
++      run_cmd "$IP nexthop add id 21 via 172.16.1.6 dev veth1"
++      run_cmd "$IP ro add 172.16.101.0/24 nhid 21"
++      run_cmd "$IP ro del 172.16.101.0/24 nexthop via 172.16.1.7 dev veth1 nexthop via 172.16.1.8 dev veth1"
++      log_test $? 2 "Delete multipath route with only nh id based entry"
+ }
+ ipv4_grp_fcnal()
+-- 
+2.35.1
+
diff --git a/queue-5.15/kconfig.debug-provide-a-little-extra-frame_warn-leew.patch b/queue-5.15/kconfig.debug-provide-a-little-extra-frame_warn-leew.patch
new file mode 100644 (file)
index 0000000..bc03b5b
--- /dev/null
@@ -0,0 +1,56 @@
+From 2e8508f7cb3a9bf0ac3e1cc25aed0d5839a7485f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Nov 2022 12:07:50 +0000
+Subject: Kconfig.debug: provide a little extra FRAME_WARN leeway when KASAN is
+ enabled
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Lee Jones <lee@kernel.org>
+
+[ Upstream commit 152fe65f300e1819d59b80477d3e0999b4d5d7d2 ]
+
+When enabled, KASAN enlarges function's stack-frames.  Pushing quite a few
+over the current threshold.  This can mainly be seen on 32-bit
+architectures where the present limit (when !GCC) is a lowly 1024-Bytes.
+
+Link: https://lkml.kernel.org/r/20221125120750.3537134-3-lee@kernel.org
+Signed-off-by: Lee Jones <lee@kernel.org>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Cc: "Christian König" <christian.koenig@amd.com>
+Cc: Daniel Vetter <daniel@ffwll.ch>
+Cc: David Airlie <airlied@gmail.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Cc: Leo Li <sunpeng.li@amd.com>
+Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
+Cc: Maxime Ripard <mripard@kernel.org>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nick Desaulniers <ndesaulniers@google.com>
+Cc: "Pan, Xinhui" <Xinhui.Pan@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Thomas Zimmermann <tzimmermann@suse.de>
+Cc: Tom Rix <trix@redhat.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ lib/Kconfig.debug | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
+index 23b7b1fccc54..f71db0cc3bf1 100644
+--- a/lib/Kconfig.debug
++++ b/lib/Kconfig.debug
+@@ -354,6 +354,7 @@ config FRAME_WARN
+       default 2048 if GCC_PLUGIN_LATENT_ENTROPY
+       default 2048 if PARISC
+       default 1536 if (!64BIT && XTENSA)
++      default 1280 if KASAN && !64BIT
+       default 1024 if !64BIT
+       default 2048 if 64BIT
+       help
+-- 
+2.35.1
+
diff --git a/queue-5.15/mm-__isolate_lru_page_prepare-in-isolate_migratepage.patch b/queue-5.15/mm-__isolate_lru_page_prepare-in-isolate_migratepage.patch
new file mode 100644 (file)
index 0000000..f2b43f6
--- /dev/null
@@ -0,0 +1,318 @@
+From 48987d79e260a608212499e10de103a76b9324db Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Mar 2022 14:45:41 -0700
+Subject: mm: __isolate_lru_page_prepare() in isolate_migratepages_block()
+
+From: Hugh Dickins <hughd@google.com>
+
+[ Upstream commit 89f6c88a6ab4a11deb14c270f7f1454cda4f73d6 ]
+
+__isolate_lru_page_prepare() conflates two unrelated functions, with the
+flags to one disjoint from the flags to the other; and hides some of the
+important checks outside of isolate_migratepages_block(), where the
+sequence is better to be visible.  It comes from the days of lumpy
+reclaim, before compaction, when the combination made more sense.
+
+Move what's needed by mm/compaction.c isolate_migratepages_block() inline
+there, and what's needed by mm/vmscan.c isolate_lru_pages() inline there.
+
+Shorten "isolate_mode" to "mode", so the sequence of conditions is easier
+to read.  Declare a "mapping" variable, to save one call to page_mapping()
+(but not another: calling again after page is locked is necessary).
+Simplify isolate_lru_pages() with a "move_to" list pointer.
+
+Link: https://lkml.kernel.org/r/879d62a8-91cc-d3c6-fb3b-69768236df68@google.com
+Signed-off-by: Hugh Dickins <hughd@google.com>
+Acked-by: David Rientjes <rientjes@google.com>
+Reviewed-by: Alex Shi <alexs@kernel.org>
+Cc: Alexander Duyck <alexander.duyck@gmail.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Stable-dep-of: 829ae0f81ce0 ("mm: migrate: fix THP's mapcount on isolation")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/swap.h |   1 -
+ mm/compaction.c      |  51 +++++++++++++++++++---
+ mm/vmscan.c          | 101 ++++++++-----------------------------------
+ 3 files changed, 62 insertions(+), 91 deletions(-)
+
+diff --git a/include/linux/swap.h b/include/linux/swap.h
+index ba52f3a3478e..4efd267e2937 100644
+--- a/include/linux/swap.h
++++ b/include/linux/swap.h
+@@ -378,7 +378,6 @@ extern void lru_cache_add_inactive_or_unevictable(struct page *page,
+ extern unsigned long zone_reclaimable_pages(struct zone *zone);
+ extern unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
+                                       gfp_t gfp_mask, nodemask_t *mask);
+-extern bool __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode);
+ extern unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg,
+                                                 unsigned long nr_pages,
+                                                 gfp_t gfp_mask,
+diff --git a/mm/compaction.c b/mm/compaction.c
+index 48a2111ce437..b6bd745a2f7f 100644
+--- a/mm/compaction.c
++++ b/mm/compaction.c
+@@ -779,7 +779,7 @@ static bool too_many_isolated(pg_data_t *pgdat)
+  * @cc:               Compaction control structure.
+  * @low_pfn:  The first PFN to isolate
+  * @end_pfn:  The one-past-the-last PFN to isolate, within same pageblock
+- * @isolate_mode: Isolation mode to be used.
++ * @mode:     Isolation mode to be used.
+  *
+  * Isolate all pages that can be migrated from the range specified by
+  * [low_pfn, end_pfn). The range is expected to be within same pageblock.
+@@ -792,7 +792,7 @@ static bool too_many_isolated(pg_data_t *pgdat)
+  */
+ static int
+ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
+-                      unsigned long end_pfn, isolate_mode_t isolate_mode)
++                      unsigned long end_pfn, isolate_mode_t mode)
+ {
+       pg_data_t *pgdat = cc->zone->zone_pgdat;
+       unsigned long nr_scanned = 0, nr_isolated = 0;
+@@ -800,6 +800,7 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
+       unsigned long flags = 0;
+       struct lruvec *locked = NULL;
+       struct page *page = NULL, *valid_page = NULL;
++      struct address_space *mapping;
+       unsigned long start_pfn = low_pfn;
+       bool skip_on_failure = false;
+       unsigned long next_skip_pfn = 0;
+@@ -984,7 +985,7 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
+                                       locked = NULL;
+                               }
+-                              if (!isolate_movable_page(page, isolate_mode))
++                              if (!isolate_movable_page(page, mode))
+                                       goto isolate_success;
+                       }
+@@ -996,15 +997,15 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
+                * so avoid taking lru_lock and isolating it unnecessarily in an
+                * admittedly racy check.
+                */
+-              if (!page_mapping(page) &&
+-                  page_count(page) > page_mapcount(page))
++              mapping = page_mapping(page);
++              if (!mapping && page_count(page) > page_mapcount(page))
+                       goto isolate_fail;
+               /*
+                * Only allow to migrate anonymous pages in GFP_NOFS context
+                * because those do not depend on fs locks.
+                */
+-              if (!(cc->gfp_mask & __GFP_FS) && page_mapping(page))
++              if (!(cc->gfp_mask & __GFP_FS) && mapping)
+                       goto isolate_fail;
+               /*
+@@ -1015,9 +1016,45 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
+               if (unlikely(!get_page_unless_zero(page)))
+                       goto isolate_fail;
+-              if (!__isolate_lru_page_prepare(page, isolate_mode))
++              /* Only take pages on LRU: a check now makes later tests safe */
++              if (!PageLRU(page))
++                      goto isolate_fail_put;
++
++              /* Compaction might skip unevictable pages but CMA takes them */
++              if (!(mode & ISOLATE_UNEVICTABLE) && PageUnevictable(page))
++                      goto isolate_fail_put;
++
++              /*
++               * To minimise LRU disruption, the caller can indicate with
++               * ISOLATE_ASYNC_MIGRATE that it only wants to isolate pages
++               * it will be able to migrate without blocking - clean pages
++               * for the most part.  PageWriteback would require blocking.
++               */
++              if ((mode & ISOLATE_ASYNC_MIGRATE) && PageWriteback(page))
+                       goto isolate_fail_put;
++              if ((mode & ISOLATE_ASYNC_MIGRATE) && PageDirty(page)) {
++                      bool migrate_dirty;
++
++                      /*
++                       * Only pages without mappings or that have a
++                       * ->migratepage callback are possible to migrate
++                       * without blocking. However, we can be racing with
++                       * truncation so it's necessary to lock the page
++                       * to stabilise the mapping as truncation holds
++                       * the page lock until after the page is removed
++                       * from the page cache.
++                       */
++                      if (!trylock_page(page))
++                              goto isolate_fail_put;
++
++                      mapping = page_mapping(page);
++                      migrate_dirty = !mapping || mapping->a_ops->migratepage;
++                      unlock_page(page);
++                      if (!migrate_dirty)
++                              goto isolate_fail_put;
++              }
++
+               /* Try isolate the page */
+               if (!TestClearPageLRU(page))
+                       goto isolate_fail_put;
+diff --git a/mm/vmscan.c b/mm/vmscan.c
+index 1b63d6155416..201acea81804 100644
+--- a/mm/vmscan.c
++++ b/mm/vmscan.c
+@@ -1865,69 +1865,6 @@ unsigned int reclaim_clean_pages_from_list(struct zone *zone,
+       return nr_reclaimed;
+ }
+-/*
+- * Attempt to remove the specified page from its LRU.  Only take this page
+- * if it is of the appropriate PageActive status.  Pages which are being
+- * freed elsewhere are also ignored.
+- *
+- * page:      page to consider
+- * mode:      one of the LRU isolation modes defined above
+- *
+- * returns true on success, false on failure.
+- */
+-bool __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode)
+-{
+-      /* Only take pages on the LRU. */
+-      if (!PageLRU(page))
+-              return false;
+-
+-      /* Compaction should not handle unevictable pages but CMA can do so */
+-      if (PageUnevictable(page) && !(mode & ISOLATE_UNEVICTABLE))
+-              return false;
+-
+-      /*
+-       * To minimise LRU disruption, the caller can indicate that it only
+-       * wants to isolate pages it will be able to operate on without
+-       * blocking - clean pages for the most part.
+-       *
+-       * ISOLATE_ASYNC_MIGRATE is used to indicate that it only wants to pages
+-       * that it is possible to migrate without blocking
+-       */
+-      if (mode & ISOLATE_ASYNC_MIGRATE) {
+-              /* All the caller can do on PageWriteback is block */
+-              if (PageWriteback(page))
+-                      return false;
+-
+-              if (PageDirty(page)) {
+-                      struct address_space *mapping;
+-                      bool migrate_dirty;
+-
+-                      /*
+-                       * Only pages without mappings or that have a
+-                       * ->migratepage callback are possible to migrate
+-                       * without blocking. However, we can be racing with
+-                       * truncation so it's necessary to lock the page
+-                       * to stabilise the mapping as truncation holds
+-                       * the page lock until after the page is removed
+-                       * from the page cache.
+-                       */
+-                      if (!trylock_page(page))
+-                              return false;
+-
+-                      mapping = page_mapping(page);
+-                      migrate_dirty = !mapping || mapping->a_ops->migratepage;
+-                      unlock_page(page);
+-                      if (!migrate_dirty)
+-                              return false;
+-              }
+-      }
+-
+-      if ((mode & ISOLATE_UNMAPPED) && page_mapped(page))
+-              return false;
+-
+-      return true;
+-}
+-
+ /*
+  * Update LRU sizes after isolating pages. The LRU size updates must
+  * be complete before mem_cgroup_update_lru_size due to a sanity check.
+@@ -1979,11 +1916,11 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
+       unsigned long skipped = 0;
+       unsigned long scan, total_scan, nr_pages;
+       LIST_HEAD(pages_skipped);
+-      isolate_mode_t mode = (sc->may_unmap ? 0 : ISOLATE_UNMAPPED);
+       total_scan = 0;
+       scan = 0;
+       while (scan < nr_to_scan && !list_empty(src)) {
++              struct list_head *move_to = src;
+               struct page *page;
+               page = lru_to_page(src);
+@@ -1993,9 +1930,9 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
+               total_scan += nr_pages;
+               if (page_zonenum(page) > sc->reclaim_idx) {
+-                      list_move(&page->lru, &pages_skipped);
+                       nr_skipped[page_zonenum(page)] += nr_pages;
+-                      continue;
++                      move_to = &pages_skipped;
++                      goto move;
+               }
+               /*
+@@ -2003,37 +1940,34 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
+                * return with no isolated pages if the LRU mostly contains
+                * ineligible pages.  This causes the VM to not reclaim any
+                * pages, triggering a premature OOM.
+-               *
+-               * Account all tail pages of THP.  This would not cause
+-               * premature OOM since __isolate_lru_page() returns -EBUSY
+-               * only when the page is being freed somewhere else.
++               * Account all tail pages of THP.
+                */
+               scan += nr_pages;
+-              if (!__isolate_lru_page_prepare(page, mode)) {
+-                      /* It is being freed elsewhere */
+-                      list_move(&page->lru, src);
+-                      continue;
+-              }
++
++              if (!PageLRU(page))
++                      goto move;
++              if (!sc->may_unmap && page_mapped(page))
++                      goto move;
++
+               /*
+                * Be careful not to clear PageLRU until after we're
+                * sure the page is not being freed elsewhere -- the
+                * page release code relies on it.
+                */
+-              if (unlikely(!get_page_unless_zero(page))) {
+-                      list_move(&page->lru, src);
+-                      continue;
+-              }
++              if (unlikely(!get_page_unless_zero(page)))
++                      goto move;
+               if (!TestClearPageLRU(page)) {
+                       /* Another thread is already isolating this page */
+                       put_page(page);
+-                      list_move(&page->lru, src);
+-                      continue;
++                      goto move;
+               }
+               nr_taken += nr_pages;
+               nr_zone_taken[page_zonenum(page)] += nr_pages;
+-              list_move(&page->lru, dst);
++              move_to = dst;
++move:
++              list_move(&page->lru, move_to);
+       }
+       /*
+@@ -2057,7 +1991,8 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
+       }
+       *nr_scanned = total_scan;
+       trace_mm_vmscan_lru_isolate(sc->reclaim_idx, sc->order, nr_to_scan,
+-                                  total_scan, skipped, nr_taken, mode, lru);
++                                  total_scan, skipped, nr_taken,
++                                  sc->may_unmap ? 0 : ISOLATE_UNMAPPED, lru);
+       update_lru_sizes(lruvec, lru, nr_zone_taken);
+       return nr_taken;
+ }
+-- 
+2.35.1
+
diff --git a/queue-5.15/mm-migrate-fix-thp-s-mapcount-on-isolation.patch b/queue-5.15/mm-migrate-fix-thp-s-mapcount-on-isolation.patch
new file mode 100644 (file)
index 0000000..65eb17f
--- /dev/null
@@ -0,0 +1,89 @@
+From 488391d6b29def702747cde1fe6054588371cfc7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Nov 2022 17:55:23 +0800
+Subject: mm: migrate: fix THP's mapcount on isolation
+
+From: Gavin Shan <gshan@redhat.com>
+
+[ Upstream commit 829ae0f81ce093d674ff2256f66a714753e9ce32 ]
+
+The issue is reported when removing memory through virtio_mem device.  The
+transparent huge page, experienced copy-on-write fault, is wrongly
+regarded as pinned.  The transparent huge page is escaped from being
+isolated in isolate_migratepages_block().  The transparent huge page can't
+be migrated and the corresponding memory block can't be put into offline
+state.
+
+Fix it by replacing page_mapcount() with total_mapcount().  With this, the
+transparent huge page can be isolated and migrated, and the memory block
+can be put into offline state.  Besides, The page's refcount is increased
+a bit earlier to avoid the page is released when the check is executed.
+
+Link: https://lkml.kernel.org/r/20221124095523.31061-1-gshan@redhat.com
+Fixes: 1da2f328fa64 ("mm,thp,compaction,cma: allow THP migration for CMA allocations")
+Signed-off-by: Gavin Shan <gshan@redhat.com>
+Reported-by: Zhenyu Zhang <zhenyzha@redhat.com>
+Tested-by: Zhenyu Zhang <zhenyzha@redhat.com>
+Suggested-by: David Hildenbrand <david@redhat.com>
+Acked-by: David Hildenbrand <david@redhat.com>
+Cc: Alistair Popple <apopple@nvidia.com>
+Cc: Hugh Dickins <hughd@google.com>
+Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
+Cc: Matthew Wilcox <willy@infradead.org>
+Cc: William Kucharski <william.kucharski@oracle.com>
+Cc: Zi Yan <ziy@nvidia.com>
+Cc: <stable@vger.kernel.org>   [5.7+]
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ mm/compaction.c | 22 +++++++++++-----------
+ 1 file changed, 11 insertions(+), 11 deletions(-)
+
+diff --git a/mm/compaction.c b/mm/compaction.c
+index b6bd745a2f7f..e8fcf0e0c1ca 100644
+--- a/mm/compaction.c
++++ b/mm/compaction.c
+@@ -992,29 +992,29 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
+                       goto isolate_fail;
+               }
++              /*
++               * Be careful not to clear PageLRU until after we're
++               * sure the page is not being freed elsewhere -- the
++               * page release code relies on it.
++               */
++              if (unlikely(!get_page_unless_zero(page)))
++                      goto isolate_fail;
++
+               /*
+                * Migration will fail if an anonymous page is pinned in memory,
+                * so avoid taking lru_lock and isolating it unnecessarily in an
+                * admittedly racy check.
+                */
+               mapping = page_mapping(page);
+-              if (!mapping && page_count(page) > page_mapcount(page))
+-                      goto isolate_fail;
++              if (!mapping && (page_count(page) - 1) > total_mapcount(page))
++                      goto isolate_fail_put;
+               /*
+                * Only allow to migrate anonymous pages in GFP_NOFS context
+                * because those do not depend on fs locks.
+                */
+               if (!(cc->gfp_mask & __GFP_FS) && mapping)
+-                      goto isolate_fail;
+-
+-              /*
+-               * Be careful not to clear PageLRU until after we're
+-               * sure the page is not being freed elsewhere -- the
+-               * page release code relies on it.
+-               */
+-              if (unlikely(!get_page_unless_zero(page)))
+-                      goto isolate_fail;
++                      goto isolate_fail_put;
+               /* Only take pages on LRU: a check now makes later tests safe */
+               if (!PageLRU(page))
+-- 
+2.35.1
+
diff --git a/queue-5.15/nvme-fix-srcu-protection-of-nvme_ns_head-list.patch b/queue-5.15/nvme-fix-srcu-protection-of-nvme_ns_head-list.patch
new file mode 100644 (file)
index 0000000..37ecb60
--- /dev/null
@@ -0,0 +1,104 @@
+From e92bc9e180b44f0d2bd81f67106d434e4f34a8cc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 18 Nov 2022 16:27:56 -0700
+Subject: nvme: fix SRCU protection of nvme_ns_head list
+
+From: Caleb Sander <csander@purestorage.com>
+
+[ Upstream commit 899d2a05dc14733cfba6224083c6b0dd5a738590 ]
+
+Walking the nvme_ns_head siblings list is protected by the head's srcu
+in nvme_ns_head_submit_bio() but not nvme_mpath_revalidate_paths().
+Removing namespaces from the list also fails to synchronize the srcu.
+Concurrent scan work can therefore cause use-after-frees.
+
+Hold the head's srcu lock in nvme_mpath_revalidate_paths() and
+synchronize with the srcu, not the global RCU, in nvme_ns_remove().
+
+Observed the following panic when making NVMe/RDMA connections
+with native multipath on the Rocky Linux 8.6 kernel
+(it seems the upstream kernel has the same race condition).
+Disassembly shows the faulting instruction is cmp 0x50(%rdx),%rcx;
+computing capacity != get_capacity(ns->disk).
+Address 0x50 is dereferenced because ns->disk is NULL.
+The NULL disk appears to be the result of concurrent scan work
+freeing the namespace (note the log line in the middle of the panic).
+
+[37314.206036] BUG: unable to handle kernel NULL pointer dereference at 0000000000000050
+[37314.206036] nvme0n3: detected capacity change from 0 to 11811160064
+[37314.299753] PGD 0 P4D 0
+[37314.299756] Oops: 0000 [#1] SMP PTI
+[37314.299759] CPU: 29 PID: 322046 Comm: kworker/u98:3 Kdump: loaded Tainted: G        W      X --------- -  - 4.18.0-372.32.1.el8test86.x86_64 #1
+[37314.299762] Hardware name: Dell Inc. PowerEdge R720/0JP31P, BIOS 2.7.0 05/23/2018
+[37314.299763] Workqueue: nvme-wq nvme_scan_work [nvme_core]
+[37314.299783] RIP: 0010:nvme_mpath_revalidate_paths+0x26/0xb0 [nvme_core]
+[37314.299790] Code: 1f 44 00 00 66 66 66 66 90 55 53 48 8b 5f 50 48 8b 83 c8 c9 00 00 48 8b 13 48 8b 48 50 48 39 d3 74 20 48 8d 42 d0 48 8b 50 20 <48> 3b 4a 50 74 05 f0 80 60 70 ef 48 8b 50 30 48 8d 42 d0 48 39 d3
+[37315.058803] RSP: 0018:ffffabe28f913d10 EFLAGS: 00010202
+[37315.121316] RAX: ffff927a077da800 RBX: ffff92991dd70000 RCX: 0000000001600000
+[37315.206704] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff92991b719800
+[37315.292106] RBP: ffff929a6b70c000 R08: 000000010234cd4a R09: c0000000ffff7fff
+[37315.377501] R10: 0000000000000001 R11: ffffabe28f913a30 R12: 0000000000000000
+[37315.462889] R13: ffff92992716600c R14: ffff929964e6e030 R15: ffff92991dd70000
+[37315.548286] FS:  0000000000000000(0000) GS:ffff92b87fb80000(0000) knlGS:0000000000000000
+[37315.645111] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[37315.713871] CR2: 0000000000000050 CR3: 0000002208810006 CR4: 00000000000606e0
+[37315.799267] Call Trace:
+[37315.828515]  nvme_update_ns_info+0x1ac/0x250 [nvme_core]
+[37315.892075]  nvme_validate_or_alloc_ns+0x2ff/0xa00 [nvme_core]
+[37315.961871]  ? __blk_mq_free_request+0x6b/0x90
+[37316.015021]  nvme_scan_work+0x151/0x240 [nvme_core]
+[37316.073371]  process_one_work+0x1a7/0x360
+[37316.121318]  ? create_worker+0x1a0/0x1a0
+[37316.168227]  worker_thread+0x30/0x390
+[37316.212024]  ? create_worker+0x1a0/0x1a0
+[37316.258939]  kthread+0x10a/0x120
+[37316.297557]  ? set_kthread_struct+0x50/0x50
+[37316.347590]  ret_from_fork+0x35/0x40
+[37316.390360] Modules linked in: nvme_rdma nvme_tcp(X) nvme_fabrics nvme_core netconsole iscsi_tcp libiscsi_tcp dm_queue_length dm_service_time nf_conntrack_netlink br_netfilter bridge stp llc overlay nft_chain_nat ipt_MASQUERADE nf_nat xt_addrtype xt_CT nft_counter xt_state xt_conntrack nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 xt_comment xt_multiport nft_compat nf_tables libcrc32c nfnetlink dm_multipath tg3 rpcrdma sunrpc rdma_ucm ib_srpt ib_isert iscsi_target_mod target_core_mod ib_iser libiscsi scsi_transport_iscsi ib_umad rdma_cm ib_ipoib iw_cm ib_cm intel_rapl_msr iTCO_wdt iTCO_vendor_support dcdbas intel_rapl_common sb_edac x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel ipmi_ssif kvm irqbypass crct10dif_pclmul crc32_pclmul mlx5_ib ghash_clmulni_intel ib_uverbs rapl intel_cstate intel_uncore ib_core ipmi_si joydev mei_me pcspkr ipmi_devintf mei lpc_ich wmi ipmi_msghandler acpi_power_meter ext4 mbcache jbd2 sd_mod t10_pi sg mgag200 mlx5_core drm_kms_helper syscopyarea
+[37316.390419]  sysfillrect ahci sysimgblt fb_sys_fops libahci drm crc32c_intel libata mlxfw pci_hyperv_intf tls i2c_algo_bit psample dm_mirror dm_region_hash dm_log dm_mod fuse [last unloaded: nvme_core]
+[37317.645908] CR2: 0000000000000050
+
+Fixes: e7d65803e2bb ("nvme-multipath: revalidate paths during rescan")
+Signed-off-by: Caleb Sander <csander@purestorage.com>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/host/core.c      | 2 +-
+ drivers/nvme/host/multipath.c | 3 +++
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
+index 92fe67bd2457..694373951b18 100644
+--- a/drivers/nvme/host/core.c
++++ b/drivers/nvme/host/core.c
+@@ -3920,7 +3920,7 @@ static void nvme_ns_remove(struct nvme_ns *ns)
+       mutex_unlock(&ns->ctrl->subsys->lock);
+       /* guarantee not available in head->list */
+-      synchronize_rcu();
++      synchronize_srcu(&ns->head->srcu);
+       /* wait for concurrent submissions */
+       if (nvme_mpath_clear_current_path(ns))
+diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
+index 36b48e2ff642..fe199d568a4a 100644
+--- a/drivers/nvme/host/multipath.c
++++ b/drivers/nvme/host/multipath.c
+@@ -151,11 +151,14 @@ void nvme_mpath_revalidate_paths(struct nvme_ns *ns)
+       struct nvme_ns_head *head = ns->head;
+       sector_t capacity = get_capacity(head->disk);
+       int node;
++      int srcu_idx;
++      srcu_idx = srcu_read_lock(&head->srcu);
+       list_for_each_entry_rcu(ns, &head->list, siblings) {
+               if (capacity != get_capacity(ns->disk))
+                       clear_bit(NVME_NS_READY, &ns->flags);
+       }
++      srcu_read_unlock(&head->srcu, srcu_idx);
+       for_each_node(node)
+               rcu_assign_pointer(head->current_path[node], NULL);
+-- 
+2.35.1
+
diff --git a/queue-5.15/parisc-increase-frame_warn-to-2048-bytes-on-parisc.patch b/queue-5.15/parisc-increase-frame_warn-to-2048-bytes-on-parisc.patch
new file mode 100644 (file)
index 0000000..df4d812
--- /dev/null
@@ -0,0 +1,40 @@
+From 44296db495c41ac25d1ab0e88455f420c768b245 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Nov 2021 22:31:03 +0100
+Subject: parisc: Increase FRAME_WARN to 2048 bytes on parisc
+
+From: Helge Deller <deller@gmx.de>
+
+[ Upstream commit 8d192bec534bd5b778135769a12e5f04580771f7 ]
+
+PA-RISC uses a much bigger frame size for functions than other
+architectures. So increase it to 2048 for 32- and 64-bit kernels.
+This fixes e.g. a warning in lib/xxhash.c.
+
+Reported-by: kernel test robot <lkp@intel.com>
+Signed-off-by: Helge Deller <deller@gmx.de>
+Stable-dep-of: 152fe65f300e ("Kconfig.debug: provide a little extra FRAME_WARN leeway when KASAN is enabled")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ lib/Kconfig.debug | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
+index 027ab190796f..23b7b1fccc54 100644
+--- a/lib/Kconfig.debug
++++ b/lib/Kconfig.debug
+@@ -352,8 +352,9 @@ config FRAME_WARN
+       int "Warn for stack frames larger than"
+       range 0 8192
+       default 2048 if GCC_PLUGIN_LATENT_ENTROPY
+-      default 1536 if (!64BIT && (PARISC || XTENSA))
+-      default 1024 if (!64BIT && !PARISC)
++      default 2048 if PARISC
++      default 1536 if (!64BIT && XTENSA)
++      default 1024 if !64BIT
+       default 2048 if 64BIT
+       help
+         Tell gcc to warn at build time for stack frames larger than this.
+-- 
+2.35.1
+
diff --git a/queue-5.15/pinctrl-single-fix-potential-division-by-zero.patch b/queue-5.15/pinctrl-single-fix-potential-division-by-zero.patch
new file mode 100644 (file)
index 0000000..fdc6545
--- /dev/null
@@ -0,0 +1,43 @@
+From cf70f3f8b44858d680ccb2f852f75d3dac8dadab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Nov 2022 15:30:34 +0300
+Subject: pinctrl: single: Fix potential division by zero
+
+From: Maxim Korotkov <korotkov.maxim.s@gmail.com>
+
+[ Upstream commit 64c150339e7f6c5cbbe8c17a56ef2b3902612798 ]
+
+There is a possibility of dividing by zero due to the pcs->bits_per_pin
+if pcs->fmask() also has a value of zero and called fls
+from asm-generic/bitops/builtin-fls.h or arch/x86/include/asm/bitops.h.
+The function pcs_probe() has the branch that assigned to fmask 0 before
+pcs_allocate_pin_table() was called
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+Fixes: 4e7e8017a80e ("pinctrl: pinctrl-single: enhance to configure multiple pins of different modules")
+Signed-off-by: Maxim Korotkov <korotkov.maxim.s@gmail.com>
+Reviewed-by: Tony Lindgren <tony@atomide.com>
+Link: https://lore.kernel.org/r/20221117123034.27383-1-korotkov.maxim.s@gmail.com
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pinctrl/pinctrl-single.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
+index 67bec7ea0f8b..414ee6bb8ac9 100644
+--- a/drivers/pinctrl/pinctrl-single.c
++++ b/drivers/pinctrl/pinctrl-single.c
+@@ -727,7 +727,7 @@ static int pcs_allocate_pin_table(struct pcs_device *pcs)
+       mux_bytes = pcs->width / BITS_PER_BYTE;
+-      if (pcs->bits_per_mux) {
++      if (pcs->bits_per_mux && pcs->fmask) {
+               pcs->bits_per_pin = fls(pcs->fmask);
+               nr_pins = (pcs->size * BITS_PER_BYTE) / pcs->bits_per_pin;
+       } else {
+-- 
+2.35.1
+
diff --git a/queue-5.15/riscv-fix-race-when-vmap-stack-overflow.patch b/queue-5.15/riscv-fix-race-when-vmap-stack-overflow.patch
new file mode 100644 (file)
index 0000000..2ba516a
--- /dev/null
@@ -0,0 +1,107 @@
+From 129f6b6589da3224c9052370bf89d08281c97728 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 30 Oct 2022 20:45:17 +0800
+Subject: riscv: fix race when vmap stack overflow
+
+From: Jisheng Zhang <jszhang@kernel.org>
+
+[ Upstream commit 7e1864332fbc1b993659eab7974da9fe8bf8c128 ]
+
+Currently, when detecting vmap stack overflow, riscv firstly switches
+to the so called shadow stack, then use this shadow stack to call the
+get_overflow_stack() to get the overflow stack. However, there's
+a race here if two or more harts use the same shadow stack at the same
+time.
+
+To solve this race, we introduce spin_shadow_stack atomic var, which
+will be swap between its own address and 0 in atomic way, when the
+var is set, it means the shadow_stack is being used; when the var
+is cleared, it means the shadow_stack isn't being used.
+
+Fixes: 31da94c25aea ("riscv: add VMAP_STACK overflow detection")
+Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
+Suggested-by: Guo Ren <guoren@kernel.org>
+Reviewed-by: Guo Ren <guoren@kernel.org>
+Link: https://lore.kernel.org/r/20221030124517.2370-1-jszhang@kernel.org
+[Palmer: Add AQ to the swap, and also some comments.]
+Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/riscv/include/asm/asm.h |  1 +
+ arch/riscv/kernel/entry.S    | 13 +++++++++++++
+ arch/riscv/kernel/traps.c    | 18 ++++++++++++++++++
+ 3 files changed, 32 insertions(+)
+
+diff --git a/arch/riscv/include/asm/asm.h b/arch/riscv/include/asm/asm.h
+index 618d7c5af1a2..e15a1c9f1cf8 100644
+--- a/arch/riscv/include/asm/asm.h
++++ b/arch/riscv/include/asm/asm.h
+@@ -23,6 +23,7 @@
+ #define REG_L         __REG_SEL(ld, lw)
+ #define REG_S         __REG_SEL(sd, sw)
+ #define REG_SC                __REG_SEL(sc.d, sc.w)
++#define REG_AMOSWAP_AQ        __REG_SEL(amoswap.d.aq, amoswap.w.aq)
+ #define REG_ASM               __REG_SEL(.dword, .word)
+ #define SZREG         __REG_SEL(8, 4)
+ #define LGREG         __REG_SEL(3, 2)
+diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
+index 7e52ad5d61ad..5ca2860cc06c 100644
+--- a/arch/riscv/kernel/entry.S
++++ b/arch/riscv/kernel/entry.S
+@@ -387,6 +387,19 @@ handle_syscall_trace_exit:
+ #ifdef CONFIG_VMAP_STACK
+ handle_kernel_stack_overflow:
++      /*
++       * Takes the psuedo-spinlock for the shadow stack, in case multiple
++       * harts are concurrently overflowing their kernel stacks.  We could
++       * store any value here, but since we're overflowing the kernel stack
++       * already we only have SP to use as a scratch register.  So we just
++       * swap in the address of the spinlock, as that's definately non-zero.
++       *
++       * Pairs with a store_release in handle_bad_stack().
++       */
++1:    la sp, spin_shadow_stack
++      REG_AMOSWAP_AQ sp, sp, (sp)
++      bnez sp, 1b
++
+       la sp, shadow_stack
+       addi sp, sp, SHADOW_OVERFLOW_STACK_SIZE
+diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c
+index 8c58aa5d2b36..2f4cd85fb651 100644
+--- a/arch/riscv/kernel/traps.c
++++ b/arch/riscv/kernel/traps.c
+@@ -218,11 +218,29 @@ asmlinkage unsigned long get_overflow_stack(void)
+               OVERFLOW_STACK_SIZE;
+ }
++/*
++ * A pseudo spinlock to protect the shadow stack from being used by multiple
++ * harts concurrently.  This isn't a real spinlock because the lock side must
++ * be taken without a valid stack and only a single register, it's only taken
++ * while in the process of panicing anyway so the performance and error
++ * checking a proper spinlock gives us doesn't matter.
++ */
++unsigned long spin_shadow_stack;
++
+ asmlinkage void handle_bad_stack(struct pt_regs *regs)
+ {
+       unsigned long tsk_stk = (unsigned long)current->stack;
+       unsigned long ovf_stk = (unsigned long)this_cpu_ptr(overflow_stack);
++      /*
++       * We're done with the shadow stack by this point, as we're on the
++       * overflow stack.  Tell any other concurrent overflowing harts that
++       * they can proceed with panicing by releasing the pseudo-spinlock.
++       *
++       * This pairs with an amoswap.aq in handle_kernel_stack_overflow.
++       */
++      smp_store_release(&spin_shadow_stack, 0);
++
+       console_verbose();
+       pr_emerg("Insufficient stack space to handle exception!\n");
+-- 
+2.35.1
+
diff --git a/queue-5.15/riscv-kexec-fixup-crash_smp_send_stop-without-multi-.patch b/queue-5.15/riscv-kexec-fixup-crash_smp_send_stop-without-multi-.patch
new file mode 100644 (file)
index 0000000..dc3e369
--- /dev/null
@@ -0,0 +1,310 @@
+From 6ebd75a424f9beed695e0aae59ccfe91565c0953 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Oct 2022 10:16:03 -0400
+Subject: riscv: kexec: Fixup crash_smp_send_stop without multi cores
+
+From: Guo Ren <guoren@linux.alibaba.com>
+
+[ Upstream commit 9b932aadfc47de5d70b53ea04b0d1b5f6c82945b ]
+
+Current crash_smp_send_stop is the same as the generic one in
+kernel/panic and misses crash_save_cpu in percpu. This patch is inspired
+by 78fd584cdec0 ("arm64: kdump: implement machine_crash_shutdown()")
+and adds the same mechanism for riscv.
+
+Before this patch, test result:
+crash> help -r
+CPU 0: [OFFLINE]
+
+CPU 1:
+epc : ffffffff80009ff0 ra : ffffffff800b789a sp : ff2000001098bb40
+ gp : ffffffff815fca60 tp : ff60000004680000 t0 : 6666666666663c5b
+ t1 : 0000000000000000 t2 : 666666666666663c s0 : ff2000001098bc90
+ s1 : ffffffff81600798 a0 : ff2000001098bb48 a1 : 0000000000000000
+ a2 : 0000000000000000 a3 : 0000000000000001 a4 : 0000000000000000
+ a5 : ff60000004690800 a6 : 0000000000000000 a7 : 0000000000000000
+ s2 : ff2000001098bb48 s3 : ffffffff81093ec8 s4 : ffffffff816004ac
+ s5 : 0000000000000000 s6 : 0000000000000007 s7 : ffffffff80e7f720
+ s8 : 00fffffffffff3f0 s9 : 0000000000000007 s10: 00aaaaaaaab98700
+ s11: 0000000000000001 t3 : ffffffff819a8097 t4 : ffffffff819a8097
+ t5 : ffffffff819a8098 t6 : ff2000001098b9a8
+
+CPU 2: [OFFLINE]
+
+CPU 3: [OFFLINE]
+
+After this patch, test result:
+crash> help -r
+CPU 0:
+epc : ffffffff80003f34 ra : ffffffff808caa7c sp : ffffffff81403eb0
+ gp : ffffffff815fcb48 tp : ffffffff81413400 t0 : 0000000000000000
+ t1 : 0000000000000000 t2 : 0000000000000000 s0 : ffffffff81403ec0
+ s1 : 0000000000000000 a0 : 0000000000000000 a1 : 0000000000000000
+ a2 : 0000000000000000 a3 : 0000000000000000 a4 : 0000000000000000
+ a5 : 0000000000000000 a6 : 0000000000000000 a7 : 0000000000000000
+ s2 : ffffffff816001c8 s3 : ffffffff81600370 s4 : ffffffff80c32e18
+ s5 : ffffffff819d3018 s6 : ffffffff810e2110 s7 : 0000000000000000
+ s8 : 0000000000000000 s9 : 0000000080039eac s10: 0000000000000000
+ s11: 0000000000000000 t3 : 0000000000000000 t4 : 0000000000000000
+ t5 : 0000000000000000 t6 : 0000000000000000
+
+CPU 1:
+epc : ffffffff80003f34 ra : ffffffff808caa7c sp : ff2000000068bf30
+ gp : ffffffff815fcb48 tp : ff6000000240d400 t0 : 0000000000000000
+ t1 : 0000000000000000 t2 : 0000000000000000 s0 : ff2000000068bf40
+ s1 : 0000000000000001 a0 : 0000000000000000 a1 : 0000000000000000
+ a2 : 0000000000000000 a3 : 0000000000000000 a4 : 0000000000000000
+ a5 : 0000000000000000 a6 : 0000000000000000 a7 : 0000000000000000
+ s2 : ffffffff816001c8 s3 : ffffffff81600370 s4 : ffffffff80c32e18
+ s5 : ffffffff819d3018 s6 : ffffffff810e2110 s7 : 0000000000000000
+ s8 : 0000000000000000 s9 : 0000000080039ea8 s10: 0000000000000000
+ s11: 0000000000000000 t3 : 0000000000000000 t4 : 0000000000000000
+ t5 : 0000000000000000 t6 : 0000000000000000
+
+CPU 2:
+epc : ffffffff80003f34 ra : ffffffff808caa7c sp : ff20000000693f30
+ gp : ffffffff815fcb48 tp : ff6000000240e900 t0 : 0000000000000000
+ t1 : 0000000000000000 t2 : 0000000000000000 s0 : ff20000000693f40
+ s1 : 0000000000000002 a0 : 0000000000000000 a1 : 0000000000000000
+ a2 : 0000000000000000 a3 : 0000000000000000 a4 : 0000000000000000
+ a5 : 0000000000000000 a6 : 0000000000000000 a7 : 0000000000000000
+ s2 : ffffffff816001c8 s3 : ffffffff81600370 s4 : ffffffff80c32e18
+ s5 : ffffffff819d3018 s6 : ffffffff810e2110 s7 : 0000000000000000
+ s8 : 0000000000000000 s9 : 0000000080039eb0 s10: 0000000000000000
+ s11: 0000000000000000 t3 : 0000000000000000 t4 : 0000000000000000
+ t5 : 0000000000000000 t6 : 0000000000000000
+
+CPU 3:
+epc : ffffffff8000a1e4 ra : ffffffff800b7bba sp : ff200000109bbb40
+ gp : ffffffff815fcb48 tp : ff6000000373aa00 t0 : 6666666666663c5b
+ t1 : 0000000000000000 t2 : 666666666666663c s0 : ff200000109bbc90
+ s1 : ffffffff816007a0 a0 : ff200000109bbb48 a1 : 0000000000000000
+ a2 : 0000000000000000 a3 : 0000000000000001 a4 : 0000000000000000
+ a5 : ff60000002c61c00 a6 : 0000000000000000 a7 : 0000000000000000
+ s2 : ff200000109bbb48 s3 : ffffffff810941a8 s4 : ffffffff816004b4
+ s5 : 0000000000000000 s6 : 0000000000000007 s7 : ffffffff80e7f7a0
+ s8 : 00fffffffffff3f0 s9 : 0000000000000007 s10: 00aaaaaaaab98700
+ s11: 0000000000000001 t3 : ffffffff819a8097 t4 : ffffffff819a8097
+ t5 : ffffffff819a8098 t6 : ff200000109bb9a8
+
+Fixes: ad943893d5f1 ("RISC-V: Fixup schedule out issue in machine_crash_shutdown()")
+Reviewed-by: Xianting Tian <xianting.tian@linux.alibaba.com>
+Signed-off-by: Guo Ren <guoren@linux.alibaba.com>
+Signed-off-by: Guo Ren <guoren@kernel.org>
+Cc: Nick Kossifidis <mick@ics.forth.gr>
+Link: https://lore.kernel.org/r/20221020141603.2856206-3-guoren@kernel.org
+Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/riscv/include/asm/smp.h      |  3 +
+ arch/riscv/kernel/machine_kexec.c | 21 ++-----
+ arch/riscv/kernel/smp.c           | 93 ++++++++++++++++++++++++++++++-
+ 3 files changed, 100 insertions(+), 17 deletions(-)
+
+diff --git a/arch/riscv/include/asm/smp.h b/arch/riscv/include/asm/smp.h
+index 62d0e6e61da8..b29f2a79b636 100644
+--- a/arch/riscv/include/asm/smp.h
++++ b/arch/riscv/include/asm/smp.h
+@@ -50,6 +50,9 @@ void riscv_set_ipi_ops(const struct riscv_ipi_ops *ops);
+ /* Clear IPI for current CPU */
+ void riscv_clear_ipi(void);
++/* Check other CPUs stop or not */
++bool smp_crash_stop_failed(void);
++
+ /* Secondary hart entry */
+ asmlinkage void smp_callin(void);
+diff --git a/arch/riscv/kernel/machine_kexec.c b/arch/riscv/kernel/machine_kexec.c
+index db41c676e5a2..2d139b724bc8 100644
+--- a/arch/riscv/kernel/machine_kexec.c
++++ b/arch/riscv/kernel/machine_kexec.c
+@@ -140,22 +140,6 @@ void machine_shutdown(void)
+ #endif
+ }
+-/* Override the weak function in kernel/panic.c */
+-void crash_smp_send_stop(void)
+-{
+-      static int cpus_stopped;
+-
+-      /*
+-       * This function can be called twice in panic path, but obviously
+-       * we execute this only once.
+-       */
+-      if (cpus_stopped)
+-              return;
+-
+-      smp_send_stop();
+-      cpus_stopped = 1;
+-}
+-
+ static void machine_kexec_mask_interrupts(void)
+ {
+       unsigned int i;
+@@ -230,6 +214,11 @@ machine_kexec(struct kimage *image)
+       void *control_code_buffer = page_address(image->control_code_page);
+       riscv_kexec_method kexec_method = NULL;
++#ifdef CONFIG_SMP
++      WARN(smp_crash_stop_failed(),
++              "Some CPUs may be stale, kdump will be unreliable.\n");
++#endif
++
+       if (image->type != KEXEC_TYPE_CRASH)
+               kexec_method = control_code_buffer;
+       else
+diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c
+index d0147294691d..3155387ca82d 100644
+--- a/arch/riscv/kernel/smp.c
++++ b/arch/riscv/kernel/smp.c
+@@ -12,6 +12,7 @@
+ #include <linux/clockchips.h>
+ #include <linux/interrupt.h>
+ #include <linux/module.h>
++#include <linux/kexec.h>
+ #include <linux/profile.h>
+ #include <linux/smp.h>
+ #include <linux/sched.h>
+@@ -22,11 +23,13 @@
+ #include <asm/sbi.h>
+ #include <asm/tlbflush.h>
+ #include <asm/cacheflush.h>
++#include <asm/cpu_ops.h>
+ enum ipi_message_type {
+       IPI_RESCHEDULE,
+       IPI_CALL_FUNC,
+       IPI_CPU_STOP,
++      IPI_CPU_CRASH_STOP,
+       IPI_IRQ_WORK,
+       IPI_TIMER,
+       IPI_MAX
+@@ -77,6 +80,32 @@ static void ipi_stop(void)
+               wait_for_interrupt();
+ }
++#ifdef CONFIG_KEXEC_CORE
++static atomic_t waiting_for_crash_ipi = ATOMIC_INIT(0);
++
++static inline void ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *regs)
++{
++      crash_save_cpu(regs, cpu);
++
++      atomic_dec(&waiting_for_crash_ipi);
++
++      local_irq_disable();
++
++#ifdef CONFIG_HOTPLUG_CPU
++      if (cpu_has_hotplug(cpu))
++              cpu_ops[cpu]->cpu_stop();
++#endif
++
++      for(;;)
++              wait_for_interrupt();
++}
++#else
++static inline void ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *regs)
++{
++      unreachable();
++}
++#endif
++
+ static const struct riscv_ipi_ops *ipi_ops __ro_after_init;
+ void riscv_set_ipi_ops(const struct riscv_ipi_ops *ops)
+@@ -130,7 +159,6 @@ void arch_irq_work_raise(void)
+ void handle_IPI(struct pt_regs *regs)
+ {
+-      struct pt_regs *old_regs = set_irq_regs(regs);
+       unsigned long *pending_ipis = &ipi_data[smp_processor_id()].bits;
+       unsigned long *stats = ipi_data[smp_processor_id()].stats;
+@@ -163,6 +191,10 @@ void handle_IPI(struct pt_regs *regs)
+                       ipi_stop();
+               }
++              if (ops & (1 << IPI_CPU_CRASH_STOP)) {
++                      ipi_cpu_crash_stop(cpu, get_irq_regs());
++              }
++
+               if (ops & (1 << IPI_IRQ_WORK)) {
+                       stats[IPI_IRQ_WORK]++;
+                       irq_work_run();
+@@ -189,6 +221,7 @@ static const char * const ipi_names[] = {
+       [IPI_RESCHEDULE]        = "Rescheduling interrupts",
+       [IPI_CALL_FUNC]         = "Function call interrupts",
+       [IPI_CPU_STOP]          = "CPU stop interrupts",
++      [IPI_CPU_CRASH_STOP]    = "CPU stop (for crash dump) interrupts",
+       [IPI_IRQ_WORK]          = "IRQ work interrupts",
+       [IPI_TIMER]             = "Timer broadcast interrupts",
+ };
+@@ -248,6 +281,64 @@ void smp_send_stop(void)
+                          cpumask_pr_args(cpu_online_mask));
+ }
++#ifdef CONFIG_KEXEC_CORE
++/*
++ * The number of CPUs online, not counting this CPU (which may not be
++ * fully online and so not counted in num_online_cpus()).
++ */
++static inline unsigned int num_other_online_cpus(void)
++{
++      unsigned int this_cpu_online = cpu_online(smp_processor_id());
++
++      return num_online_cpus() - this_cpu_online;
++}
++
++void crash_smp_send_stop(void)
++{
++      static int cpus_stopped;
++      cpumask_t mask;
++      unsigned long timeout;
++
++      /*
++       * This function can be called twice in panic path, but obviously
++       * we execute this only once.
++       */
++      if (cpus_stopped)
++              return;
++
++      cpus_stopped = 1;
++
++      /*
++       * If this cpu is the only one alive at this point in time, online or
++       * not, there are no stop messages to be sent around, so just back out.
++       */
++      if (num_other_online_cpus() == 0)
++              return;
++
++      cpumask_copy(&mask, cpu_online_mask);
++      cpumask_clear_cpu(smp_processor_id(), &mask);
++
++      atomic_set(&waiting_for_crash_ipi, num_other_online_cpus());
++
++      pr_crit("SMP: stopping secondary CPUs\n");
++      send_ipi_mask(&mask, IPI_CPU_CRASH_STOP);
++
++      /* Wait up to one second for other CPUs to stop */
++      timeout = USEC_PER_SEC;
++      while ((atomic_read(&waiting_for_crash_ipi) > 0) && timeout--)
++              udelay(1);
++
++      if (atomic_read(&waiting_for_crash_ipi) > 0)
++              pr_warn("SMP: failed to stop secondary CPUs %*pbl\n",
++                      cpumask_pr_args(&mask));
++}
++
++bool smp_crash_stop_failed(void)
++{
++      return (atomic_read(&waiting_for_crash_ipi) > 0);
++}
++#endif
++
+ void smp_send_reschedule(int cpu)
+ {
+       send_ipi_single(cpu, IPI_RESCHEDULE);
+-- 
+2.35.1
+
diff --git a/queue-5.15/riscv-kexec-fixup-irq-controller-broken-in-kexec-cra.patch b/queue-5.15/riscv-kexec-fixup-irq-controller-broken-in-kexec-cra.patch
new file mode 100644 (file)
index 0000000..d79f182
--- /dev/null
@@ -0,0 +1,93 @@
+From 3c624bc126a7ee77af1fd450bdd732f060dd32cb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Oct 2022 10:16:02 -0400
+Subject: riscv: kexec: Fixup irq controller broken in kexec crash path
+
+From: Guo Ren <guoren@linux.alibaba.com>
+
+[ Upstream commit b17d19a5314a37f7197afd1a0200affd21a7227d ]
+
+If a crash happens on cpu3 and all interrupts are binding on cpu0, the
+bad irq routing will cause a crash kernel which can't receive any irq.
+Because crash kernel won't clean up all harts' PLIC enable bits in
+enable registers. This patch is similar to 9141a003a491 ("ARM: 7316/1:
+kexec: EOI active and mask all interrupts in kexec crash path") and
+78fd584cdec0 ("arm64: kdump: implement machine_crash_shutdown()"), and
+PowerPC also has the same mechanism.
+
+Fixes: fba8a8674f68 ("RISC-V: Add kexec support")
+Signed-off-by: Guo Ren <guoren@linux.alibaba.com>
+Signed-off-by: Guo Ren <guoren@kernel.org>
+Reviewed-by: Xianting Tian <xianting.tian@linux.alibaba.com>
+Cc: Nick Kossifidis <mick@ics.forth.gr>
+Cc: Palmer Dabbelt <palmer@rivosinc.com>
+Link: https://lore.kernel.org/r/20221020141603.2856206-2-guoren@kernel.org
+Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/riscv/kernel/machine_kexec.c | 35 +++++++++++++++++++++++++++++++
+ 1 file changed, 35 insertions(+)
+
+diff --git a/arch/riscv/kernel/machine_kexec.c b/arch/riscv/kernel/machine_kexec.c
+index ee79e6839b86..db41c676e5a2 100644
+--- a/arch/riscv/kernel/machine_kexec.c
++++ b/arch/riscv/kernel/machine_kexec.c
+@@ -15,6 +15,8 @@
+ #include <linux/compiler.h>   /* For unreachable() */
+ #include <linux/cpu.h>                /* For cpu_down() */
+ #include <linux/reboot.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
+ /*
+  * kexec_image_info - Print received image details
+@@ -154,6 +156,37 @@ void crash_smp_send_stop(void)
+       cpus_stopped = 1;
+ }
++static void machine_kexec_mask_interrupts(void)
++{
++      unsigned int i;
++      struct irq_desc *desc;
++
++      for_each_irq_desc(i, desc) {
++              struct irq_chip *chip;
++              int ret;
++
++              chip = irq_desc_get_chip(desc);
++              if (!chip)
++                      continue;
++
++              /*
++               * First try to remove the active state. If this
++               * fails, try to EOI the interrupt.
++               */
++              ret = irq_set_irqchip_state(i, IRQCHIP_STATE_ACTIVE, false);
++
++              if (ret && irqd_irq_inprogress(&desc->irq_data) &&
++                  chip->irq_eoi)
++                      chip->irq_eoi(&desc->irq_data);
++
++              if (chip->irq_mask)
++                      chip->irq_mask(&desc->irq_data);
++
++              if (chip->irq_disable && !irqd_irq_disabled(&desc->irq_data))
++                      chip->irq_disable(&desc->irq_data);
++      }
++}
++
+ /*
+  * machine_crash_shutdown - Prepare to kexec after a kernel crash
+  *
+@@ -169,6 +202,8 @@ machine_crash_shutdown(struct pt_regs *regs)
+       crash_smp_send_stop();
+       crash_save_cpu(regs, smp_processor_id());
++      machine_kexec_mask_interrupts();
++
+       pr_info("Starting crashdump kernel...\n");
+ }
+-- 
+2.35.1
+
diff --git a/queue-5.15/riscv-sync-efi-page-table-s-kernel-mappings-before-s.patch b/queue-5.15/riscv-sync-efi-page-table-s-kernel-mappings-before-s.patch
new file mode 100644 (file)
index 0000000..6fe647b
--- /dev/null
@@ -0,0 +1,87 @@
+From 309a70fdc593c39652d53e29effdfc8de757dd9d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Nov 2022 14:33:03 +0100
+Subject: riscv: Sync efi page table's kernel mappings before switching
+
+From: Alexandre Ghiti <alexghiti@rivosinc.com>
+
+[ Upstream commit 3f105a742725a1b78766a55169f1d827732e62b8 ]
+
+The EFI page table is initially created as a copy of the kernel page table.
+With VMAP_STACK enabled, kernel stacks are allocated in the vmalloc area:
+if the stack is allocated in a new PGD (one that was not present at the
+moment of the efi page table creation or not synced in a previous vmalloc
+fault), the kernel will take a trap when switching to the efi page table
+when the vmalloc kernel stack is accessed, resulting in a kernel panic.
+
+Fix that by updating the efi kernel mappings before switching to the efi
+page table.
+
+Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
+Fixes: b91540d52a08 ("RISC-V: Add EFI runtime services")
+Tested-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
+Reviewed-by: Atish Patra <atishp@rivosinc.com>
+Link: https://lore.kernel.org/r/20221121133303.1782246-1-alexghiti@rivosinc.com
+Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/riscv/include/asm/efi.h     |  6 +++++-
+ arch/riscv/include/asm/pgalloc.h | 11 ++++++++---
+ 2 files changed, 13 insertions(+), 4 deletions(-)
+
+diff --git a/arch/riscv/include/asm/efi.h b/arch/riscv/include/asm/efi.h
+index cc4f6787f937..1bb8662875dd 100644
+--- a/arch/riscv/include/asm/efi.h
++++ b/arch/riscv/include/asm/efi.h
+@@ -10,6 +10,7 @@
+ #include <asm/mmu_context.h>
+ #include <asm/ptrace.h>
+ #include <asm/tlbflush.h>
++#include <asm/pgalloc.h>
+ #ifdef CONFIG_EFI
+ extern void efi_init(void);
+@@ -20,7 +21,10 @@ extern void efi_init(void);
+ int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);
+ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);
+-#define arch_efi_call_virt_setup()      efi_virtmap_load()
++#define arch_efi_call_virt_setup()      ({            \
++              sync_kernel_mappings(efi_mm.pgd);       \
++              efi_virtmap_load();                     \
++      })
+ #define arch_efi_call_virt_teardown()   efi_virtmap_unload()
+ #define arch_efi_call_virt(p, f, args...) p->f(args)
+diff --git a/arch/riscv/include/asm/pgalloc.h b/arch/riscv/include/asm/pgalloc.h
+index 0af6933a7100..98e040332482 100644
+--- a/arch/riscv/include/asm/pgalloc.h
++++ b/arch/riscv/include/asm/pgalloc.h
+@@ -38,6 +38,13 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
+ }
+ #endif /* __PAGETABLE_PMD_FOLDED */
++static inline void sync_kernel_mappings(pgd_t *pgd)
++{
++      memcpy(pgd + USER_PTRS_PER_PGD,
++             init_mm.pgd + USER_PTRS_PER_PGD,
++             (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
++}
++
+ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+ {
+       pgd_t *pgd;
+@@ -46,9 +53,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+       if (likely(pgd != NULL)) {
+               memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
+               /* Copy kernel mappings */
+-              memcpy(pgd + USER_PTRS_PER_PGD,
+-                      init_mm.pgd + USER_PTRS_PER_PGD,
+-                      (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
++              sync_kernel_mappings(pgd);
+       }
+       return pgd;
+ }
+-- 
+2.35.1
+
diff --git a/queue-5.15/selftests-net-add-delete-nexthop-route-warning-test.patch b/queue-5.15/selftests-net-add-delete-nexthop-route-warning-test.patch
new file mode 100644 (file)
index 0000000..7706aba
--- /dev/null
@@ -0,0 +1,60 @@
+From 511036bf8e01983a3a86305d45eaadd36a599df9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 1 Apr 2022 10:33:43 +0300
+Subject: selftests: net: add delete nexthop route warning test
+
+From: Nikolay Aleksandrov <razor@blackwall.org>
+
+[ Upstream commit 392baa339c6a42a2cb088e5e5df2b59b8f89be24 ]
+
+Add a test which causes a WARNING on kernels which treat a
+nexthop route like a normal route when comparing for deletion and a
+device is specified. That is, a route is found but we hit a warning while
+matching it. The warning is from fib_info_nh() in include/net/nexthop.h
+because we run it on a fib_info with nexthop object. The call chain is:
+ inet_rtm_delroute -> fib_table_delete -> fib_nh_match (called with a
+nexthop fib_info and also with fc_oif set thus calling fib_info_nh on
+the fib_info and triggering the warning).
+
+Repro steps:
+ $ ip nexthop add id 12 via 172.16.1.3 dev veth1
+ $ ip route add 172.16.101.1/32 nhid 12
+ $ ip route delete 172.16.101.1/32 dev veth1
+
+Signed-off-by: Nikolay Aleksandrov <razor@blackwall.org>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: d5082d386eee ("ipv4: Fix route deletion when nexthop info is not specified")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/net/fib_nexthops.sh | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/tools/testing/selftests/net/fib_nexthops.sh b/tools/testing/selftests/net/fib_nexthops.sh
+index b5a69ad191b0..d1257a321ced 100755
+--- a/tools/testing/selftests/net/fib_nexthops.sh
++++ b/tools/testing/selftests/net/fib_nexthops.sh
+@@ -1145,6 +1145,20 @@ ipv4_fcnal()
+       set +e
+       check_nexthop "dev veth1" ""
+       log_test $? 0 "Nexthops removed on admin down"
++
++      # nexthop route delete warning: route add with nhid and delete
++      # using device
++      run_cmd "$IP li set dev veth1 up"
++      run_cmd "$IP nexthop add id 12 via 172.16.1.3 dev veth1"
++      out1=`dmesg | grep "WARNING:.*fib_nh_match.*" | wc -l`
++      run_cmd "$IP route add 172.16.101.1/32 nhid 12"
++      run_cmd "$IP route delete 172.16.101.1/32 dev veth1"
++      out2=`dmesg | grep "WARNING:.*fib_nh_match.*" | wc -l`
++      [ $out1 -eq $out2 ]
++      rc=$?
++      log_test $rc 0 "Delete nexthop route warning"
++      run_cmd "$IP ip route delete 172.16.101.1/32 nhid 12"
++      run_cmd "$IP ip nexthop del id 12"
+ }
+ ipv4_grp_fcnal()
+-- 
+2.35.1
+
diff --git a/queue-5.15/selftests-net-fix-nexthop-warning-cleanup-double-ip-.patch b/queue-5.15/selftests-net-fix-nexthop-warning-cleanup-double-ip-.patch
new file mode 100644 (file)
index 0000000..b2e9e7d
--- /dev/null
@@ -0,0 +1,41 @@
+From 005c1ec8ee95ecfbc9f192bfb25b92a4f23fb52f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 1 Apr 2022 18:54:27 +0300
+Subject: selftests: net: fix nexthop warning cleanup double ip typo
+
+From: Nikolay Aleksandrov <razor@blackwall.org>
+
+[ Upstream commit 692930cc435099580a4b9e32fa781b0688c18439 ]
+
+I made a stupid typo when adding the nexthop route warning selftest and
+added both $IP and ip after it (double ip) on the cleanup path. The
+error doesn't show up when running the test, but obviously it doesn't
+cleanup properly after it.
+
+Fixes: 392baa339c6a ("selftests: net: add delete nexthop route warning test")
+Signed-off-by: Nikolay Aleksandrov <razor@blackwall.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: d5082d386eee ("ipv4: Fix route deletion when nexthop info is not specified")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/net/fib_nexthops.sh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/tools/testing/selftests/net/fib_nexthops.sh b/tools/testing/selftests/net/fib_nexthops.sh
+index d1257a321ced..4afc4b20c546 100755
+--- a/tools/testing/selftests/net/fib_nexthops.sh
++++ b/tools/testing/selftests/net/fib_nexthops.sh
+@@ -1157,8 +1157,8 @@ ipv4_fcnal()
+       [ $out1 -eq $out2 ]
+       rc=$?
+       log_test $rc 0 "Delete nexthop route warning"
+-      run_cmd "$IP ip route delete 172.16.101.1/32 nhid 12"
+-      run_cmd "$IP ip nexthop del id 12"
++      run_cmd "$IP route delete 172.16.101.1/32 nhid 12"
++      run_cmd "$IP nexthop del id 12"
+ }
+ ipv4_grp_fcnal()
+-- 
+2.35.1
+
diff --git a/queue-5.15/serial-stm32-deassert-transmit-enable-on-rs485_confi.patch b/queue-5.15/serial-stm32-deassert-transmit-enable-on-rs485_confi.patch
new file mode 100644 (file)
index 0000000..0b430b5
--- /dev/null
@@ -0,0 +1,172 @@
+From 19a4090f1b6ab594e732c6b8f91089128063a8a9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 11 Sep 2022 11:02:03 +0200
+Subject: serial: stm32: Deassert Transmit Enable on ->rs485_config()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Lukas Wunner <lukas@wunner.de>
+
+[ Upstream commit adafbbf6895eb0ce41a313c6ee68870ab9aa93cd ]
+
+The STM32 USART can control RS-485 Transmit Enable in hardware.  Since
+commit 7df5081cbf5e ("serial: stm32: Add RS485 RTS GPIO control"),
+it can alternatively be controlled in software.  That was done to allow
+RS-485 even if the RTS pin is unavailable because it's pinmuxed to a
+different function.
+
+However the commit neglected to deassert Transmit Enable upon invocation
+of the ->rs485_config() callback.  Fix it.
+
+Avoid forward declarations by moving stm32_usart_tx_empty(),
+stm32_usart_rs485_rts_enable() and stm32_usart_rs485_rts_disable()
+further up in the driver.
+
+Fixes: 7df5081cbf5e ("serial: stm32: Add RS485 RTS GPIO control")
+Cc: stable@vger.kernel.org # v5.9+
+Cc: Marek Vasut <marex@denx.de>
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Link: https://lore.kernel.org/r/6059eab35dba394468335ef640df8b0050fd9dbd.1662886616.git.lukas@wunner.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/stm32-usart.c | 100 ++++++++++++++++---------------
+ 1 file changed, 53 insertions(+), 47 deletions(-)
+
+diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
+index 86f044a96de1..ce7ff7a0207f 100644
+--- a/drivers/tty/serial/stm32-usart.c
++++ b/drivers/tty/serial/stm32-usart.c
+@@ -61,6 +61,53 @@ static void stm32_usart_clr_bits(struct uart_port *port, u32 reg, u32 bits)
+       writel_relaxed(val, port->membase + reg);
+ }
++static unsigned int stm32_usart_tx_empty(struct uart_port *port)
++{
++      struct stm32_port *stm32_port = to_stm32_port(port);
++      const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
++
++      if (readl_relaxed(port->membase + ofs->isr) & USART_SR_TC)
++              return TIOCSER_TEMT;
++
++      return 0;
++}
++
++static void stm32_usart_rs485_rts_enable(struct uart_port *port)
++{
++      struct stm32_port *stm32_port = to_stm32_port(port);
++      struct serial_rs485 *rs485conf = &port->rs485;
++
++      if (stm32_port->hw_flow_control ||
++          !(rs485conf->flags & SER_RS485_ENABLED))
++              return;
++
++      if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
++              mctrl_gpio_set(stm32_port->gpios,
++                             stm32_port->port.mctrl | TIOCM_RTS);
++      } else {
++              mctrl_gpio_set(stm32_port->gpios,
++                             stm32_port->port.mctrl & ~TIOCM_RTS);
++      }
++}
++
++static void stm32_usart_rs485_rts_disable(struct uart_port *port)
++{
++      struct stm32_port *stm32_port = to_stm32_port(port);
++      struct serial_rs485 *rs485conf = &port->rs485;
++
++      if (stm32_port->hw_flow_control ||
++          !(rs485conf->flags & SER_RS485_ENABLED))
++              return;
++
++      if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
++              mctrl_gpio_set(stm32_port->gpios,
++                             stm32_port->port.mctrl & ~TIOCM_RTS);
++      } else {
++              mctrl_gpio_set(stm32_port->gpios,
++                             stm32_port->port.mctrl | TIOCM_RTS);
++      }
++}
++
+ static void stm32_usart_config_reg_rs485(u32 *cr1, u32 *cr3, u32 delay_ADE,
+                                        u32 delay_DDE, u32 baud)
+ {
+@@ -149,6 +196,12 @@ static int stm32_usart_config_rs485(struct uart_port *port,
+       stm32_usart_set_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit));
++      /* Adjust RTS polarity in case it's driven in software */
++      if (stm32_usart_tx_empty(port))
++              stm32_usart_rs485_rts_disable(port);
++      else
++              stm32_usart_rs485_rts_enable(port);
++
+       return 0;
+ }
+@@ -341,42 +394,6 @@ static void stm32_usart_tc_interrupt_disable(struct uart_port *port)
+       stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_TCIE);
+ }
+-static void stm32_usart_rs485_rts_enable(struct uart_port *port)
+-{
+-      struct stm32_port *stm32_port = to_stm32_port(port);
+-      struct serial_rs485 *rs485conf = &port->rs485;
+-
+-      if (stm32_port->hw_flow_control ||
+-          !(rs485conf->flags & SER_RS485_ENABLED))
+-              return;
+-
+-      if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
+-              mctrl_gpio_set(stm32_port->gpios,
+-                             stm32_port->port.mctrl | TIOCM_RTS);
+-      } else {
+-              mctrl_gpio_set(stm32_port->gpios,
+-                             stm32_port->port.mctrl & ~TIOCM_RTS);
+-      }
+-}
+-
+-static void stm32_usart_rs485_rts_disable(struct uart_port *port)
+-{
+-      struct stm32_port *stm32_port = to_stm32_port(port);
+-      struct serial_rs485 *rs485conf = &port->rs485;
+-
+-      if (stm32_port->hw_flow_control ||
+-          !(rs485conf->flags & SER_RS485_ENABLED))
+-              return;
+-
+-      if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
+-              mctrl_gpio_set(stm32_port->gpios,
+-                             stm32_port->port.mctrl & ~TIOCM_RTS);
+-      } else {
+-              mctrl_gpio_set(stm32_port->gpios,
+-                             stm32_port->port.mctrl | TIOCM_RTS);
+-      }
+-}
+-
+ static void stm32_usart_transmit_chars_pio(struct uart_port *port)
+ {
+       struct stm32_port *stm32_port = to_stm32_port(port);
+@@ -590,17 +607,6 @@ static irqreturn_t stm32_usart_threaded_interrupt(int irq, void *ptr)
+       return IRQ_HANDLED;
+ }
+-static unsigned int stm32_usart_tx_empty(struct uart_port *port)
+-{
+-      struct stm32_port *stm32_port = to_stm32_port(port);
+-      const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
+-
+-      if (readl_relaxed(port->membase + ofs->isr) & USART_SR_TC)
+-              return TIOCSER_TEMT;
+-
+-      return 0;
+-}
+-
+ static void stm32_usart_set_mctrl(struct uart_port *port, unsigned int mctrl)
+ {
+       struct stm32_port *stm32_port = to_stm32_port(port);
+-- 
+2.35.1
+
diff --git a/queue-5.15/serial-stm32-factor-out-gpio-rts-toggling-into-separ.patch b/queue-5.15/serial-stm32-factor-out-gpio-rts-toggling-into-separ.patch
new file mode 100644 (file)
index 0000000..bf7a727
--- /dev/null
@@ -0,0 +1,122 @@
+From 8f1a30ca6d33b347dc53e44ab33ca88ce364b761 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 30 Apr 2022 18:28:44 +0200
+Subject: serial: stm32: Factor out GPIO RTS toggling into separate function
+
+From: Marek Vasut <marex@denx.de>
+
+[ Upstream commit 3bcea529b295a993b1b05db63f245ae8030c5acf ]
+
+Pull out the GPIO RTS enable and disable handling into separate function.
+Limit the scope of GPIO RTS toggling only to GPIO emulated RS485 too.
+
+Signed-off-by: Marek Vasut <marex@denx.de>
+Cc: Alexandre Torgue <alexandre.torgue@foss.st.com>
+Cc: Erwan Le Ray <erwan.leray@foss.st.com>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Jean Philippe Romain <jean-philippe.romain@foss.st.com>
+Cc: Valentin Caron <valentin.caron@foss.st.com>
+Cc: linux-arm-kernel@lists.infradead.org
+Cc: linux-stm32@st-md-mailman.stormreply.com
+To: linux-serial@vger.kernel.org
+Link: https://lore.kernel.org/r/20220430162845.244655-1-marex@denx.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/stm32-usart.c | 61 ++++++++++++++++++++------------
+ 1 file changed, 38 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
+index fc166cc2c856..f2cef5f7ae5a 100644
+--- a/drivers/tty/serial/stm32-usart.c
++++ b/drivers/tty/serial/stm32-usart.c
+@@ -325,6 +325,42 @@ static void stm32_usart_tx_interrupt_disable(struct uart_port *port)
+               stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_TXEIE);
+ }
++static void stm32_usart_rs485_rts_enable(struct uart_port *port)
++{
++      struct stm32_port *stm32_port = to_stm32_port(port);
++      struct serial_rs485 *rs485conf = &port->rs485;
++
++      if (stm32_port->hw_flow_control ||
++          !(rs485conf->flags & SER_RS485_ENABLED))
++              return;
++
++      if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
++              mctrl_gpio_set(stm32_port->gpios,
++                             stm32_port->port.mctrl | TIOCM_RTS);
++      } else {
++              mctrl_gpio_set(stm32_port->gpios,
++                             stm32_port->port.mctrl & ~TIOCM_RTS);
++      }
++}
++
++static void stm32_usart_rs485_rts_disable(struct uart_port *port)
++{
++      struct stm32_port *stm32_port = to_stm32_port(port);
++      struct serial_rs485 *rs485conf = &port->rs485;
++
++      if (stm32_port->hw_flow_control ||
++          !(rs485conf->flags & SER_RS485_ENABLED))
++              return;
++
++      if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
++              mctrl_gpio_set(stm32_port->gpios,
++                             stm32_port->port.mctrl & ~TIOCM_RTS);
++      } else {
++              mctrl_gpio_set(stm32_port->gpios,
++                             stm32_port->port.mctrl | TIOCM_RTS);
++      }
++}
++
+ static void stm32_usart_transmit_chars_pio(struct uart_port *port)
+ {
+       struct stm32_port *stm32_port = to_stm32_port(port);
+@@ -566,41 +602,20 @@ static void stm32_usart_disable_ms(struct uart_port *port)
+ /* Transmit stop */
+ static void stm32_usart_stop_tx(struct uart_port *port)
+ {
+-      struct stm32_port *stm32_port = to_stm32_port(port);
+-      struct serial_rs485 *rs485conf = &port->rs485;
+-
+       stm32_usart_tx_interrupt_disable(port);
+-      if (rs485conf->flags & SER_RS485_ENABLED) {
+-              if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
+-                      mctrl_gpio_set(stm32_port->gpios,
+-                                      stm32_port->port.mctrl & ~TIOCM_RTS);
+-              } else {
+-                      mctrl_gpio_set(stm32_port->gpios,
+-                                      stm32_port->port.mctrl | TIOCM_RTS);
+-              }
+-      }
++      stm32_usart_rs485_rts_disable(port);
+ }
+ /* There are probably characters waiting to be transmitted. */
+ static void stm32_usart_start_tx(struct uart_port *port)
+ {
+-      struct stm32_port *stm32_port = to_stm32_port(port);
+-      struct serial_rs485 *rs485conf = &port->rs485;
+       struct circ_buf *xmit = &port->state->xmit;
+       if (uart_circ_empty(xmit) && !port->x_char)
+               return;
+-      if (rs485conf->flags & SER_RS485_ENABLED) {
+-              if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
+-                      mctrl_gpio_set(stm32_port->gpios,
+-                                      stm32_port->port.mctrl | TIOCM_RTS);
+-              } else {
+-                      mctrl_gpio_set(stm32_port->gpios,
+-                                      stm32_port->port.mctrl & ~TIOCM_RTS);
+-              }
+-      }
++      stm32_usart_rs485_rts_enable(port);
+       stm32_usart_transmit_chars(port);
+ }
+-- 
+2.35.1
+
diff --git a/queue-5.15/serial-stm32-use-tc-interrupt-to-deassert-gpio-rts-i.patch b/queue-5.15/serial-stm32-use-tc-interrupt-to-deassert-gpio-rts-i.patch
new file mode 100644 (file)
index 0000000..04f4d71
--- /dev/null
@@ -0,0 +1,135 @@
+From ebe3c928daac036c01cefe5e671141ba2e19703a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 30 Apr 2022 18:28:45 +0200
+Subject: serial: stm32: Use TC interrupt to deassert GPIO RTS in RS485 mode
+
+From: Marek Vasut <marex@denx.de>
+
+[ Upstream commit d7c76716169ddc37cf6316ff381d34ea807fbfd7 ]
+
+In case the RS485 mode is emulated using GPIO RTS, use the TC interrupt
+to deassert the GPIO RTS, otherwise the GPIO RTS stays asserted after a
+transmission ended and the RS485 cannot work.
+
+Signed-off-by: Marek Vasut <marex@denx.de>
+Cc: Alexandre Torgue <alexandre.torgue@foss.st.com>
+Cc: Erwan Le Ray <erwan.leray@foss.st.com>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Jean Philippe Romain <jean-philippe.romain@foss.st.com>
+Cc: Valentin Caron <valentin.caron@foss.st.com>
+Cc: linux-arm-kernel@lists.infradead.org
+Cc: linux-stm32@st-md-mailman.stormreply.com
+To: linux-serial@vger.kernel.org
+Link: https://lore.kernel.org/r/20220430162845.244655-2-marex@denx.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/stm32-usart.c | 42 ++++++++++++++++++++++++++++++--
+ drivers/tty/serial/stm32-usart.h |  1 +
+ 2 files changed, 41 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
+index f2cef5f7ae5a..86f044a96de1 100644
+--- a/drivers/tty/serial/stm32-usart.c
++++ b/drivers/tty/serial/stm32-usart.c
+@@ -314,6 +314,14 @@ static void stm32_usart_tx_interrupt_enable(struct uart_port *port)
+               stm32_usart_set_bits(port, ofs->cr1, USART_CR1_TXEIE);
+ }
++static void stm32_usart_tc_interrupt_enable(struct uart_port *port)
++{
++      struct stm32_port *stm32_port = to_stm32_port(port);
++      const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
++
++      stm32_usart_set_bits(port, ofs->cr1, USART_CR1_TCIE);
++}
++
+ static void stm32_usart_tx_interrupt_disable(struct uart_port *port)
+ {
+       struct stm32_port *stm32_port = to_stm32_port(port);
+@@ -325,6 +333,14 @@ static void stm32_usart_tx_interrupt_disable(struct uart_port *port)
+               stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_TXEIE);
+ }
++static void stm32_usart_tc_interrupt_disable(struct uart_port *port)
++{
++      struct stm32_port *stm32_port = to_stm32_port(port);
++      const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
++
++      stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_TCIE);
++}
++
+ static void stm32_usart_rs485_rts_enable(struct uart_port *port)
+ {
+       struct stm32_port *stm32_port = to_stm32_port(port);
+@@ -462,6 +478,13 @@ static void stm32_usart_transmit_chars(struct uart_port *port)
+       u32 isr;
+       int ret;
++      if (!stm32_port->hw_flow_control &&
++          port->rs485.flags & SER_RS485_ENABLED) {
++              stm32_port->txdone = false;
++              stm32_usart_tc_interrupt_disable(port);
++              stm32_usart_rs485_rts_enable(port);
++      }
++
+       if (port->x_char) {
+               if (stm32_port->tx_dma_busy)
+                       stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
+@@ -501,8 +524,14 @@ static void stm32_usart_transmit_chars(struct uart_port *port)
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+               uart_write_wakeup(port);
+-      if (uart_circ_empty(xmit))
++      if (uart_circ_empty(xmit)) {
+               stm32_usart_tx_interrupt_disable(port);
++              if (!stm32_port->hw_flow_control &&
++                  port->rs485.flags & SER_RS485_ENABLED) {
++                      stm32_port->txdone = true;
++                      stm32_usart_tc_interrupt_enable(port);
++              }
++      }
+ }
+ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
+@@ -515,6 +544,13 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
+       sr = readl_relaxed(port->membase + ofs->isr);
++      if (!stm32_port->hw_flow_control &&
++          port->rs485.flags & SER_RS485_ENABLED &&
++          (sr & USART_SR_TC)) {
++              stm32_usart_tc_interrupt_disable(port);
++              stm32_usart_rs485_rts_disable(port);
++      }
++
+       if ((sr & USART_SR_RTOF) && ofs->icr != UNDEF_REG)
+               writel_relaxed(USART_ICR_RTOCF,
+                              port->membase + ofs->icr);
+@@ -612,8 +648,10 @@ static void stm32_usart_start_tx(struct uart_port *port)
+ {
+       struct circ_buf *xmit = &port->state->xmit;
+-      if (uart_circ_empty(xmit) && !port->x_char)
++      if (uart_circ_empty(xmit) && !port->x_char) {
++              stm32_usart_rs485_rts_disable(port);
+               return;
++      }
+       stm32_usart_rs485_rts_enable(port);
+diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h
+index 07ac291328cd..ad6335155de2 100644
+--- a/drivers/tty/serial/stm32-usart.h
++++ b/drivers/tty/serial/stm32-usart.h
+@@ -267,6 +267,7 @@ struct stm32_port {
+       bool hw_flow_control;
+       bool swap;               /* swap RX & TX pins */
+       bool fifoen;
++      bool txdone;
+       int rxftcfg;            /* RX FIFO threshold CFG      */
+       int txftcfg;            /* TX FIFO threshold CFG      */
+       bool wakeup_src;
+-- 
+2.35.1
+
index 29a3d25ca67aaaa3af24f7b192125f8f9b44440a..ef975df9662f156bad41385cc4f51ea679bd6512 100644 (file)
@@ -91,3 +91,23 @@ io_uring-cmpxchg-for-poll-arm-refs-release.patch
 io_uring-make-poll-refs-more-robust.patch
 io_uring-poll-fix-poll_refs-race-with-cancelation.patch
 kvm-x86-mmu-fix-race-condition-in-direct_page_fault.patch
+asoc-ops-fix-bounds-check-for-_sx-controls.patch
+pinctrl-single-fix-potential-division-by-zero.patch
+riscv-sync-efi-page-table-s-kernel-mappings-before-s.patch
+riscv-fix-race-when-vmap-stack-overflow.patch
+riscv-kexec-fixup-irq-controller-broken-in-kexec-cra.patch
+riscv-kexec-fixup-crash_smp_send_stop-without-multi-.patch
+nvme-fix-srcu-protection-of-nvme_ns_head-list.patch
+iommu-vt-d-fix-pci-device-refcount-leak-in-has_exter.patch
+iommu-vt-d-fix-pci-device-refcount-leak-in-dmar_dev_.patch
+mm-__isolate_lru_page_prepare-in-isolate_migratepage.patch
+mm-migrate-fix-thp-s-mapcount-on-isolation.patch
+parisc-increase-frame_warn-to-2048-bytes-on-parisc.patch
+kconfig.debug-provide-a-little-extra-frame_warn-leew.patch
+selftests-net-add-delete-nexthop-route-warning-test.patch
+selftests-net-fix-nexthop-warning-cleanup-double-ip-.patch
+ipv4-handle-attempt-to-delete-multipath-route-when-f.patch
+ipv4-fix-route-deletion-when-nexthop-info-is-not-spe.patch
+serial-stm32-factor-out-gpio-rts-toggling-into-separ.patch
+serial-stm32-use-tc-interrupt-to-deassert-gpio-rts-i.patch
+serial-stm32-deassert-transmit-enable-on-rs485_confi.patch