From: Sasha Levin Date: Sun, 4 Dec 2022 02:26:49 +0000 (-0500) Subject: Fixes for 5.15 X-Git-Tag: v4.9.335~57 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=53c3ccc7bb06596186dbf4074f4b4a486fe9ff82;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.15 Signed-off-by: Sasha Levin --- 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 index 00000000000..647a8a3c9f3 --- /dev/null +++ b/queue-5.15/asoc-ops-fix-bounds-check-for-_sx-controls.patch @@ -0,0 +1,39 @@ +From fe0bc28b7cf4f765ad2632f0f5947bfc10444c46 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 11 May 2022 14:41:36 +0100 +Subject: ASoC: ops: Fix bounds check for _sx controls + +From: Mark Brown + +[ 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 +Link: https://lore.kernel.org/r/20220511134137.169575-1-broonie@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..e0e26f76368 --- /dev/null +++ b/queue-5.15/iommu-vt-d-fix-pci-device-refcount-leak-in-dmar_dev_.patch @@ -0,0 +1,43 @@ +From 4855387092177c8f95cc4e1976f74f6f82d690b1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20221121113649.190393-3-wangxiongfeng2@huawei.com +Signed-off-by: Lu Baolu +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..a4205f604c8 --- /dev/null +++ b/queue-5.15/iommu-vt-d-fix-pci-device-refcount-leak-in-has_exter.patch @@ -0,0 +1,47 @@ +From 98d0ccdcd2a8cc412e0286cffb740e9cdf62f137 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20221121113649.190393-2-wangxiongfeng2@huawei.com +Signed-off-by: Lu Baolu +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..189dc3eec7a --- /dev/null +++ b/queue-5.15/ipv4-fix-route-deletion-when-nexthop-info-is-not-spe.patch @@ -0,0 +1,118 @@ +From d7be1e434afec50b15bb2a923c64eb2103d9f31f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Nov 2022 23:09:32 +0200 +Subject: ipv4: Fix route deletion when nexthop info is not specified + +From: Ido Schimmel + +[ 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 +Tested-by: Jonas Gorski +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 +Reviewed-by: Nikolay Aleksandrov +Reviewed-by: David Ahern +Link: https://lore.kernel.org/r/20221124210932.2470010-1-idosch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..5980bf7f424 --- /dev/null +++ b/queue-5.15/ipv4-handle-attempt-to-delete-multipath-route-when-f.patch @@ -0,0 +1,75 @@ +From 1aa0cf3032041bd7f09fc507e0185cc2f4e976c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: David Ahern +Reviewed-by: Ido Schimmel +Tested-by: Ido Schimmel +Signed-off-by: David S. Miller +Stable-dep-of: d5082d386eee ("ipv4: Fix route deletion when nexthop info is not specified") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..bc03b5b316a --- /dev/null +++ b/queue-5.15/kconfig.debug-provide-a-little-extra-frame_warn-leew.patch @@ -0,0 +1,56 @@ +From 2e8508f7cb3a9bf0ac3e1cc25aed0d5839a7485f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Acked-by: Arnd Bergmann +Cc: Alex Deucher +Cc: "Christian König" +Cc: Daniel Vetter +Cc: David Airlie +Cc: Harry Wentland +Cc: Leo Li +Cc: Maarten Lankhorst +Cc: Maxime Ripard +Cc: Nathan Chancellor +Cc: Nick Desaulniers +Cc: "Pan, Xinhui" +Cc: Rodrigo Siqueira +Cc: Thomas Zimmermann +Cc: Tom Rix +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..f2b43f6c405 --- /dev/null +++ b/queue-5.15/mm-__isolate_lru_page_prepare-in-isolate_migratepage.patch @@ -0,0 +1,318 @@ +From 48987d79e260a608212499e10de103a76b9324db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Mar 2022 14:45:41 -0700 +Subject: mm: __isolate_lru_page_prepare() in isolate_migratepages_block() + +From: Hugh Dickins + +[ 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 +Acked-by: David Rientjes +Reviewed-by: Alex Shi +Cc: Alexander Duyck +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Stable-dep-of: 829ae0f81ce0 ("mm: migrate: fix THP's mapcount on isolation") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..65eb17f68a2 --- /dev/null +++ b/queue-5.15/mm-migrate-fix-thp-s-mapcount-on-isolation.patch @@ -0,0 +1,89 @@ +From 488391d6b29def702747cde1fe6054588371cfc7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Nov 2022 17:55:23 +0800 +Subject: mm: migrate: fix THP's mapcount on isolation + +From: Gavin Shan + +[ 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 +Reported-by: Zhenyu Zhang +Tested-by: Zhenyu Zhang +Suggested-by: David Hildenbrand +Acked-by: David Hildenbrand +Cc: Alistair Popple +Cc: Hugh Dickins +Cc: Kirill A. Shutemov +Cc: Matthew Wilcox +Cc: William Kucharski +Cc: Zi Yan +Cc: [5.7+] +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..37ecb601b89 --- /dev/null +++ b/queue-5.15/nvme-fix-srcu-protection-of-nvme_ns_head-list.patch @@ -0,0 +1,104 @@ +From e92bc9e180b44f0d2bd81f67106d434e4f34a8cc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Nov 2022 16:27:56 -0700 +Subject: nvme: fix SRCU protection of nvme_ns_head list + +From: Caleb Sander + +[ 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 +Signed-off-by: Christoph Hellwig +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..df4d8120345 --- /dev/null +++ b/queue-5.15/parisc-increase-frame_warn-to-2048-bytes-on-parisc.patch @@ -0,0 +1,40 @@ +From 44296db495c41ac25d1ab0e88455f420c768b245 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Nov 2021 22:31:03 +0100 +Subject: parisc: Increase FRAME_WARN to 2048 bytes on parisc + +From: Helge Deller + +[ 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 +Signed-off-by: Helge Deller +Stable-dep-of: 152fe65f300e ("Kconfig.debug: provide a little extra FRAME_WARN leeway when KASAN is enabled") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..fdc6545e6bb --- /dev/null +++ b/queue-5.15/pinctrl-single-fix-potential-division-by-zero.patch @@ -0,0 +1,43 @@ +From cf70f3f8b44858d680ccb2f852f75d3dac8dadab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 15:30:34 +0300 +Subject: pinctrl: single: Fix potential division by zero + +From: Maxim Korotkov + +[ 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 +Reviewed-by: Tony Lindgren +Link: https://lore.kernel.org/r/20221117123034.27383-1-korotkov.maxim.s@gmail.com +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..2ba516a9a34 --- /dev/null +++ b/queue-5.15/riscv-fix-race-when-vmap-stack-overflow.patch @@ -0,0 +1,107 @@ +From 129f6b6589da3224c9052370bf89d08281c97728 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 30 Oct 2022 20:45:17 +0800 +Subject: riscv: fix race when vmap stack overflow + +From: Jisheng Zhang + +[ 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 +Suggested-by: Guo Ren +Reviewed-by: Guo Ren +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 +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..dc3e3690c3e --- /dev/null +++ b/queue-5.15/riscv-kexec-fixup-crash_smp_send_stop-without-multi-.patch @@ -0,0 +1,310 @@ +From 6ebd75a424f9beed695e0aae59ccfe91565c0953 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Oct 2022 10:16:03 -0400 +Subject: riscv: kexec: Fixup crash_smp_send_stop without multi cores + +From: Guo Ren + +[ 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 +Signed-off-by: Guo Ren +Signed-off-by: Guo Ren +Cc: Nick Kossifidis +Link: https://lore.kernel.org/r/20221020141603.2856206-3-guoren@kernel.org +Signed-off-by: Palmer Dabbelt +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + #include + #include + #include +@@ -22,11 +23,13 @@ + #include + #include + #include ++#include + + 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 index 00000000000..d79f18252ff --- /dev/null +++ b/queue-5.15/riscv-kexec-fixup-irq-controller-broken-in-kexec-cra.patch @@ -0,0 +1,93 @@ +From 3c624bc126a7ee77af1fd450bdd732f060dd32cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Oct 2022 10:16:02 -0400 +Subject: riscv: kexec: Fixup irq controller broken in kexec crash path + +From: Guo Ren + +[ 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 +Signed-off-by: Guo Ren +Reviewed-by: Xianting Tian +Cc: Nick Kossifidis +Cc: Palmer Dabbelt +Link: https://lore.kernel.org/r/20221020141603.2856206-2-guoren@kernel.org +Signed-off-by: Palmer Dabbelt +Signed-off-by: Sasha Levin +--- + 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 /* For unreachable() */ + #include /* For cpu_down() */ + #include ++#include ++#include + + /* + * 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 index 00000000000..6fe647b7b27 --- /dev/null +++ b/queue-5.15/riscv-sync-efi-page-table-s-kernel-mappings-before-s.patch @@ -0,0 +1,87 @@ +From 309a70fdc593c39652d53e29effdfc8de757dd9d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Nov 2022 14:33:03 +0100 +Subject: riscv: Sync efi page table's kernel mappings before switching + +From: Alexandre Ghiti + +[ 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 +Fixes: b91540d52a08 ("RISC-V: Add EFI runtime services") +Tested-by: Emil Renner Berthing +Reviewed-by: Atish Patra +Link: https://lore.kernel.org/r/20221121133303.1782246-1-alexghiti@rivosinc.com +Signed-off-by: Palmer Dabbelt +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + + #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 index 00000000000..7706aba1d23 --- /dev/null +++ b/queue-5.15/selftests-net-add-delete-nexthop-route-warning-test.patch @@ -0,0 +1,60 @@ +From 511036bf8e01983a3a86305d45eaadd36a599df9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 1 Apr 2022 10:33:43 +0300 +Subject: selftests: net: add delete nexthop route warning test + +From: Nikolay Aleksandrov + +[ 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 +Reviewed-by: David Ahern +Signed-off-by: David S. Miller +Stable-dep-of: d5082d386eee ("ipv4: Fix route deletion when nexthop info is not specified") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..b2e9e7d7ee9 --- /dev/null +++ b/queue-5.15/selftests-net-fix-nexthop-warning-cleanup-double-ip-.patch @@ -0,0 +1,41 @@ +From 005c1ec8ee95ecfbc9f192bfb25b92a4f23fb52f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 1 Apr 2022 18:54:27 +0300 +Subject: selftests: net: fix nexthop warning cleanup double ip typo + +From: Nikolay Aleksandrov + +[ 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 +Signed-off-by: David S. Miller +Stable-dep-of: d5082d386eee ("ipv4: Fix route deletion when nexthop info is not specified") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..0b430b5ba4a --- /dev/null +++ b/queue-5.15/serial-stm32-deassert-transmit-enable-on-rs485_confi.patch @@ -0,0 +1,172 @@ +From 19a4090f1b6ab594e732c6b8f91089128063a8a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Ilpo Järvinen +Signed-off-by: Lukas Wunner +Link: https://lore.kernel.org/r/6059eab35dba394468335ef640df8b0050fd9dbd.1662886616.git.lukas@wunner.de +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..bf7a7275705 --- /dev/null +++ b/queue-5.15/serial-stm32-factor-out-gpio-rts-toggling-into-separ.patch @@ -0,0 +1,122 @@ +From 8f1a30ca6d33b347dc53e44ab33ca88ce364b761 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 30 Apr 2022 18:28:44 +0200 +Subject: serial: stm32: Factor out GPIO RTS toggling into separate function + +From: Marek Vasut + +[ 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 +Cc: Alexandre Torgue +Cc: Erwan Le Ray +Cc: Greg Kroah-Hartman +Cc: Jean Philippe Romain +Cc: Valentin Caron +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 +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..04f4d711455 --- /dev/null +++ b/queue-5.15/serial-stm32-use-tc-interrupt-to-deassert-gpio-rts-i.patch @@ -0,0 +1,135 @@ +From ebe3c928daac036c01cefe5e671141ba2e19703a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: Alexandre Torgue +Cc: Erwan Le Ray +Cc: Greg Kroah-Hartman +Cc: Jean Philippe Romain +Cc: Valentin Caron +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 +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/series b/queue-5.15/series index 29a3d25ca67..ef975df9662 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -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