release 6.16.3 (preliminary)
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
From 1cb9f09cead0ba384729bfdc74d6fa21d586530c Mon Sep 17 00:00:00 2001
|
||||
From 2f7f5a0cd283219e09f8b05b7bfef26b518685ee Mon Sep 17 00:00:00 2001
|
||||
From: Christian Loehle <christian.loehle@arm.com>
|
||||
Date: Thu, 5 Sep 2024 10:26:39 +0100
|
||||
Subject: cpuidle: Prefer teo over menu governor
|
||||
|
@@ -1,29 +0,0 @@
|
||||
From b3dc27f64b5d62505ae9f03a6c342a43b0b7e0b2 Mon Sep 17 00:00:00 2001
|
||||
From: Jens Axboe <axboe@kernel.dk>
|
||||
Date: Tue, 27 May 2025 07:28:54 -0600
|
||||
Subject: Revert "Disable FOP_DONTCACHE for now due to bugs"
|
||||
|
||||
This reverts commit 478ad02d6844217cc7568619aeb0809d93ade43d.
|
||||
|
||||
Both the read and write side dirty && writeback races should be resolved
|
||||
now, revert the commit that disabled FOP_DONTCACHE for filesystems.
|
||||
|
||||
Link: https://lore.kernel.org/linux-fsdevel/20250525083209.GS2023217@ZenIV/
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
Link: https://lore.kernel.org/20250527133255.452431-4-axboe@kernel.dk
|
||||
Signed-off-by: Christian Brauner <brauner@kernel.org>
|
||||
---
|
||||
include/linux/fs.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/include/linux/fs.h
|
||||
+++ b/include/linux/fs.h
|
||||
@@ -2186,7 +2186,7 @@ struct file_operations {
|
||||
/* Supports asynchronous lock callbacks */
|
||||
#define FOP_ASYNC_LOCK ((__force fop_flags_t)(1 << 6))
|
||||
/* File system supports uncached read/write buffered IO */
|
||||
-#define FOP_DONTCACHE 0 /* ((__force fop_flags_t)(1 << 7)) */
|
||||
+#define FOP_DONTCACHE ((__force fop_flags_t)(1 << 7))
|
||||
|
||||
/* Wrap a directory iterator that needs exclusive inode access */
|
||||
int wrap_directory_iterator(struct file *, struct dir_context *,
|
@@ -1,36 +0,0 @@
|
||||
From 0b8d9b7ae677a03629218f69037be3f342c5ee81 Mon Sep 17 00:00:00 2001
|
||||
From: Jens Axboe <axboe@kernel.dk>
|
||||
Date: Tue, 27 May 2025 07:28:55 -0600
|
||||
Subject: mm/filemap: unify read/write dropbehind naming
|
||||
|
||||
The read side is filemap_end_dropbehind_read(), while the write side
|
||||
used folio_ as the prefix rather than filemap_. The read side makes more
|
||||
sense, unify the naming such that the write side follows that.
|
||||
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
Link: https://lore.kernel.org/20250527133255.452431-5-axboe@kernel.dk
|
||||
Signed-off-by: Christian Brauner <brauner@kernel.org>
|
||||
---
|
||||
mm/filemap.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/mm/filemap.c
|
||||
+++ b/mm/filemap.c
|
||||
@@ -1604,7 +1604,7 @@ static void filemap_end_dropbehind(struc
|
||||
* completes. Do that now. If we fail, it's likely because of a big folio -
|
||||
* just reset dropbehind for that case and latter completions should invalidate.
|
||||
*/
|
||||
-static void folio_end_dropbehind_write(struct folio *folio)
|
||||
+static void filemap_end_dropbehind_write(struct folio *folio)
|
||||
{
|
||||
/*
|
||||
* Hitting !in_task() should not happen off RWF_DONTCACHE writeback,
|
||||
@@ -1659,7 +1659,7 @@ void folio_end_writeback(struct folio *f
|
||||
acct_reclaim_writeback(folio);
|
||||
|
||||
if (folio_dropbehind)
|
||||
- folio_end_dropbehind_write(folio);
|
||||
+ filemap_end_dropbehind_write(folio);
|
||||
folio_put(folio);
|
||||
}
|
||||
EXPORT_SYMBOL(folio_end_writeback);
|
@@ -1,78 +0,0 @@
|
||||
From 2c1c3b3aafb153cbc3bd298db57cc7313d1601b1 Mon Sep 17 00:00:00 2001
|
||||
From: Jens Axboe <axboe@kernel.dk>
|
||||
Date: Tue, 27 May 2025 07:28:56 -0600
|
||||
Subject: mm/filemap: unify dropbehind flag testing and clearing
|
||||
|
||||
The read and write side does this a bit differently, unify it such that
|
||||
the _{read,write} helpers check the bit before locking, and the generic
|
||||
handler is in charge of clearing the bit and invalidating, once under
|
||||
the folio lock.
|
||||
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
Link: https://lore.kernel.org/20250527133255.452431-6-axboe@kernel.dk
|
||||
Signed-off-by: Christian Brauner <brauner@kernel.org>
|
||||
---
|
||||
mm/filemap.c | 21 +++++++++++----------
|
||||
1 file changed, 11 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/mm/filemap.c
|
||||
+++ b/mm/filemap.c
|
||||
@@ -1595,7 +1595,11 @@ static void filemap_end_dropbehind(struc
|
||||
|
||||
VM_BUG_ON_FOLIO(!folio_test_locked(folio), folio);
|
||||
|
||||
- if (mapping && !folio_test_writeback(folio) && !folio_test_dirty(folio))
|
||||
+ if (folio_test_writeback(folio) || folio_test_dirty(folio))
|
||||
+ return;
|
||||
+ if (!folio_test_clear_dropbehind(folio))
|
||||
+ return;
|
||||
+ if (mapping)
|
||||
folio_unmap_invalidate(mapping, folio, 0);
|
||||
}
|
||||
|
||||
@@ -1606,6 +1610,9 @@ static void filemap_end_dropbehind(struc
|
||||
*/
|
||||
static void filemap_end_dropbehind_write(struct folio *folio)
|
||||
{
|
||||
+ if (!folio_test_dropbehind(folio))
|
||||
+ return;
|
||||
+
|
||||
/*
|
||||
* Hitting !in_task() should not happen off RWF_DONTCACHE writeback,
|
||||
* but can happen if normal writeback just happens to find dirty folios
|
||||
@@ -1629,8 +1636,6 @@ static void filemap_end_dropbehind_write
|
||||
*/
|
||||
void folio_end_writeback(struct folio *folio)
|
||||
{
|
||||
- bool folio_dropbehind = false;
|
||||
-
|
||||
VM_BUG_ON_FOLIO(!folio_test_writeback(folio), folio);
|
||||
|
||||
/*
|
||||
@@ -1652,14 +1657,11 @@ void folio_end_writeback(struct folio *f
|
||||
* reused before the folio_wake_bit().
|
||||
*/
|
||||
folio_get(folio);
|
||||
- if (!folio_test_dirty(folio))
|
||||
- folio_dropbehind = folio_test_clear_dropbehind(folio);
|
||||
if (__folio_end_writeback(folio))
|
||||
folio_wake_bit(folio, PG_writeback);
|
||||
- acct_reclaim_writeback(folio);
|
||||
|
||||
- if (folio_dropbehind)
|
||||
- filemap_end_dropbehind_write(folio);
|
||||
+ filemap_end_dropbehind_write(folio);
|
||||
+ acct_reclaim_writeback(folio);
|
||||
folio_put(folio);
|
||||
}
|
||||
EXPORT_SYMBOL(folio_end_writeback);
|
||||
@@ -2651,8 +2653,7 @@ static void filemap_end_dropbehind_read(
|
||||
if (folio_test_writeback(folio) || folio_test_dirty(folio))
|
||||
return;
|
||||
if (folio_trylock(folio)) {
|
||||
- if (folio_test_clear_dropbehind(folio))
|
||||
- filemap_end_dropbehind(folio);
|
||||
+ filemap_end_dropbehind(folio);
|
||||
folio_unlock(folio);
|
||||
}
|
||||
}
|
@@ -1,98 +0,0 @@
|
||||
From 61d27e9dadb2eb2b7596a11a37402452d97625f7 Mon Sep 17 00:00:00 2001
|
||||
From: Shivank Garg <shivankg@amd.com>
|
||||
Date: Mon, 26 May 2025 18:28:18 +0000
|
||||
Subject: mm/khugepaged: fix race with folio split/free using temporary
|
||||
reference
|
||||
|
||||
hpage_collapse_scan_file() calls is_refcount_suitable(), which in turn
|
||||
calls folio_mapcount(). folio_mapcount() checks folio_test_large() before
|
||||
proceeding to folio_large_mapcount(), but there is a race window where the
|
||||
folio may get split/freed between these checks, triggering:
|
||||
|
||||
VM_WARN_ON_FOLIO(!folio_test_large(folio), folio)
|
||||
|
||||
Take a temporary reference to the folio in hpage_collapse_scan_file().
|
||||
This stabilizes the folio during refcount check and prevents incorrect
|
||||
large folio detection due to concurrent split/free. Use helper
|
||||
folio_expected_ref_count() + 1 to compare with folio_ref_count() instead
|
||||
of using is_refcount_suitable().
|
||||
|
||||
Link: https://lkml.kernel.org/r/20250526182818.37978-1-shivankg@amd.com
|
||||
Fixes: 05c5323b2a34 ("mm: track mapcount of large folios in single value")
|
||||
Signed-off-by: Shivank Garg <shivankg@amd.com>
|
||||
Reported-by: syzbot+2b99589e33edbe9475ca@syzkaller.appspotmail.com
|
||||
Closes: https://lore.kernel.org/all/6828470d.a70a0220.38f255.000c.GAE@google.com
|
||||
Suggested-by: David Hildenbrand <david@redhat.com>
|
||||
Acked-by: David Hildenbrand <david@redhat.com>
|
||||
Acked-by: Dev Jain <dev.jain@arm.com>
|
||||
Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
|
||||
Cc: Bharata B Rao <bharata@amd.com>
|
||||
Cc: Fengwei Yin <fengwei.yin@intel.com>
|
||||
Cc: Liam Howlett <liam.howlett@oracle.com>
|
||||
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
|
||||
Cc: Mariano Pache <npache@redhat.com>
|
||||
Cc: Ryan Roberts <ryan.roberts@arm.com>
|
||||
Cc: Zi Yan <ziy@nvidia.com>
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
---
|
||||
mm/khugepaged.c | 18 +++++++++++++++++-
|
||||
1 file changed, 17 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/mm/khugepaged.c
|
||||
+++ b/mm/khugepaged.c
|
||||
@@ -2295,6 +2295,17 @@ static int hpage_collapse_scan_file(stru
|
||||
continue;
|
||||
}
|
||||
|
||||
+ if (!folio_try_get(folio)) {
|
||||
+ xas_reset(&xas);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (unlikely(folio != xas_reload(&xas))) {
|
||||
+ folio_put(folio);
|
||||
+ xas_reset(&xas);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
if (folio_order(folio) == HPAGE_PMD_ORDER &&
|
||||
folio->index == start) {
|
||||
/* Maybe PMD-mapped */
|
||||
@@ -2305,23 +2316,27 @@ static int hpage_collapse_scan_file(stru
|
||||
* it's safe to skip LRU and refcount checks before
|
||||
* returning.
|
||||
*/
|
||||
+ folio_put(folio);
|
||||
break;
|
||||
}
|
||||
|
||||
node = folio_nid(folio);
|
||||
if (hpage_collapse_scan_abort(node, cc)) {
|
||||
result = SCAN_SCAN_ABORT;
|
||||
+ folio_put(folio);
|
||||
break;
|
||||
}
|
||||
cc->node_load[node]++;
|
||||
|
||||
if (!folio_test_lru(folio)) {
|
||||
result = SCAN_PAGE_LRU;
|
||||
+ folio_put(folio);
|
||||
break;
|
||||
}
|
||||
|
||||
- if (!is_refcount_suitable(folio)) {
|
||||
+ if (folio_expected_ref_count(folio) + 1 != folio_ref_count(folio)) {
|
||||
result = SCAN_PAGE_COUNT;
|
||||
+ folio_put(folio);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2333,6 +2348,7 @@ static int hpage_collapse_scan_file(stru
|
||||
*/
|
||||
|
||||
present += folio_nr_pages(folio);
|
||||
+ folio_put(folio);
|
||||
|
||||
if (need_resched()) {
|
||||
xas_pause(&xas);
|
@@ -1,198 +0,0 @@
|
||||
From 8135974e9e512fdf6d15f59947f95e44f2834c37 Mon Sep 17 00:00:00 2001
|
||||
From: Shivank Garg <shivankg@amd.com>
|
||||
Date: Wed, 30 Apr 2025 10:01:51 +0000
|
||||
Subject: mm: add folio_expected_ref_count() for reference count calculation
|
||||
|
||||
Patch series " JFS: Implement migrate_folio for jfs_metapage_aops" v5.
|
||||
|
||||
This patchset addresses a warning that occurs during memory compaction due
|
||||
to JFS's missing migrate_folio operation. The warning was introduced by
|
||||
commit 7ee3647243e5 ("migrate: Remove call to ->writepage") which added
|
||||
explicit warnings when filesystem don't implement migrate_folio.
|
||||
|
||||
The syzbot reported following [1]:
|
||||
jfs_metapage_aops does not implement migrate_folio
|
||||
WARNING: CPU: 1 PID: 5861 at mm/migrate.c:955 fallback_migrate_folio mm/migrate.c:953 [inline]
|
||||
WARNING: CPU: 1 PID: 5861 at mm/migrate.c:955 move_to_new_folio+0x70e/0x840 mm/migrate.c:1007
|
||||
Modules linked in:
|
||||
CPU: 1 UID: 0 PID: 5861 Comm: syz-executor280 Not tainted 6.15.0-rc1-next-20250411-syzkaller #0 PREEMPT(full)
|
||||
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 02/12/2025
|
||||
RIP: 0010:fallback_migrate_folio mm/migrate.c:953 [inline]
|
||||
RIP: 0010:move_to_new_folio+0x70e/0x840 mm/migrate.c:1007
|
||||
|
||||
To fix this issue, this series implement metapage_migrate_folio() for JFS
|
||||
which handles both single and multiple metapages per page configurations.
|
||||
|
||||
While most filesystems leverage existing migration implementations like
|
||||
filemap_migrate_folio(), buffer_migrate_folio_norefs() or
|
||||
buffer_migrate_folio() (which internally used folio_expected_refs()),
|
||||
JFS's metapage architecture requires special handling of its private data
|
||||
during migration. To support this, this series introduce the
|
||||
folio_expected_ref_count(), which calculates external references to a
|
||||
folio from page/swap cache, private data, and page table mappings.
|
||||
|
||||
This standardized implementation replaces the previous ad-hoc
|
||||
folio_expected_refs() function and enables JFS to accurately determine
|
||||
whether a folio has unexpected references before attempting migration.
|
||||
|
||||
|
||||
|
||||
|
||||
Implement folio_expected_ref_count() to calculate expected folio reference
|
||||
counts from:
|
||||
- Page/swap cache (1 per page)
|
||||
- Private data (1)
|
||||
- Page table mappings (1 per map)
|
||||
|
||||
While originally needed for page migration operations, this improved
|
||||
implementation standardizes reference counting by consolidating all
|
||||
refcount contributors into a single, reusable function that can benefit
|
||||
any subsystem needing to detect unexpected references to folios.
|
||||
|
||||
The folio_expected_ref_count() returns the sum of these external
|
||||
references without including any reference the caller itself might hold.
|
||||
Callers comparing against the actual folio_ref_count() must account for
|
||||
their own references separately.
|
||||
|
||||
Link: https://syzkaller.appspot.com/bug?extid=8bb6fd945af4e0ad9299 [1]
|
||||
Link: https://lkml.kernel.org/r/20250430100150.279751-1-shivankg@amd.com
|
||||
Link: https://lkml.kernel.org/r/20250430100150.279751-2-shivankg@amd.com
|
||||
Signed-off-by: David Hildenbrand <david@redhat.com>
|
||||
Signed-off-by: Shivank Garg <shivankg@amd.com>
|
||||
Suggested-by: Matthew Wilcox <willy@infradead.org>
|
||||
Co-developed-by: David Hildenbrand <david@redhat.com>
|
||||
Cc: Alistair Popple <apopple@nvidia.com>
|
||||
Cc: Dave Kleikamp <shaggy@kernel.org>
|
||||
Cc: Donet Tom <donettom@linux.ibm.com>
|
||||
Cc: Jane Chu <jane.chu@oracle.com>
|
||||
Cc: Kefeng Wang <wangkefeng.wang@huawei.com>
|
||||
Cc: Zi Yan <ziy@nvidia.com>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
---
|
||||
include/linux/mm.h | 55 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||
mm/migrate.c | 22 ++++---------------
|
||||
2 files changed, 59 insertions(+), 18 deletions(-)
|
||||
|
||||
--- a/include/linux/mm.h
|
||||
+++ b/include/linux/mm.h
|
||||
@@ -2337,6 +2337,61 @@ static inline bool folio_maybe_mapped_sh
|
||||
return folio_test_large_maybe_mapped_shared(folio);
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * folio_expected_ref_count - calculate the expected folio refcount
|
||||
+ * @folio: the folio
|
||||
+ *
|
||||
+ * Calculate the expected folio refcount, taking references from the pagecache,
|
||||
+ * swapcache, PG_private and page table mappings into account. Useful in
|
||||
+ * combination with folio_ref_count() to detect unexpected references (e.g.,
|
||||
+ * GUP or other temporary references).
|
||||
+ *
|
||||
+ * Does currently not consider references from the LRU cache. If the folio
|
||||
+ * was isolated from the LRU (which is the case during migration or split),
|
||||
+ * the LRU cache does not apply.
|
||||
+ *
|
||||
+ * Calling this function on an unmapped folio -- !folio_mapped() -- that is
|
||||
+ * locked will return a stable result.
|
||||
+ *
|
||||
+ * Calling this function on a mapped folio will not result in a stable result,
|
||||
+ * because nothing stops additional page table mappings from coming (e.g.,
|
||||
+ * fork()) or going (e.g., munmap()).
|
||||
+ *
|
||||
+ * Calling this function without the folio lock will also not result in a
|
||||
+ * stable result: for example, the folio might get dropped from the swapcache
|
||||
+ * concurrently.
|
||||
+ *
|
||||
+ * However, even when called without the folio lock or on a mapped folio,
|
||||
+ * this function can be used to detect unexpected references early (for example,
|
||||
+ * if it makes sense to even lock the folio and unmap it).
|
||||
+ *
|
||||
+ * The caller must add any reference (e.g., from folio_try_get()) it might be
|
||||
+ * holding itself to the result.
|
||||
+ *
|
||||
+ * Returns the expected folio refcount.
|
||||
+ */
|
||||
+static inline int folio_expected_ref_count(const struct folio *folio)
|
||||
+{
|
||||
+ const int order = folio_order(folio);
|
||||
+ int ref_count = 0;
|
||||
+
|
||||
+ if (WARN_ON_ONCE(folio_test_slab(folio)))
|
||||
+ return 0;
|
||||
+
|
||||
+ if (folio_test_anon(folio)) {
|
||||
+ /* One reference per page from the swapcache. */
|
||||
+ ref_count += folio_test_swapcache(folio) << order;
|
||||
+ } else if (!((unsigned long)folio->mapping & PAGE_MAPPING_FLAGS)) {
|
||||
+ /* One reference per page from the pagecache. */
|
||||
+ ref_count += !!folio->mapping << order;
|
||||
+ /* One reference from PG_private. */
|
||||
+ ref_count += folio_test_private(folio);
|
||||
+ }
|
||||
+
|
||||
+ /* One reference per page table mapping. */
|
||||
+ return ref_count + folio_mapcount(folio);
|
||||
+}
|
||||
+
|
||||
#ifndef HAVE_ARCH_MAKE_FOLIO_ACCESSIBLE
|
||||
static inline int arch_make_folio_accessible(struct folio *folio)
|
||||
{
|
||||
--- a/mm/migrate.c
|
||||
+++ b/mm/migrate.c
|
||||
@@ -445,20 +445,6 @@ unlock:
|
||||
}
|
||||
#endif
|
||||
|
||||
-static int folio_expected_refs(struct address_space *mapping,
|
||||
- struct folio *folio)
|
||||
-{
|
||||
- int refs = 1;
|
||||
- if (!mapping)
|
||||
- return refs;
|
||||
-
|
||||
- refs += folio_nr_pages(folio);
|
||||
- if (folio_test_private(folio))
|
||||
- refs++;
|
||||
-
|
||||
- return refs;
|
||||
-}
|
||||
-
|
||||
/*
|
||||
* Replace the folio in the mapping.
|
||||
*
|
||||
@@ -601,7 +587,7 @@ static int __folio_migrate_mapping(struc
|
||||
int folio_migrate_mapping(struct address_space *mapping,
|
||||
struct folio *newfolio, struct folio *folio, int extra_count)
|
||||
{
|
||||
- int expected_count = folio_expected_refs(mapping, folio) + extra_count;
|
||||
+ int expected_count = folio_expected_ref_count(folio) + extra_count + 1;
|
||||
|
||||
if (folio_ref_count(folio) != expected_count)
|
||||
return -EAGAIN;
|
||||
@@ -618,7 +604,7 @@ int migrate_huge_page_move_mapping(struc
|
||||
struct folio *dst, struct folio *src)
|
||||
{
|
||||
XA_STATE(xas, &mapping->i_pages, folio_index(src));
|
||||
- int rc, expected_count = folio_expected_refs(mapping, src);
|
||||
+ int rc, expected_count = folio_expected_ref_count(src) + 1;
|
||||
|
||||
if (folio_ref_count(src) != expected_count)
|
||||
return -EAGAIN;
|
||||
@@ -749,7 +735,7 @@ static int __migrate_folio(struct addres
|
||||
struct folio *src, void *src_private,
|
||||
enum migrate_mode mode)
|
||||
{
|
||||
- int rc, expected_count = folio_expected_refs(mapping, src);
|
||||
+ int rc, expected_count = folio_expected_ref_count(src) + 1;
|
||||
|
||||
/* Check whether src does not have extra refs before we do more work */
|
||||
if (folio_ref_count(src) != expected_count)
|
||||
@@ -837,7 +823,7 @@ static int __buffer_migrate_folio(struct
|
||||
return migrate_folio(mapping, dst, src, mode);
|
||||
|
||||
/* Check whether page does not have extra refs before we do more work */
|
||||
- expected_count = folio_expected_refs(mapping, src);
|
||||
+ expected_count = folio_expected_ref_count(src) + 1;
|
||||
if (folio_ref_count(src) != expected_count)
|
||||
return -EAGAIN;
|
||||
|
@@ -1,40 +0,0 @@
|
||||
From 3d1a493525955678c231ab7ccf0950c0ba2b9f45 Mon Sep 17 00:00:00 2001
|
||||
From: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
|
||||
Date: Fri, 13 Jun 2025 11:42:46 +0530
|
||||
Subject: drm/i915/snps_hdmi_pll: Fix 64-bit divisor truncation by using
|
||||
div64_u64
|
||||
|
||||
DIV_ROUND_CLOSEST_ULL uses do_div(), which expects a 32-bit divisor.
|
||||
When passing a 64-bit constant like CURVE2_MULTIPLIER, the value is
|
||||
silently truncated to u32, potentially leading to incorrect results
|
||||
on large divisors.
|
||||
|
||||
Replace DIV_ROUND_CLOSEST_ULL with div64_u64(), which correctly
|
||||
handles full 64-bit division. Since the result is clamped between
|
||||
1 and 127, rounding is unnecessary and truncating division
|
||||
is sufficient.
|
||||
|
||||
Fixes: 5947642004bf ("drm/i915/display: Add support for SNPS PHY HDMI PLL algorithm for DG2")
|
||||
Cc: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
|
||||
Cc: Suraj Kandpal <suraj.kandpal@intel.com>
|
||||
Cc: Jani Nikula <jani.nikula@intel.com>
|
||||
Cc: <stable@vger.kernel.org> # v6.15+
|
||||
Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
|
||||
Cherry-picked-for: https://gitlab.archlinux.org/archlinux/packaging/packages/linux/-/issues/145
|
||||
---
|
||||
drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c
|
||||
@@ -103,8 +103,8 @@ static void get_ana_cp_int_prop(u64 vco_
|
||||
DIV_ROUND_DOWN_ULL(curve_1_interpolated, CURVE0_MULTIPLIER)));
|
||||
|
||||
ana_cp_int_temp =
|
||||
- DIV64_U64_ROUND_CLOSEST(DIV_ROUND_DOWN_ULL(adjusted_vco_clk1, curve_2_scaled1),
|
||||
- CURVE2_MULTIPLIER);
|
||||
+ div64_u64(DIV_ROUND_DOWN_ULL(adjusted_vco_clk1, curve_2_scaled1),
|
||||
+ CURVE2_MULTIPLIER);
|
||||
|
||||
*ana_cp_int = max(1, min(ana_cp_int_temp, 127));
|
||||
|
@@ -1,86 +0,0 @@
|
||||
From 336152e6ec30b13f5617ee9b702beb5bc310c6a7 Mon Sep 17 00:00:00 2001
|
||||
From: "Vishal Moola (Oracle)" <vishal.moola@gmail.com>
|
||||
Date: Mon, 31 Mar 2025 19:10:25 -0700
|
||||
Subject: mm/compaction: use folio in hugetlb pathway
|
||||
|
||||
Use a folio in the hugetlb pathway during the compaction migrate-able
|
||||
pageblock scan.
|
||||
|
||||
This removes a call to compound_head().
|
||||
|
||||
Link: https://lkml.kernel.org/r/20250401021025.637333-2-vishal.moola@gmail.com
|
||||
Signed-off-by: Vishal Moola (Oracle) <vishal.moola@gmail.com>
|
||||
Acked-by: Oscar Salvador <osalvador@suse.de>
|
||||
Reviewed-by: Zi Yan <ziy@nvidia.com>
|
||||
Cc: Muchun Song <muchun.song@linux.dev>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
---
|
||||
include/linux/hugetlb.h | 4 ++--
|
||||
mm/compaction.c | 8 ++++----
|
||||
mm/hugetlb.c | 3 +--
|
||||
3 files changed, 7 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/include/linux/hugetlb.h
|
||||
+++ b/include/linux/hugetlb.h
|
||||
@@ -703,7 +703,7 @@ struct huge_bootmem_page {
|
||||
|
||||
bool hugetlb_bootmem_page_zones_valid(int nid, struct huge_bootmem_page *m);
|
||||
|
||||
-int isolate_or_dissolve_huge_page(struct page *page, struct list_head *list);
|
||||
+int isolate_or_dissolve_huge_folio(struct folio *folio, struct list_head *list);
|
||||
int replace_free_hugepage_folios(unsigned long start_pfn, unsigned long end_pfn);
|
||||
void wait_for_freed_hugetlb_folios(void);
|
||||
struct folio *alloc_hugetlb_folio(struct vm_area_struct *vma,
|
||||
@@ -1091,7 +1091,7 @@ static inline struct folio *filemap_lock
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-static inline int isolate_or_dissolve_huge_page(struct page *page,
|
||||
+static inline int isolate_or_dissolve_huge_folio(struct folio *folio,
|
||||
struct list_head *list)
|
||||
{
|
||||
return -ENOMEM;
|
||||
--- a/mm/compaction.c
|
||||
+++ b/mm/compaction.c
|
||||
@@ -1001,10 +1001,11 @@ isolate_migratepages_block(struct compac
|
||||
locked = NULL;
|
||||
}
|
||||
|
||||
- ret = isolate_or_dissolve_huge_page(page, &cc->migratepages);
|
||||
+ folio = page_folio(page);
|
||||
+ ret = isolate_or_dissolve_huge_folio(folio, &cc->migratepages);
|
||||
|
||||
/*
|
||||
- * Fail isolation in case isolate_or_dissolve_huge_page()
|
||||
+ * Fail isolation in case isolate_or_dissolve_huge_folio()
|
||||
* reports an error. In case of -ENOMEM, abort right away.
|
||||
*/
|
||||
if (ret < 0) {
|
||||
@@ -1016,12 +1017,11 @@ isolate_migratepages_block(struct compac
|
||||
goto isolate_fail;
|
||||
}
|
||||
|
||||
- if (PageHuge(page)) {
|
||||
+ if (folio_test_hugetlb(folio)) {
|
||||
/*
|
||||
* Hugepage was successfully isolated and placed
|
||||
* on the cc->migratepages list.
|
||||
*/
|
||||
- folio = page_folio(page);
|
||||
low_pfn += folio_nr_pages(folio) - 1;
|
||||
goto isolate_success_no_list;
|
||||
}
|
||||
--- a/mm/hugetlb.c
|
||||
+++ b/mm/hugetlb.c
|
||||
@@ -2896,10 +2896,9 @@ free_new:
|
||||
return ret;
|
||||
}
|
||||
|
||||
-int isolate_or_dissolve_huge_page(struct page *page, struct list_head *list)
|
||||
+int isolate_or_dissolve_huge_folio(struct folio *folio, struct list_head *list)
|
||||
{
|
||||
struct hstate *h;
|
||||
- struct folio *folio = page_folio(page);
|
||||
int ret = -EBUSY;
|
||||
|
||||
/*
|
@@ -1,154 +0,0 @@
|
||||
From 2e50b415d59dda319bb3208c5ed5234a23f307e9 Mon Sep 17 00:00:00 2001
|
||||
From: Ge Yang <yangge1116@126.com>
|
||||
Date: Tue, 27 May 2025 11:36:50 +0800
|
||||
Subject: mm/hugetlb: remove unnecessary holding of hugetlb_lock
|
||||
|
||||
In isolate_or_dissolve_huge_folio(), after acquiring the hugetlb_lock, it
|
||||
is only for the purpose of obtaining the correct hstate, which is then
|
||||
passed to alloc_and_dissolve_hugetlb_folio().
|
||||
|
||||
alloc_and_dissolve_hugetlb_folio() itself also acquires the hugetlb_lock.
|
||||
We can have alloc_and_dissolve_hugetlb_folio() obtain the hstate by
|
||||
itself, so that isolate_or_dissolve_huge_folio() no longer needs to
|
||||
acquire the hugetlb_lock. In addition, we keep the folio_test_hugetlb()
|
||||
check within isolate_or_dissolve_huge_folio(). By doing so, we can avoid
|
||||
disrupting the normal path by vainly holding the hugetlb_lock.
|
||||
|
||||
replace_free_hugepage_folios() has the same issue, and we should address
|
||||
it as well.
|
||||
|
||||
Addresses a possible performance problem which was added by the hotfix
|
||||
113ed54ad276 ("mm/hugetlb: fix kernel NULL pointer dereference when
|
||||
replacing free hugetlb folios").
|
||||
|
||||
Link: https://lkml.kernel.org/r/1748317010-16272-1-git-send-email-yangge1116@126.com
|
||||
Fixes: 113ed54ad276 ("mm/hugetlb: fix kernel NULL pointer dereference when replacing free hugetlb folios")
|
||||
Signed-off-by: Ge Yang <yangge1116@126.com>
|
||||
Suggested-by: Oscar Salvador <osalvador@suse.de>
|
||||
Reviewed-by: Muchun Song <muchun.song@linux.dev>
|
||||
Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
|
||||
Cc: Barry Song <21cnbao@gmail.com>
|
||||
Cc: David Hildenbrand <david@redhat.com>
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
---
|
||||
mm/hugetlb.c | 54 +++++++++++++++++-----------------------------------
|
||||
1 file changed, 17 insertions(+), 37 deletions(-)
|
||||
|
||||
--- a/mm/hugetlb.c
|
||||
+++ b/mm/hugetlb.c
|
||||
@@ -2811,20 +2811,24 @@ void restore_reserve_on_error(struct hst
|
||||
/*
|
||||
* alloc_and_dissolve_hugetlb_folio - Allocate a new folio and dissolve
|
||||
* the old one
|
||||
- * @h: struct hstate old page belongs to
|
||||
* @old_folio: Old folio to dissolve
|
||||
* @list: List to isolate the page in case we need to
|
||||
* Returns 0 on success, otherwise negated error.
|
||||
*/
|
||||
-static int alloc_and_dissolve_hugetlb_folio(struct hstate *h,
|
||||
- struct folio *old_folio, struct list_head *list)
|
||||
+static int alloc_and_dissolve_hugetlb_folio(struct folio *old_folio,
|
||||
+ struct list_head *list)
|
||||
{
|
||||
- gfp_t gfp_mask = htlb_alloc_mask(h) | __GFP_THISNODE;
|
||||
+ gfp_t gfp_mask;
|
||||
+ struct hstate *h;
|
||||
int nid = folio_nid(old_folio);
|
||||
struct folio *new_folio = NULL;
|
||||
int ret = 0;
|
||||
|
||||
retry:
|
||||
+ /*
|
||||
+ * The old_folio might have been dissolved from under our feet, so make sure
|
||||
+ * to carefully check the state under the lock.
|
||||
+ */
|
||||
spin_lock_irq(&hugetlb_lock);
|
||||
if (!folio_test_hugetlb(old_folio)) {
|
||||
/*
|
||||
@@ -2853,8 +2857,10 @@ retry:
|
||||
cond_resched();
|
||||
goto retry;
|
||||
} else {
|
||||
+ h = folio_hstate(old_folio);
|
||||
if (!new_folio) {
|
||||
spin_unlock_irq(&hugetlb_lock);
|
||||
+ gfp_mask = htlb_alloc_mask(h) | __GFP_THISNODE;
|
||||
new_folio = alloc_buddy_hugetlb_folio(h, gfp_mask, nid,
|
||||
NULL, NULL);
|
||||
if (!new_folio)
|
||||
@@ -2898,35 +2904,24 @@ free_new:
|
||||
|
||||
int isolate_or_dissolve_huge_folio(struct folio *folio, struct list_head *list)
|
||||
{
|
||||
- struct hstate *h;
|
||||
int ret = -EBUSY;
|
||||
|
||||
- /*
|
||||
- * The page might have been dissolved from under our feet, so make sure
|
||||
- * to carefully check the state under the lock.
|
||||
- * Return success when racing as if we dissolved the page ourselves.
|
||||
- */
|
||||
- spin_lock_irq(&hugetlb_lock);
|
||||
- if (folio_test_hugetlb(folio)) {
|
||||
- h = folio_hstate(folio);
|
||||
- } else {
|
||||
- spin_unlock_irq(&hugetlb_lock);
|
||||
+ /* Not to disrupt normal path by vainly holding hugetlb_lock */
|
||||
+ if (!folio_test_hugetlb(folio))
|
||||
return 0;
|
||||
- }
|
||||
- spin_unlock_irq(&hugetlb_lock);
|
||||
|
||||
/*
|
||||
* Fence off gigantic pages as there is a cyclic dependency between
|
||||
* alloc_contig_range and them. Return -ENOMEM as this has the effect
|
||||
* of bailing out right away without further retrying.
|
||||
*/
|
||||
- if (hstate_is_gigantic(h))
|
||||
+ if (folio_order(folio) > MAX_PAGE_ORDER)
|
||||
return -ENOMEM;
|
||||
|
||||
if (folio_ref_count(folio) && folio_isolate_hugetlb(folio, list))
|
||||
ret = 0;
|
||||
else if (!folio_ref_count(folio))
|
||||
- ret = alloc_and_dissolve_hugetlb_folio(h, folio, list);
|
||||
+ ret = alloc_and_dissolve_hugetlb_folio(folio, list);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -2940,7 +2935,6 @@ int isolate_or_dissolve_huge_folio(struc
|
||||
*/
|
||||
int replace_free_hugepage_folios(unsigned long start_pfn, unsigned long end_pfn)
|
||||
{
|
||||
- struct hstate *h;
|
||||
struct folio *folio;
|
||||
int ret = 0;
|
||||
|
||||
@@ -2949,23 +2943,9 @@ int replace_free_hugepage_folios(unsigne
|
||||
while (start_pfn < end_pfn) {
|
||||
folio = pfn_folio(start_pfn);
|
||||
|
||||
- /*
|
||||
- * The folio might have been dissolved from under our feet, so make sure
|
||||
- * to carefully check the state under the lock.
|
||||
- */
|
||||
- spin_lock_irq(&hugetlb_lock);
|
||||
- if (folio_test_hugetlb(folio)) {
|
||||
- h = folio_hstate(folio);
|
||||
- } else {
|
||||
- spin_unlock_irq(&hugetlb_lock);
|
||||
- start_pfn++;
|
||||
- continue;
|
||||
- }
|
||||
- spin_unlock_irq(&hugetlb_lock);
|
||||
-
|
||||
- if (!folio_ref_count(folio)) {
|
||||
- ret = alloc_and_dissolve_hugetlb_folio(h, folio,
|
||||
- &isolate_list);
|
||||
+ /* Not to disrupt normal path by vainly holding hugetlb_lock */
|
||||
+ if (folio_test_hugetlb(folio) && !folio_ref_count(folio)) {
|
||||
+ ret = alloc_and_dissolve_hugetlb_folio(folio, &isolate_list);
|
||||
if (ret)
|
||||
break;
|
||||
|
@@ -1,136 +0,0 @@
|
||||
From b885aa903c313644f7ba8d46d4c09ead1b52f1f1 Mon Sep 17 00:00:00 2001
|
||||
From: David Howells <dhowells@redhat.com>
|
||||
Date: Tue, 1 Jul 2025 17:38:38 +0100
|
||||
Subject: netfs: Provide helpers to perform NETFS_RREQ_IN_PROGRESS flag
|
||||
wangling
|
||||
|
||||
Provide helpers to clear and test the NETFS_RREQ_IN_PROGRESS and to insert
|
||||
the appropriate barrierage.
|
||||
|
||||
Signed-off-by: David Howells <dhowells@redhat.com>
|
||||
Link: https://lore.kernel.org/20250701163852.2171681-4-dhowells@redhat.com
|
||||
Tested-by: Steve French <sfrench@samba.org>
|
||||
Reviewed-by: Paulo Alcantara <pc@manguebit.org>
|
||||
cc: netfs@lists.linux.dev
|
||||
cc: linux-fsdevel@vger.kernel.org
|
||||
Signed-off-by: Christian Brauner <brauner@kernel.org>
|
||||
---
|
||||
fs/netfs/internal.h | 18 ++++++++++++++++++
|
||||
fs/netfs/misc.c | 10 +++++-----
|
||||
fs/netfs/read_collect.c | 4 ++--
|
||||
fs/netfs/write_collect.c | 4 ++--
|
||||
4 files changed, 27 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/fs/netfs/internal.h
|
||||
+++ b/fs/netfs/internal.h
|
||||
@@ -275,6 +275,24 @@ static inline void netfs_wake_rreq_flag(
|
||||
}
|
||||
|
||||
/*
|
||||
+ * Test the NETFS_RREQ_IN_PROGRESS flag, inserting an appropriate barrier.
|
||||
+ */
|
||||
+static inline bool netfs_check_rreq_in_progress(const struct netfs_io_request *rreq)
|
||||
+{
|
||||
+ /* Order read of flags before read of anything else, such as error. */
|
||||
+ return test_bit_acquire(NETFS_RREQ_IN_PROGRESS, &rreq->flags);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Test the NETFS_SREQ_IN_PROGRESS flag, inserting an appropriate barrier.
|
||||
+ */
|
||||
+static inline bool netfs_check_subreq_in_progress(const struct netfs_io_subrequest *subreq)
|
||||
+{
|
||||
+ /* Order read of flags before read of anything else, such as error. */
|
||||
+ return test_bit_acquire(NETFS_SREQ_IN_PROGRESS, &subreq->flags);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
* fscache-cache.c
|
||||
*/
|
||||
#ifdef CONFIG_PROC_FS
|
||||
--- a/fs/netfs/misc.c
|
||||
+++ b/fs/netfs/misc.c
|
||||
@@ -356,14 +356,14 @@ void netfs_wait_for_in_progress_stream(s
|
||||
DEFINE_WAIT(myself);
|
||||
|
||||
list_for_each_entry(subreq, &stream->subrequests, rreq_link) {
|
||||
- if (!test_bit(NETFS_SREQ_IN_PROGRESS, &subreq->flags))
|
||||
+ if (!netfs_check_subreq_in_progress(subreq))
|
||||
continue;
|
||||
|
||||
trace_netfs_rreq(rreq, netfs_rreq_trace_wait_queue);
|
||||
for (;;) {
|
||||
prepare_to_wait(&rreq->waitq, &myself, TASK_UNINTERRUPTIBLE);
|
||||
|
||||
- if (!test_bit(NETFS_SREQ_IN_PROGRESS, &subreq->flags))
|
||||
+ if (!netfs_check_subreq_in_progress(subreq))
|
||||
break;
|
||||
|
||||
trace_netfs_sreq(subreq, netfs_sreq_trace_wait_for);
|
||||
@@ -400,7 +400,7 @@ static int netfs_collect_in_app(struct n
|
||||
struct netfs_io_subrequest,
|
||||
rreq_link);
|
||||
if (subreq &&
|
||||
- (!test_bit(NETFS_SREQ_IN_PROGRESS, &subreq->flags) ||
|
||||
+ (!netfs_check_subreq_in_progress(subreq) ||
|
||||
test_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags))) {
|
||||
need_collect = true;
|
||||
break;
|
||||
@@ -454,7 +454,7 @@ static ssize_t netfs_wait_for_in_progres
|
||||
}
|
||||
}
|
||||
|
||||
- if (!test_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags))
|
||||
+ if (!netfs_check_rreq_in_progress(rreq))
|
||||
break;
|
||||
|
||||
schedule();
|
||||
@@ -525,7 +525,7 @@ static void netfs_wait_for_pause(struct
|
||||
}
|
||||
}
|
||||
|
||||
- if (!test_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags) ||
|
||||
+ if (!netfs_check_rreq_in_progress(rreq) ||
|
||||
!test_bit(NETFS_RREQ_PAUSE, &rreq->flags))
|
||||
break;
|
||||
|
||||
--- a/fs/netfs/read_collect.c
|
||||
+++ b/fs/netfs/read_collect.c
|
||||
@@ -220,7 +220,7 @@ reassess:
|
||||
stream->collected_to = front->start;
|
||||
}
|
||||
|
||||
- if (test_bit(NETFS_SREQ_IN_PROGRESS, &front->flags))
|
||||
+ if (netfs_check_subreq_in_progress(front))
|
||||
notes |= HIT_PENDING;
|
||||
smp_rmb(); /* Read counters after IN_PROGRESS flag. */
|
||||
transferred = READ_ONCE(front->transferred);
|
||||
@@ -447,7 +447,7 @@ void netfs_read_collection_worker(struct
|
||||
struct netfs_io_request *rreq = container_of(work, struct netfs_io_request, work);
|
||||
|
||||
netfs_see_request(rreq, netfs_rreq_trace_see_work);
|
||||
- if (test_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags)) {
|
||||
+ if (netfs_check_rreq_in_progress(rreq)) {
|
||||
if (netfs_read_collection(rreq))
|
||||
/* Drop the ref from the IN_PROGRESS flag. */
|
||||
netfs_put_request(rreq, netfs_rreq_trace_put_work_ip);
|
||||
--- a/fs/netfs/write_collect.c
|
||||
+++ b/fs/netfs/write_collect.c
|
||||
@@ -240,7 +240,7 @@ reassess_streams:
|
||||
}
|
||||
|
||||
/* Stall if the front is still undergoing I/O. */
|
||||
- if (test_bit(NETFS_SREQ_IN_PROGRESS, &front->flags)) {
|
||||
+ if (netfs_check_subreq_in_progress(front)) {
|
||||
notes |= HIT_PENDING;
|
||||
break;
|
||||
}
|
||||
@@ -434,7 +434,7 @@ void netfs_write_collection_worker(struc
|
||||
struct netfs_io_request *rreq = container_of(work, struct netfs_io_request, work);
|
||||
|
||||
netfs_see_request(rreq, netfs_rreq_trace_see_work);
|
||||
- if (test_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags)) {
|
||||
+ if (netfs_check_rreq_in_progress(rreq)) {
|
||||
if (netfs_write_collection(rreq))
|
||||
/* Drop the ref from the IN_PROGRESS flag. */
|
||||
netfs_put_request(rreq, netfs_rreq_trace_put_work_ip);
|
@@ -1,4 +1,4 @@
|
||||
From 3400d11fad849dae6015e448c83d6e90f8a6ef35 Mon Sep 17 00:00:00 2001
|
||||
From cb67be41cf8b19fed3b1cc08a42417aa1c7550e0 Mon Sep 17 00:00:00 2001
|
||||
From: Oleksandr Natalenko <oleksandr@natalenko.name>
|
||||
Date: Tue, 8 Apr 2025 12:02:36 +0200
|
||||
Subject: ice: mark ice_write_prof_mask_reg() as noinline
|
||||
|
@@ -1,4 +1,4 @@
|
||||
From 1615cc0c7d979a1c211f349c8c28ee8afb9ad57d Mon Sep 17 00:00:00 2001
|
||||
From a3c672256ccc59b07f007b569e1e7507b0a82dce Mon Sep 17 00:00:00 2001
|
||||
From: Oleksandr Natalenko <oleksandr@natalenko.name>
|
||||
Date: Thu, 1 May 2025 20:22:53 +0200
|
||||
Subject: wifi: mac80211: mark copy_mesh_setup() as noinline
|
||||
@@ -24,7 +24,7 @@ Signed-off-by: Oleksandr Natalenko <oleksandr@natalenko.name>
|
||||
|
||||
--- a/net/mac80211/cfg.c
|
||||
+++ b/net/mac80211/cfg.c
|
||||
@@ -2515,7 +2515,7 @@ static inline bool _chg_mesh_attr(enum n
|
||||
@@ -2539,7 +2539,7 @@ static inline bool _chg_mesh_attr(enum n
|
||||
return (mask >> (parm-1)) & 0x1;
|
||||
}
|
||||
|
||||
|
91
debian/patches/patchset-pf/steady/0001-PCI-Fix-link-speed-calculation-on-retrain-failure.patch
vendored
Normal file
91
debian/patches/patchset-pf/steady/0001-PCI-Fix-link-speed-calculation-on-retrain-failure.patch
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
From e9efb8c2e0d662c1d28a95732f0a085e81c365ab Mon Sep 17 00:00:00 2001
|
||||
From: Jiwei Sun <sunjw10@lenovo.com>
|
||||
Date: Thu, 23 Jan 2025 13:51:54 +0800
|
||||
Subject: PCI: Fix link speed calculation on retrain failure
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
When pcie_failed_link_retrain() fails to retrain, it tries to revert to the
|
||||
previous link speed. However it calculates that speed from the Link
|
||||
Control 2 register without masking out non-speed bits first.
|
||||
|
||||
PCIE_LNKCTL2_TLS2SPEED() converts such incorrect values to
|
||||
PCI_SPEED_UNKNOWN (0xff), which in turn causes a WARN splat in
|
||||
pcie_set_target_speed():
|
||||
|
||||
pci 0000:00:01.1: [1022:14ed] type 01 class 0x060400 PCIe Root Port
|
||||
pci 0000:00:01.1: broken device, retraining non-functional downstream link at 2.5GT/s
|
||||
pci 0000:00:01.1: retraining failed
|
||||
WARNING: CPU: 1 PID: 1 at drivers/pci/pcie/bwctrl.c:168 pcie_set_target_speed
|
||||
RDX: 0000000000000001 RSI: 00000000000000ff RDI: ffff9acd82efa000
|
||||
pcie_failed_link_retrain
|
||||
pci_device_add
|
||||
pci_scan_single_device
|
||||
|
||||
Mask out the non-speed bits in PCIE_LNKCTL2_TLS2SPEED() and
|
||||
PCIE_LNKCAP_SLS2SPEED() so they don't incorrectly return PCI_SPEED_UNKNOWN.
|
||||
|
||||
Fixes: de9a6c8d5dbf ("PCI/bwctrl: Add pcie_set_target_speed() to set PCIe Link Speed")
|
||||
Reported-by: Andrew <andreasx0@protonmail.com>
|
||||
Closes: https://lore.kernel.org/r/7iNzXbCGpf8yUMJZBQjLdbjPcXrEJqBxy5-bHfppz0ek-h4_-G93b1KUrm106r2VNF2FV_sSq0nENv4RsRIUGnlYZMlQr2ZD2NyB5sdj5aU=@protonmail.com/
|
||||
Suggested-by: Maciej W. Rozycki <macro@orcam.me.uk>
|
||||
Suggested-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
|
||||
Signed-off-by: Jiwei Sun <sunjw10@lenovo.com>
|
||||
[bhelgaas: commit log, add details from https://lore.kernel.org/r/1c92ef6bcb314ee6977839b46b393282e4f52e74.1750684771.git.lukas@wunner.de]
|
||||
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
|
||||
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
|
||||
Cc: stable@vger.kernel.org # v6.13+
|
||||
Link: https://patch.msgid.link/20250123055155.22648-2-sjiwei@163.com
|
||||
---
|
||||
drivers/pci/pci.h | 32 +++++++++++++++++++-------------
|
||||
1 file changed, 19 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/pci/pci.h
|
||||
+++ b/drivers/pci/pci.h
|
||||
@@ -391,12 +391,14 @@ void pci_bus_put(struct pci_bus *bus);
|
||||
|
||||
#define PCIE_LNKCAP_SLS2SPEED(lnkcap) \
|
||||
({ \
|
||||
- ((lnkcap) == PCI_EXP_LNKCAP_SLS_64_0GB ? PCIE_SPEED_64_0GT : \
|
||||
- (lnkcap) == PCI_EXP_LNKCAP_SLS_32_0GB ? PCIE_SPEED_32_0GT : \
|
||||
- (lnkcap) == PCI_EXP_LNKCAP_SLS_16_0GB ? PCIE_SPEED_16_0GT : \
|
||||
- (lnkcap) == PCI_EXP_LNKCAP_SLS_8_0GB ? PCIE_SPEED_8_0GT : \
|
||||
- (lnkcap) == PCI_EXP_LNKCAP_SLS_5_0GB ? PCIE_SPEED_5_0GT : \
|
||||
- (lnkcap) == PCI_EXP_LNKCAP_SLS_2_5GB ? PCIE_SPEED_2_5GT : \
|
||||
+ u32 lnkcap_sls = (lnkcap) & PCI_EXP_LNKCAP_SLS; \
|
||||
+ \
|
||||
+ (lnkcap_sls == PCI_EXP_LNKCAP_SLS_64_0GB ? PCIE_SPEED_64_0GT : \
|
||||
+ lnkcap_sls == PCI_EXP_LNKCAP_SLS_32_0GB ? PCIE_SPEED_32_0GT : \
|
||||
+ lnkcap_sls == PCI_EXP_LNKCAP_SLS_16_0GB ? PCIE_SPEED_16_0GT : \
|
||||
+ lnkcap_sls == PCI_EXP_LNKCAP_SLS_8_0GB ? PCIE_SPEED_8_0GT : \
|
||||
+ lnkcap_sls == PCI_EXP_LNKCAP_SLS_5_0GB ? PCIE_SPEED_5_0GT : \
|
||||
+ lnkcap_sls == PCI_EXP_LNKCAP_SLS_2_5GB ? PCIE_SPEED_2_5GT : \
|
||||
PCI_SPEED_UNKNOWN); \
|
||||
})
|
||||
|
||||
@@ -411,13 +413,17 @@ void pci_bus_put(struct pci_bus *bus);
|
||||
PCI_SPEED_UNKNOWN)
|
||||
|
||||
#define PCIE_LNKCTL2_TLS2SPEED(lnkctl2) \
|
||||
- ((lnkctl2) == PCI_EXP_LNKCTL2_TLS_64_0GT ? PCIE_SPEED_64_0GT : \
|
||||
- (lnkctl2) == PCI_EXP_LNKCTL2_TLS_32_0GT ? PCIE_SPEED_32_0GT : \
|
||||
- (lnkctl2) == PCI_EXP_LNKCTL2_TLS_16_0GT ? PCIE_SPEED_16_0GT : \
|
||||
- (lnkctl2) == PCI_EXP_LNKCTL2_TLS_8_0GT ? PCIE_SPEED_8_0GT : \
|
||||
- (lnkctl2) == PCI_EXP_LNKCTL2_TLS_5_0GT ? PCIE_SPEED_5_0GT : \
|
||||
- (lnkctl2) == PCI_EXP_LNKCTL2_TLS_2_5GT ? PCIE_SPEED_2_5GT : \
|
||||
- PCI_SPEED_UNKNOWN)
|
||||
+({ \
|
||||
+ u16 lnkctl2_tls = (lnkctl2) & PCI_EXP_LNKCTL2_TLS; \
|
||||
+ \
|
||||
+ (lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_64_0GT ? PCIE_SPEED_64_0GT : \
|
||||
+ lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_32_0GT ? PCIE_SPEED_32_0GT : \
|
||||
+ lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_16_0GT ? PCIE_SPEED_16_0GT : \
|
||||
+ lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_8_0GT ? PCIE_SPEED_8_0GT : \
|
||||
+ lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_5_0GT ? PCIE_SPEED_5_0GT : \
|
||||
+ lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_2_5GT ? PCIE_SPEED_2_5GT : \
|
||||
+ PCI_SPEED_UNKNOWN); \
|
||||
+})
|
||||
|
||||
/* PCIe speed to Mb/s reduced by encoding overhead */
|
||||
#define PCIE_SPEED2MBS_ENC(speed) \
|
57
debian/patches/patchset-pf/steady/0002-PCI-endpoint-Fix-configfs-group-list-head-handling.patch
vendored
Normal file
57
debian/patches/patchset-pf/steady/0002-PCI-endpoint-Fix-configfs-group-list-head-handling.patch
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
From ab8a3c32946686d57d720dc4a1b23635fb4a39bd Mon Sep 17 00:00:00 2001
|
||||
From: Damien Le Moal <dlemoal@kernel.org>
|
||||
Date: Tue, 24 Jun 2025 20:45:43 +0900
|
||||
Subject: PCI: endpoint: Fix configfs group list head handling
|
||||
|
||||
Doing a list_del() on the epf_group field of struct pci_epf_driver in
|
||||
pci_epf_remove_cfs() is not correct as this field is a list head, not
|
||||
a list entry. This list_del() call triggers a KASAN warning when an
|
||||
endpoint function driver which has a configfs attribute group is torn
|
||||
down:
|
||||
|
||||
==================================================================
|
||||
BUG: KASAN: slab-use-after-free in pci_epf_remove_cfs+0x17c/0x198
|
||||
Write of size 8 at addr ffff00010f4a0d80 by task rmmod/319
|
||||
|
||||
CPU: 3 UID: 0 PID: 319 Comm: rmmod Not tainted 6.16.0-rc2 #1 NONE
|
||||
Hardware name: Radxa ROCK 5B (DT)
|
||||
Call trace:
|
||||
show_stack+0x2c/0x84 (C)
|
||||
dump_stack_lvl+0x70/0x98
|
||||
print_report+0x17c/0x538
|
||||
kasan_report+0xb8/0x190
|
||||
__asan_report_store8_noabort+0x20/0x2c
|
||||
pci_epf_remove_cfs+0x17c/0x198
|
||||
pci_epf_unregister_driver+0x18/0x30
|
||||
nvmet_pci_epf_cleanup_module+0x24/0x30 [nvmet_pci_epf]
|
||||
__arm64_sys_delete_module+0x264/0x424
|
||||
invoke_syscall+0x70/0x260
|
||||
el0_svc_common.constprop.0+0xac/0x230
|
||||
do_el0_svc+0x40/0x58
|
||||
el0_svc+0x48/0xdc
|
||||
el0t_64_sync_handler+0x10c/0x138
|
||||
el0t_64_sync+0x198/0x19c
|
||||
...
|
||||
|
||||
Remove this incorrect list_del() call from pci_epf_remove_cfs().
|
||||
|
||||
Fixes: ef1433f717a2 ("PCI: endpoint: Create configfs entry for each pci_epf_device_id table entry")
|
||||
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
|
||||
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
|
||||
Reviewed-by: Niklas Cassel <cassel@kernel.org>
|
||||
Cc: stable@vger.kernel.org
|
||||
Link: https://patch.msgid.link/20250624114544.342159-2-dlemoal@kernel.org
|
||||
---
|
||||
drivers/pci/endpoint/pci-epf-core.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
--- a/drivers/pci/endpoint/pci-epf-core.c
|
||||
+++ b/drivers/pci/endpoint/pci-epf-core.c
|
||||
@@ -338,7 +338,6 @@ static void pci_epf_remove_cfs(struct pc
|
||||
mutex_lock(&pci_epf_mutex);
|
||||
list_for_each_entry_safe(group, tmp, &driver->epf_group, group_entry)
|
||||
pci_ep_cfs_remove_epf_group(group);
|
||||
- list_del(&driver->epf_group);
|
||||
mutex_unlock(&pci_epf_mutex);
|
||||
}
|
||||
|
@@ -0,0 +1,48 @@
|
||||
From ac49c252132396b1910ea5aad0541f550c55679c Mon Sep 17 00:00:00 2001
|
||||
From: Damien Le Moal <dlemoal@kernel.org>
|
||||
Date: Tue, 24 Jun 2025 20:45:44 +0900
|
||||
Subject: PCI: endpoint: Fix configfs group removal on driver teardown
|
||||
|
||||
An endpoint driver configfs attributes group is added to the
|
||||
epf_group list of struct pci_epf_driver by pci_epf_add_cfs() but an
|
||||
added group is not removed from this list when the attribute group is
|
||||
unregistered with pci_ep_cfs_remove_epf_group().
|
||||
|
||||
Add the missing list_del() call in pci_ep_cfs_remove_epf_group()
|
||||
to correctly remove the attribute group from the driver list.
|
||||
|
||||
With this change, once the loop over all attribute groups in
|
||||
pci_epf_remove_cfs() completes, the driver epf_group list should be
|
||||
empty. Add a WARN_ON() to make sure of that.
|
||||
|
||||
Fixes: ef1433f717a2 ("PCI: endpoint: Create configfs entry for each pci_epf_device_id table entry")
|
||||
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
|
||||
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
|
||||
Reviewed-by: Niklas Cassel <cassel@kernel.org>
|
||||
Cc: stable@vger.kernel.org
|
||||
Link: https://patch.msgid.link/20250624114544.342159-3-dlemoal@kernel.org
|
||||
---
|
||||
drivers/pci/endpoint/pci-ep-cfs.c | 1 +
|
||||
drivers/pci/endpoint/pci-epf-core.c | 1 +
|
||||
2 files changed, 2 insertions(+)
|
||||
|
||||
--- a/drivers/pci/endpoint/pci-ep-cfs.c
|
||||
+++ b/drivers/pci/endpoint/pci-ep-cfs.c
|
||||
@@ -691,6 +691,7 @@ void pci_ep_cfs_remove_epf_group(struct
|
||||
if (IS_ERR_OR_NULL(group))
|
||||
return;
|
||||
|
||||
+ list_del(&group->group_entry);
|
||||
configfs_unregister_default_group(group);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_ep_cfs_remove_epf_group);
|
||||
--- a/drivers/pci/endpoint/pci-epf-core.c
|
||||
+++ b/drivers/pci/endpoint/pci-epf-core.c
|
||||
@@ -338,6 +338,7 @@ static void pci_epf_remove_cfs(struct pc
|
||||
mutex_lock(&pci_epf_mutex);
|
||||
list_for_each_entry_safe(group, tmp, &driver->epf_group, group_entry)
|
||||
pci_ep_cfs_remove_epf_group(group);
|
||||
+ WARN_ON(!list_empty(&driver->epf_group));
|
||||
mutex_unlock(&pci_epf_mutex);
|
||||
}
|
||||
|
@@ -0,0 +1,40 @@
|
||||
From bb8fada608c868a04288371c76dd387bb9ce5101 Mon Sep 17 00:00:00 2001
|
||||
From: Sakari Ailus <sakari.ailus@linux.intel.com>
|
||||
Date: Thu, 8 May 2025 18:55:38 +0300
|
||||
Subject: media: v4l2-ctrls: Don't reset handler's error in
|
||||
v4l2_ctrl_handler_free()
|
||||
|
||||
It's a common pattern in drivers to free the control handler's resources
|
||||
and then return the handler's error code on drivers' error handling paths.
|
||||
Alas, the v4l2_ctrl_handler_free() function also zeroes the error field,
|
||||
effectively indicating successful return to the caller.
|
||||
|
||||
There's no apparent need to touch the error field while releasing the
|
||||
control handler's resources and cleaning up stale pointers. Not touching
|
||||
the handler's error field is a more certain way to address this problem
|
||||
than changing all the users, in which case the pattern would be likely to
|
||||
re-emerge in new drivers.
|
||||
|
||||
Do just that, don't touch the control handler's error field in
|
||||
v4l2_ctrl_handler_free().
|
||||
|
||||
Fixes: 0996517cf8ea ("V4L/DVB: v4l2: Add new control handling framework")
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
|
||||
Reviewed-by: Hans Verkuil <hverkuil@xs4all.nl>
|
||||
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
|
||||
---
|
||||
drivers/media/v4l2-core/v4l2-ctrls-core.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
--- a/drivers/media/v4l2-core/v4l2-ctrls-core.c
|
||||
+++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c
|
||||
@@ -1661,7 +1661,6 @@ void v4l2_ctrl_handler_free(struct v4l2_
|
||||
kvfree(hdl->buckets);
|
||||
hdl->buckets = NULL;
|
||||
hdl->cached = NULL;
|
||||
- hdl->error = 0;
|
||||
mutex_unlock(hdl->lock);
|
||||
mutex_destroy(&hdl->_lock);
|
||||
}
|
145
debian/patches/patchset-pf/steady/0005-dm-dm-crypt-Do-not-partially-accept-write-BIOs-with-.patch
vendored
Normal file
145
debian/patches/patchset-pf/steady/0005-dm-dm-crypt-Do-not-partially-accept-write-BIOs-with-.patch
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
From e90295abea9dd31f84e7784e19e988be0dfcfb83 Mon Sep 17 00:00:00 2001
|
||||
From: Damien Le Moal <dlemoal@kernel.org>
|
||||
Date: Wed, 25 Jun 2025 18:33:26 +0900
|
||||
Subject: dm: dm-crypt: Do not partially accept write BIOs with zoned targets
|
||||
|
||||
Read and write operations issued to a dm-crypt target may be split
|
||||
according to the dm-crypt internal limits defined by the max_read_size
|
||||
and max_write_size module parameters (default is 128 KB). The intent is
|
||||
to improve processing time of large BIOs by splitting them into smaller
|
||||
operations that can be parallelized on different CPUs.
|
||||
|
||||
For zoned dm-crypt targets, this BIO splitting is still done but without
|
||||
the parallel execution to ensure that the issuing order of write
|
||||
operations to the underlying devices remains sequential. However, the
|
||||
splitting itself causes other problems:
|
||||
|
||||
1) Since dm-crypt relies on the block layer zone write plugging to
|
||||
handle zone append emulation using regular write operations, the
|
||||
reminder of a split write BIO will always be plugged into the target
|
||||
zone write plugged. Once the on-going write BIO finishes, this
|
||||
reminder BIO is unplugged and issued from the zone write plug work.
|
||||
If this reminder BIO itself needs to be split, the reminder will be
|
||||
re-issued and plugged again, but that causes a call to a
|
||||
blk_queue_enter(), which may block if a queue freeze operation was
|
||||
initiated. This results in a deadlock as DM submission still holds
|
||||
BIOs that the queue freeze side is waiting for.
|
||||
|
||||
2) dm-crypt relies on the emulation done by the block layer using
|
||||
regular write operations for processing zone append operations. This
|
||||
still requires to properly return the written sector as the BIO
|
||||
sector of the original BIO. However, this can be done correctly only
|
||||
and only if there is a single clone BIO used for processing the
|
||||
original zone append operation issued by the user. If the size of a
|
||||
zone append operation is larger than dm-crypt max_write_size, then
|
||||
the orginal BIO will be split and processed as a chain of regular
|
||||
write operations. Such chaining result in an incorrect written sector
|
||||
being returned to the zone append issuer using the original BIO
|
||||
sector. This in turn results in file system data corruptions using
|
||||
xfs or btrfs.
|
||||
|
||||
Fix this by modifying get_max_request_size() to always return the size
|
||||
of the BIO to avoid it being split with dm_accpet_partial_bio() in
|
||||
crypt_map(). get_max_request_size() is renamed to
|
||||
get_max_request_sectors() to clarify the unit of the value returned
|
||||
and its interface is changed to take a struct dm_target pointer and a
|
||||
pointer to the struct bio being processed. In addition to this change,
|
||||
to ensure that crypt_alloc_buffer() works correctly, set the dm-crypt
|
||||
device max_hw_sectors limit to be at most
|
||||
BIO_MAX_VECS << PAGE_SECTORS_SHIFT (1 MB with a 4KB page architecture).
|
||||
This forces DM core to split write BIOs before passing them to
|
||||
crypt_map(), and thus guaranteeing that dm-crypt can always accept an
|
||||
entire write BIO without needing to split it.
|
||||
|
||||
This change does not have any effect on the read path of dm-crypt. Read
|
||||
operations can still be split and the BIO fragments processed in
|
||||
parallel. There is also no impact on the performance of the write path
|
||||
given that all zone write BIOs were already processed inline instead of
|
||||
in parallel.
|
||||
|
||||
This change also does not affect in any way regular dm-crypt block
|
||||
devices.
|
||||
|
||||
Fixes: f211268ed1f9 ("dm: Use the block layer zone append emulation")
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
|
||||
Reviewed-by: Mikulas Patocka <mpatocka@redhat.com>
|
||||
Link: https://lore.kernel.org/r/20250625093327.548866-5-dlemoal@kernel.org
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
drivers/md/dm-crypt.c | 49 ++++++++++++++++++++++++++++++++++---------
|
||||
1 file changed, 39 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/drivers/md/dm-crypt.c
|
||||
+++ b/drivers/md/dm-crypt.c
|
||||
@@ -253,17 +253,35 @@ MODULE_PARM_DESC(max_read_size, "Maximum
|
||||
static unsigned int max_write_size = 0;
|
||||
module_param(max_write_size, uint, 0644);
|
||||
MODULE_PARM_DESC(max_write_size, "Maximum size of a write request");
|
||||
-static unsigned get_max_request_size(struct crypt_config *cc, bool wrt)
|
||||
+
|
||||
+static unsigned get_max_request_sectors(struct dm_target *ti, struct bio *bio)
|
||||
{
|
||||
+ struct crypt_config *cc = ti->private;
|
||||
unsigned val, sector_align;
|
||||
- val = !wrt ? READ_ONCE(max_read_size) : READ_ONCE(max_write_size);
|
||||
- if (likely(!val))
|
||||
- val = !wrt ? DM_CRYPT_DEFAULT_MAX_READ_SIZE : DM_CRYPT_DEFAULT_MAX_WRITE_SIZE;
|
||||
- if (wrt || cc->used_tag_size) {
|
||||
- if (unlikely(val > BIO_MAX_VECS << PAGE_SHIFT))
|
||||
- val = BIO_MAX_VECS << PAGE_SHIFT;
|
||||
+ bool wrt = op_is_write(bio_op(bio));
|
||||
+
|
||||
+ if (wrt) {
|
||||
+ /*
|
||||
+ * For zoned devices, splitting write operations creates the
|
||||
+ * risk of deadlocking queue freeze operations with zone write
|
||||
+ * plugging BIO work when the reminder of a split BIO is
|
||||
+ * issued. So always allow the entire BIO to proceed.
|
||||
+ */
|
||||
+ if (ti->emulate_zone_append)
|
||||
+ return bio_sectors(bio);
|
||||
+
|
||||
+ val = min_not_zero(READ_ONCE(max_write_size),
|
||||
+ DM_CRYPT_DEFAULT_MAX_WRITE_SIZE);
|
||||
+ } else {
|
||||
+ val = min_not_zero(READ_ONCE(max_read_size),
|
||||
+ DM_CRYPT_DEFAULT_MAX_READ_SIZE);
|
||||
}
|
||||
- sector_align = max(bdev_logical_block_size(cc->dev->bdev), (unsigned)cc->sector_size);
|
||||
+
|
||||
+ if (wrt || cc->used_tag_size)
|
||||
+ val = min(val, BIO_MAX_VECS << PAGE_SHIFT);
|
||||
+
|
||||
+ sector_align = max(bdev_logical_block_size(cc->dev->bdev),
|
||||
+ (unsigned)cc->sector_size);
|
||||
val = round_down(val, sector_align);
|
||||
if (unlikely(!val))
|
||||
val = sector_align;
|
||||
@@ -3496,7 +3514,7 @@ static int crypt_map(struct dm_target *t
|
||||
/*
|
||||
* Check if bio is too large, split as needed.
|
||||
*/
|
||||
- max_sectors = get_max_request_size(cc, bio_data_dir(bio) == WRITE);
|
||||
+ max_sectors = get_max_request_sectors(ti, bio);
|
||||
if (unlikely(bio_sectors(bio) > max_sectors))
|
||||
dm_accept_partial_bio(bio, max_sectors);
|
||||
|
||||
@@ -3733,6 +3751,17 @@ static void crypt_io_hints(struct dm_tar
|
||||
max_t(unsigned int, limits->physical_block_size, cc->sector_size);
|
||||
limits->io_min = max_t(unsigned int, limits->io_min, cc->sector_size);
|
||||
limits->dma_alignment = limits->logical_block_size - 1;
|
||||
+
|
||||
+ /*
|
||||
+ * For zoned dm-crypt targets, there will be no internal splitting of
|
||||
+ * write BIOs to avoid exceeding BIO_MAX_VECS vectors per BIO. But
|
||||
+ * without respecting this limit, crypt_alloc_buffer() will trigger a
|
||||
+ * BUG(). Avoid this by forcing DM core to split write BIOs to this
|
||||
+ * limit.
|
||||
+ */
|
||||
+ if (ti->emulate_zone_append)
|
||||
+ limits->max_hw_sectors = min(limits->max_hw_sectors,
|
||||
+ BIO_MAX_VECS << PAGE_SECTORS_SHIFT);
|
||||
}
|
||||
|
||||
static struct target_type crypt_target = {
|
@@ -0,0 +1,62 @@
|
||||
From 32eefb128e8ca539632595379da05e5662b72161 Mon Sep 17 00:00:00 2001
|
||||
From: Damien Le Moal <dlemoal@kernel.org>
|
||||
Date: Wed, 25 Jun 2025 18:33:27 +0900
|
||||
Subject: dm: Check for forbidden splitting of zone write operations
|
||||
|
||||
DM targets must not split zone append and write operations using
|
||||
dm_accept_partial_bio() as doing so is forbidden for zone append BIOs,
|
||||
breaks zone append emulation using regular write BIOs and potentially
|
||||
creates deadlock situations with queue freeze operations.
|
||||
|
||||
Modify dm_accept_partial_bio() to add missing BUG_ON() checks for all
|
||||
these cases, that is, check that the BIO is a write or write zeroes
|
||||
operation. This change packs all the zone related checks together under
|
||||
a static_branch_unlikely(&zoned_enabled) and done only if the target is
|
||||
a zoned device.
|
||||
|
||||
Fixes: f211268ed1f9 ("dm: Use the block layer zone append emulation")
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
|
||||
Reviewed-by: Mikulas Patocka <mpatocka@redhat.com>
|
||||
Link: https://lore.kernel.org/r/20250625093327.548866-6-dlemoal@kernel.org
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
drivers/md/dm.c | 17 +++++++++++++----
|
||||
1 file changed, 13 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/md/dm.c
|
||||
+++ b/drivers/md/dm.c
|
||||
@@ -1293,8 +1293,9 @@ out:
|
||||
/*
|
||||
* A target may call dm_accept_partial_bio only from the map routine. It is
|
||||
* allowed for all bio types except REQ_PREFLUSH, REQ_OP_ZONE_* zone management
|
||||
- * operations, REQ_OP_ZONE_APPEND (zone append writes) and any bio serviced by
|
||||
- * __send_duplicate_bios().
|
||||
+ * operations, zone append writes (native with REQ_OP_ZONE_APPEND or emulated
|
||||
+ * with write BIOs flagged with BIO_EMULATES_ZONE_APPEND) and any bio serviced
|
||||
+ * by __send_duplicate_bios().
|
||||
*
|
||||
* dm_accept_partial_bio informs the dm that the target only wants to process
|
||||
* additional n_sectors sectors of the bio and the rest of the data should be
|
||||
@@ -1327,11 +1328,19 @@ void dm_accept_partial_bio(struct bio *b
|
||||
unsigned int bio_sectors = bio_sectors(bio);
|
||||
|
||||
BUG_ON(dm_tio_flagged(tio, DM_TIO_IS_DUPLICATE_BIO));
|
||||
- BUG_ON(op_is_zone_mgmt(bio_op(bio)));
|
||||
- BUG_ON(bio_op(bio) == REQ_OP_ZONE_APPEND);
|
||||
BUG_ON(bio_sectors > *tio->len_ptr);
|
||||
BUG_ON(n_sectors > bio_sectors);
|
||||
|
||||
+ if (static_branch_unlikely(&zoned_enabled) &&
|
||||
+ unlikely(bdev_is_zoned(bio->bi_bdev))) {
|
||||
+ enum req_op op = bio_op(bio);
|
||||
+
|
||||
+ BUG_ON(op_is_zone_mgmt(op));
|
||||
+ BUG_ON(op == REQ_OP_WRITE);
|
||||
+ BUG_ON(op == REQ_OP_WRITE_ZEROES);
|
||||
+ BUG_ON(op == REQ_OP_ZONE_APPEND);
|
||||
+ }
|
||||
+
|
||||
*tio->len_ptr -= bio_sectors - n_sectors;
|
||||
bio->bi_iter.bi_size = n_sectors << SECTOR_SHIFT;
|
||||
|
110
debian/patches/patchset-pf/steady/0007-mtd-spi-nor-Fix-spi_nor_try_unlock_all.patch
vendored
Normal file
110
debian/patches/patchset-pf/steady/0007-mtd-spi-nor-Fix-spi_nor_try_unlock_all.patch
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
From 457eadbe8b4399d1c64d99536f5a2029f5e793d6 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Walle <mwalle@kernel.org>
|
||||
Date: Tue, 1 Jul 2025 16:04:26 +0200
|
||||
Subject: mtd: spi-nor: Fix spi_nor_try_unlock_all()
|
||||
|
||||
Commit ff67592cbdfc ("mtd: spi-nor: Introduce spi_nor_set_mtd_info()")
|
||||
moved all initialization of the mtd fields at the end of spi_nor_scan().
|
||||
Normally, the mtd info is only needed for the mtd ops on the device,
|
||||
with one exception: spi_nor_try_unlock_all(), which will also make use
|
||||
of the mtd->size parameter. With that commit, the size will always be
|
||||
zero because it is not initialized. Fix that by not using the size of
|
||||
the mtd_info struct, but use the size from struct spi_nor_flash_parameter.
|
||||
|
||||
Fixes: ff67592cbdfc ("mtd: spi-nor: Introduce spi_nor_set_mtd_info()")
|
||||
Cc: stable@vger.kernel.org
|
||||
Reported-by: Jean-Marc Ranger <jmranger@hotmail.com>
|
||||
Closes: https://lore.kernel.org/all/DM6PR06MB561177323DC5207E34AF2A06C547A@DM6PR06MB5611.namprd06.prod.outlook.com/
|
||||
Tested-by: Jean-Marc Ranger <jmranger@hotmail.com>
|
||||
Signed-off-by: Michael Walle <mwalle@kernel.org>
|
||||
Reviewed-by: Pratyush Yadav <pratyush@kernel.org>
|
||||
Signed-off-by: Pratyush Yadav <pratyush@kernel.org>
|
||||
Link: https://lore.kernel.org/r/20250701140426.2355182-1-mwalle@kernel.org
|
||||
---
|
||||
drivers/mtd/spi-nor/swp.c | 19 ++++++++-----------
|
||||
1 file changed, 8 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/spi-nor/swp.c
|
||||
+++ b/drivers/mtd/spi-nor/swp.c
|
||||
@@ -56,7 +56,6 @@ static u64 spi_nor_get_min_prot_length_s
|
||||
static void spi_nor_get_locked_range_sr(struct spi_nor *nor, u8 sr, loff_t *ofs,
|
||||
u64 *len)
|
||||
{
|
||||
- struct mtd_info *mtd = &nor->mtd;
|
||||
u64 min_prot_len;
|
||||
u8 mask = spi_nor_get_sr_bp_mask(nor);
|
||||
u8 tb_mask = spi_nor_get_sr_tb_mask(nor);
|
||||
@@ -77,13 +76,13 @@ static void spi_nor_get_locked_range_sr(
|
||||
min_prot_len = spi_nor_get_min_prot_length_sr(nor);
|
||||
*len = min_prot_len << (bp - 1);
|
||||
|
||||
- if (*len > mtd->size)
|
||||
- *len = mtd->size;
|
||||
+ if (*len > nor->params->size)
|
||||
+ *len = nor->params->size;
|
||||
|
||||
if (nor->flags & SNOR_F_HAS_SR_TB && sr & tb_mask)
|
||||
*ofs = 0;
|
||||
else
|
||||
- *ofs = mtd->size - *len;
|
||||
+ *ofs = nor->params->size - *len;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -158,7 +157,6 @@ static bool spi_nor_is_unlocked_sr(struc
|
||||
*/
|
||||
static int spi_nor_sr_lock(struct spi_nor *nor, loff_t ofs, u64 len)
|
||||
{
|
||||
- struct mtd_info *mtd = &nor->mtd;
|
||||
u64 min_prot_len;
|
||||
int ret, status_old, status_new;
|
||||
u8 mask = spi_nor_get_sr_bp_mask(nor);
|
||||
@@ -183,7 +181,7 @@ static int spi_nor_sr_lock(struct spi_no
|
||||
can_be_bottom = false;
|
||||
|
||||
/* If anything above us is unlocked, we can't use 'top' protection */
|
||||
- if (!spi_nor_is_locked_sr(nor, ofs + len, mtd->size - (ofs + len),
|
||||
+ if (!spi_nor_is_locked_sr(nor, ofs + len, nor->params->size - (ofs + len),
|
||||
status_old))
|
||||
can_be_top = false;
|
||||
|
||||
@@ -195,11 +193,11 @@ static int spi_nor_sr_lock(struct spi_no
|
||||
|
||||
/* lock_len: length of region that should end up locked */
|
||||
if (use_top)
|
||||
- lock_len = mtd->size - ofs;
|
||||
+ lock_len = nor->params->size - ofs;
|
||||
else
|
||||
lock_len = ofs + len;
|
||||
|
||||
- if (lock_len == mtd->size) {
|
||||
+ if (lock_len == nor->params->size) {
|
||||
val = mask;
|
||||
} else {
|
||||
min_prot_len = spi_nor_get_min_prot_length_sr(nor);
|
||||
@@ -248,7 +246,6 @@ static int spi_nor_sr_lock(struct spi_no
|
||||
*/
|
||||
static int spi_nor_sr_unlock(struct spi_nor *nor, loff_t ofs, u64 len)
|
||||
{
|
||||
- struct mtd_info *mtd = &nor->mtd;
|
||||
u64 min_prot_len;
|
||||
int ret, status_old, status_new;
|
||||
u8 mask = spi_nor_get_sr_bp_mask(nor);
|
||||
@@ -273,7 +270,7 @@ static int spi_nor_sr_unlock(struct spi_
|
||||
can_be_top = false;
|
||||
|
||||
/* If anything above us is locked, we can't use 'bottom' protection */
|
||||
- if (!spi_nor_is_unlocked_sr(nor, ofs + len, mtd->size - (ofs + len),
|
||||
+ if (!spi_nor_is_unlocked_sr(nor, ofs + len, nor->params->size - (ofs + len),
|
||||
status_old))
|
||||
can_be_bottom = false;
|
||||
|
||||
@@ -285,7 +282,7 @@ static int spi_nor_sr_unlock(struct spi_
|
||||
|
||||
/* lock_len: length of region that should remain locked */
|
||||
if (use_top)
|
||||
- lock_len = mtd->size - (ofs + len);
|
||||
+ lock_len = nor->params->size - (ofs + len);
|
||||
else
|
||||
lock_len = ofs;
|
||||
|
@@ -0,0 +1,40 @@
|
||||
From dd30d1837412d22457fc47562da3e4ae9c7d70ae Mon Sep 17 00:00:00 2001
|
||||
From: Chi Zhiling <chizhiling@kylinos.cn>
|
||||
Date: Thu, 5 Jun 2025 13:49:35 +0800
|
||||
Subject: readahead: fix return value of page_cache_next_miss() when no hole is
|
||||
found
|
||||
|
||||
max_scan in page_cache_next_miss always decreases to zero when no hole is
|
||||
found, causing the return value to be index + 0.
|
||||
|
||||
Fix this by preserving the max_scan value throughout the loop.
|
||||
|
||||
Jan said "From what I know and have seen in the past, wrong responses
|
||||
from page_cache_next_miss() can lead to readahead window reduction and
|
||||
thus reduced read speeds."
|
||||
|
||||
Link: https://lkml.kernel.org/r/20250605054935.2323451-1-chizhiling@163.com
|
||||
Fixes: 901a269ff3d5 ("filemap: fix page_cache_next_miss() when no hole found")
|
||||
Signed-off-by: Chi Zhiling <chizhiling@kylinos.cn>
|
||||
Reviewed-by: Jan Kara <jack@suse.cz>
|
||||
Cc: Josef Bacik <josef@toxicpanda.com>
|
||||
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
---
|
||||
mm/filemap.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/mm/filemap.c
|
||||
+++ b/mm/filemap.c
|
||||
@@ -1778,8 +1778,9 @@ pgoff_t page_cache_next_miss(struct addr
|
||||
pgoff_t index, unsigned long max_scan)
|
||||
{
|
||||
XA_STATE(xas, &mapping->i_pages, index);
|
||||
+ unsigned long nr = max_scan;
|
||||
|
||||
- while (max_scan--) {
|
||||
+ while (nr--) {
|
||||
void *entry = xas_next(&xas);
|
||||
if (!entry || xa_is_value(entry))
|
||||
return xas.xa_index;
|
@@ -0,0 +1,77 @@
|
||||
From 143c76ac94eddb9c2cb5ff4f57d78f60e22d9e20 Mon Sep 17 00:00:00 2001
|
||||
From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
|
||||
Date: Wed, 9 Jul 2025 12:41:45 +0200
|
||||
Subject: PM: runtime: Take active children into account in
|
||||
pm_runtime_get_if_in_use()
|
||||
|
||||
For all practical purposes, there is no difference between the situation
|
||||
in which a given device is not ignoring children and its active child
|
||||
count is nonzero and the situation in which its runtime PM usage counter
|
||||
is nonzero. However, pm_runtime_get_if_in_use() will only increment the
|
||||
device's usage counter and return 1 in the latter case.
|
||||
|
||||
For consistency, make it do so in the former case either by adjusting
|
||||
pm_runtime_get_conditional() and update the related kerneldoc comments
|
||||
accordingly.
|
||||
|
||||
Fixes: c111566bea7c ("PM: runtime: Add pm_runtime_get_if_active()")
|
||||
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
||||
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
|
||||
Reviewed-by: Sakari Ailus <sakari.ailus@linux.intel.com>
|
||||
Cc: 5.10+ <stable@vger.kernel.org> # 5.10+: c0ef3df8dbae: PM: runtime: Simplify pm_runtime_get_if_active() usage
|
||||
Cc: 5.10+ <stable@vger.kernel.org> # 5.10+
|
||||
Link: https://patch.msgid.link/12700973.O9o76ZdvQC@rjwysocki.net
|
||||
---
|
||||
drivers/base/power/runtime.c | 27 ++++++++++++++++++---------
|
||||
1 file changed, 18 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/drivers/base/power/runtime.c
|
||||
+++ b/drivers/base/power/runtime.c
|
||||
@@ -1191,10 +1191,12 @@ EXPORT_SYMBOL_GPL(__pm_runtime_resume);
|
||||
*
|
||||
* Return -EINVAL if runtime PM is disabled for @dev.
|
||||
*
|
||||
- * Otherwise, if the runtime PM status of @dev is %RPM_ACTIVE and either
|
||||
- * @ign_usage_count is %true or the runtime PM usage counter of @dev is not
|
||||
- * zero, increment the usage counter of @dev and return 1. Otherwise, return 0
|
||||
- * without changing the usage counter.
|
||||
+ * Otherwise, if its runtime PM status is %RPM_ACTIVE and (1) @ign_usage_count
|
||||
+ * is set, or (2) @dev is not ignoring children and its active child count is
|
||||
+ * nonero, or (3) the runtime PM usage counter of @dev is not zero, increment
|
||||
+ * the usage counter of @dev and return 1.
|
||||
+ *
|
||||
+ * Otherwise, return 0 without changing the usage counter.
|
||||
*
|
||||
* If @ign_usage_count is %true, this function can be used to prevent suspending
|
||||
* the device when its runtime PM status is %RPM_ACTIVE.
|
||||
@@ -1216,7 +1218,8 @@ static int pm_runtime_get_conditional(st
|
||||
retval = -EINVAL;
|
||||
} else if (dev->power.runtime_status != RPM_ACTIVE) {
|
||||
retval = 0;
|
||||
- } else if (ign_usage_count) {
|
||||
+ } else if (ign_usage_count || (!dev->power.ignore_children &&
|
||||
+ atomic_read(&dev->power.child_count) > 0)) {
|
||||
retval = 1;
|
||||
atomic_inc(&dev->power.usage_count);
|
||||
} else {
|
||||
@@ -1249,10 +1252,16 @@ EXPORT_SYMBOL_GPL(pm_runtime_get_if_acti
|
||||
* @dev: Target device.
|
||||
*
|
||||
* Increment the runtime PM usage counter of @dev if its runtime PM status is
|
||||
- * %RPM_ACTIVE and its runtime PM usage counter is greater than 0, in which case
|
||||
- * it returns 1. If the device is in a different state or its usage_count is 0,
|
||||
- * 0 is returned. -EINVAL is returned if runtime PM is disabled for the device,
|
||||
- * in which case also the usage_count will remain unmodified.
|
||||
+ * %RPM_ACTIVE and its runtime PM usage counter is greater than 0 or it is not
|
||||
+ * ignoring children and its active child count is nonzero. 1 is returned in
|
||||
+ * this case.
|
||||
+ *
|
||||
+ * If @dev is in a different state or it is not in use (that is, its usage
|
||||
+ * counter is 0, or it is ignoring children, or its active child count is 0),
|
||||
+ * 0 is returned.
|
||||
+ *
|
||||
+ * -EINVAL is returned if runtime PM is disabled for the device, in which case
|
||||
+ * also the usage counter of @dev is not updated.
|
||||
*/
|
||||
int pm_runtime_get_if_in_use(struct device *dev)
|
||||
{
|
@@ -0,0 +1,77 @@
|
||||
From 0958a5878e3cbeb42c0e6dbad00000c15a44c544 Mon Sep 17 00:00:00 2001
|
||||
From: Pavel Begunkov <asml.silence@gmail.com>
|
||||
Date: Wed, 2 Jul 2025 15:29:04 +0100
|
||||
Subject: io_uring/zcrx: always pass page to io_zcrx_copy_chunk
|
||||
|
||||
io_zcrx_copy_chunk() currently takes either a page or virtual address.
|
||||
Unify the parameters, make it take pages and resolve the linear part
|
||||
into a page the same way general networking code does that.
|
||||
|
||||
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
|
||||
Reviewed-by: David Wei <dw@davidwei.uk>
|
||||
Link: https://lore.kernel.org/r/b8f9f4bac027f5f44a9ccf85350912d1db41ceb8.1751466461.git.asml.silence@gmail.com
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
io_uring/zcrx.c | 21 ++++++++++-----------
|
||||
1 file changed, 10 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/io_uring/zcrx.c
|
||||
+++ b/io_uring/zcrx.c
|
||||
@@ -968,8 +968,8 @@ static struct net_iov *io_zcrx_alloc_fal
|
||||
}
|
||||
|
||||
static ssize_t io_zcrx_copy_chunk(struct io_kiocb *req, struct io_zcrx_ifq *ifq,
|
||||
- void *src_base, struct page *src_page,
|
||||
- unsigned int src_offset, size_t len)
|
||||
+ struct page *src_page, unsigned int src_offset,
|
||||
+ size_t len)
|
||||
{
|
||||
struct io_zcrx_area *area = ifq->area;
|
||||
size_t copied = 0;
|
||||
@@ -983,7 +983,7 @@ static ssize_t io_zcrx_copy_chunk(struct
|
||||
const int dst_off = 0;
|
||||
struct net_iov *niov;
|
||||
struct page *dst_page;
|
||||
- void *dst_addr;
|
||||
+ void *dst_addr, *src_addr;
|
||||
|
||||
niov = io_zcrx_alloc_fallback(area);
|
||||
if (!niov) {
|
||||
@@ -993,13 +993,11 @@ static ssize_t io_zcrx_copy_chunk(struct
|
||||
|
||||
dst_page = io_zcrx_iov_page(niov);
|
||||
dst_addr = kmap_local_page(dst_page);
|
||||
- if (src_page)
|
||||
- src_base = kmap_local_page(src_page);
|
||||
+ src_addr = kmap_local_page(src_page);
|
||||
|
||||
- memcpy(dst_addr, src_base + src_offset, copy_size);
|
||||
+ memcpy(dst_addr, src_addr + src_offset, copy_size);
|
||||
|
||||
- if (src_page)
|
||||
- kunmap_local(src_base);
|
||||
+ kunmap_local(src_addr);
|
||||
kunmap_local(dst_addr);
|
||||
|
||||
if (!io_zcrx_queue_cqe(req, niov, ifq, dst_off, copy_size)) {
|
||||
@@ -1028,7 +1026,7 @@ static int io_zcrx_copy_frag(struct io_k
|
||||
|
||||
skb_frag_foreach_page(frag, off, len,
|
||||
page, p_off, p_len, t) {
|
||||
- ret = io_zcrx_copy_chunk(req, ifq, NULL, page, p_off, p_len);
|
||||
+ ret = io_zcrx_copy_chunk(req, ifq, page, p_off, p_len);
|
||||
if (ret < 0)
|
||||
return copied ? copied : ret;
|
||||
copied += ret;
|
||||
@@ -1090,8 +1088,9 @@ io_zcrx_recv_skb(read_descriptor_t *desc
|
||||
size_t to_copy;
|
||||
|
||||
to_copy = min_t(size_t, skb_headlen(skb) - offset, len);
|
||||
- copied = io_zcrx_copy_chunk(req, ifq, skb->data, NULL,
|
||||
- offset, to_copy);
|
||||
+ copied = io_zcrx_copy_chunk(req, ifq, virt_to_page(skb->data),
|
||||
+ offset_in_page(skb->data) + offset,
|
||||
+ to_copy);
|
||||
if (copied < 0) {
|
||||
ret = copied;
|
||||
goto out;
|
26
debian/patches/patchset-pf/steady/0011-io_uring-zcrx-assert-area-type-in-io_zcrx_iov_page.patch
vendored
Normal file
26
debian/patches/patchset-pf/steady/0011-io_uring-zcrx-assert-area-type-in-io_zcrx_iov_page.patch
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
From 221ca821b4f8439aa9749e41f1a35b0b19c4d825 Mon Sep 17 00:00:00 2001
|
||||
From: Pavel Begunkov <asml.silence@gmail.com>
|
||||
Date: Wed, 2 Jul 2025 15:29:08 +0100
|
||||
Subject: io_uring/zcrx: assert area type in io_zcrx_iov_page
|
||||
|
||||
Add a simple debug assertion to io_zcrx_iov_page() making it's not
|
||||
trying to return pages for a dmabuf area.
|
||||
|
||||
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
|
||||
Link: https://lore.kernel.org/r/c3c30a926a18436a399a1768f3cc86c76cd17fa7.1751466461.git.asml.silence@gmail.com
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
io_uring/zcrx.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- a/io_uring/zcrx.c
|
||||
+++ b/io_uring/zcrx.c
|
||||
@@ -44,6 +44,8 @@ static inline struct page *io_zcrx_iov_p
|
||||
{
|
||||
struct io_zcrx_area *area = io_zcrx_iov_to_area(niov);
|
||||
|
||||
+ lockdep_assert(!area->mem.is_dmabuf);
|
||||
+
|
||||
return area->mem.pages[net_iov_idx(niov)];
|
||||
}
|
||||
|
142
debian/patches/patchset-pf/steady/0012-io_uring-zcrx-prepare-fallback-for-larger-pages.patch
vendored
Normal file
142
debian/patches/patchset-pf/steady/0012-io_uring-zcrx-prepare-fallback-for-larger-pages.patch
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
From ace17dfbf605c4eab9eb68c897ace0708d466bca Mon Sep 17 00:00:00 2001
|
||||
From: Pavel Begunkov <asml.silence@gmail.com>
|
||||
Date: Wed, 2 Jul 2025 15:29:09 +0100
|
||||
Subject: io_uring/zcrx: prepare fallback for larger pages
|
||||
|
||||
io_zcrx_copy_chunk() processes one page at a time, which won't be
|
||||
sufficient when the net_iov size grows. Introduce a structure keeping
|
||||
the target niov page and other parameters, it's more convenient and can
|
||||
be reused later. And add a helper function that can efficient copy
|
||||
buffers of an arbitrary length. For 64bit archs the loop inside should
|
||||
be compiled out.
|
||||
|
||||
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
|
||||
Link: https://lore.kernel.org/r/e84bc705a4e1edeb9aefff470d96558d8232388f.1751466461.git.asml.silence@gmail.com
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
io_uring/zcrx.c | 83 +++++++++++++++++++++++++++++++++----------------
|
||||
1 file changed, 56 insertions(+), 27 deletions(-)
|
||||
|
||||
--- a/io_uring/zcrx.c
|
||||
+++ b/io_uring/zcrx.c
|
||||
@@ -969,6 +969,51 @@ static struct net_iov *io_zcrx_alloc_fal
|
||||
return niov;
|
||||
}
|
||||
|
||||
+struct io_copy_cache {
|
||||
+ struct page *page;
|
||||
+ unsigned long offset;
|
||||
+ size_t size;
|
||||
+};
|
||||
+
|
||||
+static ssize_t io_copy_page(struct io_copy_cache *cc, struct page *src_page,
|
||||
+ unsigned int src_offset, size_t len)
|
||||
+{
|
||||
+ size_t copied = 0;
|
||||
+
|
||||
+ len = min(len, cc->size);
|
||||
+
|
||||
+ while (len) {
|
||||
+ void *src_addr, *dst_addr;
|
||||
+ struct page *dst_page = cc->page;
|
||||
+ unsigned dst_offset = cc->offset;
|
||||
+ size_t n = len;
|
||||
+
|
||||
+ if (folio_test_partial_kmap(page_folio(dst_page)) ||
|
||||
+ folio_test_partial_kmap(page_folio(src_page))) {
|
||||
+ dst_page = nth_page(dst_page, dst_offset / PAGE_SIZE);
|
||||
+ dst_offset = offset_in_page(dst_offset);
|
||||
+ src_page = nth_page(src_page, src_offset / PAGE_SIZE);
|
||||
+ src_offset = offset_in_page(src_offset);
|
||||
+ n = min(PAGE_SIZE - src_offset, PAGE_SIZE - dst_offset);
|
||||
+ n = min(n, len);
|
||||
+ }
|
||||
+
|
||||
+ dst_addr = kmap_local_page(dst_page) + dst_offset;
|
||||
+ src_addr = kmap_local_page(src_page) + src_offset;
|
||||
+
|
||||
+ memcpy(dst_addr, src_addr, n);
|
||||
+
|
||||
+ kunmap_local(src_addr);
|
||||
+ kunmap_local(dst_addr);
|
||||
+
|
||||
+ cc->size -= n;
|
||||
+ cc->offset += n;
|
||||
+ len -= n;
|
||||
+ copied += n;
|
||||
+ }
|
||||
+ return copied;
|
||||
+}
|
||||
+
|
||||
static ssize_t io_zcrx_copy_chunk(struct io_kiocb *req, struct io_zcrx_ifq *ifq,
|
||||
struct page *src_page, unsigned int src_offset,
|
||||
size_t len)
|
||||
@@ -981,11 +1026,9 @@ static ssize_t io_zcrx_copy_chunk(struct
|
||||
return -EFAULT;
|
||||
|
||||
while (len) {
|
||||
- size_t copy_size = min_t(size_t, PAGE_SIZE, len);
|
||||
- const int dst_off = 0;
|
||||
+ struct io_copy_cache cc;
|
||||
struct net_iov *niov;
|
||||
- struct page *dst_page;
|
||||
- void *dst_addr, *src_addr;
|
||||
+ size_t n;
|
||||
|
||||
niov = io_zcrx_alloc_fallback(area);
|
||||
if (!niov) {
|
||||
@@ -993,25 +1036,22 @@ static ssize_t io_zcrx_copy_chunk(struct
|
||||
break;
|
||||
}
|
||||
|
||||
- dst_page = io_zcrx_iov_page(niov);
|
||||
- dst_addr = kmap_local_page(dst_page);
|
||||
- src_addr = kmap_local_page(src_page);
|
||||
-
|
||||
- memcpy(dst_addr, src_addr + src_offset, copy_size);
|
||||
+ cc.page = io_zcrx_iov_page(niov);
|
||||
+ cc.offset = 0;
|
||||
+ cc.size = PAGE_SIZE;
|
||||
|
||||
- kunmap_local(src_addr);
|
||||
- kunmap_local(dst_addr);
|
||||
+ n = io_copy_page(&cc, src_page, src_offset, len);
|
||||
|
||||
- if (!io_zcrx_queue_cqe(req, niov, ifq, dst_off, copy_size)) {
|
||||
+ if (!io_zcrx_queue_cqe(req, niov, ifq, 0, n)) {
|
||||
io_zcrx_return_niov(niov);
|
||||
ret = -ENOSPC;
|
||||
break;
|
||||
}
|
||||
|
||||
io_zcrx_get_niov_uref(niov);
|
||||
- src_offset += copy_size;
|
||||
- len -= copy_size;
|
||||
- copied += copy_size;
|
||||
+ src_offset += n;
|
||||
+ len -= n;
|
||||
+ copied += n;
|
||||
}
|
||||
|
||||
return copied ? copied : ret;
|
||||
@@ -1021,19 +1061,8 @@ static int io_zcrx_copy_frag(struct io_k
|
||||
const skb_frag_t *frag, int off, int len)
|
||||
{
|
||||
struct page *page = skb_frag_page(frag);
|
||||
- u32 p_off, p_len, t, copied = 0;
|
||||
- int ret = 0;
|
||||
|
||||
- off += skb_frag_off(frag);
|
||||
-
|
||||
- skb_frag_foreach_page(frag, off, len,
|
||||
- page, p_off, p_len, t) {
|
||||
- ret = io_zcrx_copy_chunk(req, ifq, page, p_off, p_len);
|
||||
- if (ret < 0)
|
||||
- return copied ? copied : ret;
|
||||
- copied += ret;
|
||||
- }
|
||||
- return copied;
|
||||
+ return io_zcrx_copy_chunk(req, ifq, page, off + skb_frag_off(frag), len);
|
||||
}
|
||||
|
||||
static int io_zcrx_recv_frag(struct io_kiocb *req, struct io_zcrx_ifq *ifq,
|
@@ -0,0 +1,57 @@
|
||||
From 127ab7f801b3ec9cf94d2436ef1f579a1fc09dd6 Mon Sep 17 00:00:00 2001
|
||||
From: Eric Biggers <ebiggers@kernel.org>
|
||||
Date: Tue, 8 Jul 2025 12:38:28 -0700
|
||||
Subject: crypto: x86/aegis - Fix sleeping when disallowed on PREEMPT_RT
|
||||
|
||||
skcipher_walk_done() can call kfree(), which takes a spinlock, which
|
||||
makes it incorrect to call while preemption is disabled on PREEMPT_RT.
|
||||
Therefore, end the kernel-mode FPU section before calling
|
||||
skcipher_walk_done(), and restart it afterwards.
|
||||
|
||||
Moreover, pass atomic=false to skcipher_walk_aead_encrypt() instead of
|
||||
atomic=true. The point of atomic=true was to make skcipher_walk_done()
|
||||
safe to call while in a kernel-mode FPU section, but that does not
|
||||
actually work. So just use the usual atomic=false.
|
||||
|
||||
Fixes: 1d373d4e8e15 ("crypto: x86 - Add optimized AEGIS implementations")
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
arch/x86/crypto/aegis128-aesni-glue.c | 8 ++++++--
|
||||
1 file changed, 6 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/arch/x86/crypto/aegis128-aesni-glue.c
|
||||
+++ b/arch/x86/crypto/aegis128-aesni-glue.c
|
||||
@@ -119,7 +119,9 @@ crypto_aegis128_aesni_process_crypt(stru
|
||||
walk->dst.virt.addr,
|
||||
round_down(walk->nbytes,
|
||||
AEGIS128_BLOCK_SIZE));
|
||||
+ kernel_fpu_end();
|
||||
skcipher_walk_done(walk, walk->nbytes % AEGIS128_BLOCK_SIZE);
|
||||
+ kernel_fpu_begin();
|
||||
}
|
||||
|
||||
if (walk->nbytes) {
|
||||
@@ -131,7 +133,9 @@ crypto_aegis128_aesni_process_crypt(stru
|
||||
aegis128_aesni_dec_tail(state, walk->src.virt.addr,
|
||||
walk->dst.virt.addr,
|
||||
walk->nbytes);
|
||||
+ kernel_fpu_end();
|
||||
skcipher_walk_done(walk, 0);
|
||||
+ kernel_fpu_begin();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,9 +180,9 @@ crypto_aegis128_aesni_crypt(struct aead_
|
||||
struct aegis_state state;
|
||||
|
||||
if (enc)
|
||||
- skcipher_walk_aead_encrypt(&walk, req, true);
|
||||
+ skcipher_walk_aead_encrypt(&walk, req, false);
|
||||
else
|
||||
- skcipher_walk_aead_decrypt(&walk, req, true);
|
||||
+ skcipher_walk_aead_decrypt(&walk, req, false);
|
||||
|
||||
kernel_fpu_begin();
|
||||
|
122
debian/patches/patchset-pf/steady/0014-crypto-x86-aegis-Add-missing-error-checks.patch
vendored
Normal file
122
debian/patches/patchset-pf/steady/0014-crypto-x86-aegis-Add-missing-error-checks.patch
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
From 3bc9bc41e634767f001b7b37b6f1f89fc0214b8a Mon Sep 17 00:00:00 2001
|
||||
From: Eric Biggers <ebiggers@kernel.org>
|
||||
Date: Tue, 8 Jul 2025 12:38:29 -0700
|
||||
Subject: crypto: x86/aegis - Add missing error checks
|
||||
|
||||
The skcipher_walk functions can allocate memory and can fail, so
|
||||
checking for errors is necessary.
|
||||
|
||||
Fixes: 1d373d4e8e15 ("crypto: x86 - Add optimized AEGIS implementations")
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
arch/x86/crypto/aegis128-aesni-glue.c | 36 +++++++++++++++++++--------
|
||||
1 file changed, 25 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/arch/x86/crypto/aegis128-aesni-glue.c
|
||||
+++ b/arch/x86/crypto/aegis128-aesni-glue.c
|
||||
@@ -104,10 +104,12 @@ static void crypto_aegis128_aesni_proces
|
||||
}
|
||||
}
|
||||
|
||||
-static __always_inline void
|
||||
+static __always_inline int
|
||||
crypto_aegis128_aesni_process_crypt(struct aegis_state *state,
|
||||
struct skcipher_walk *walk, bool enc)
|
||||
{
|
||||
+ int err = 0;
|
||||
+
|
||||
while (walk->nbytes >= AEGIS128_BLOCK_SIZE) {
|
||||
if (enc)
|
||||
aegis128_aesni_enc(state, walk->src.virt.addr,
|
||||
@@ -120,7 +122,8 @@ crypto_aegis128_aesni_process_crypt(stru
|
||||
round_down(walk->nbytes,
|
||||
AEGIS128_BLOCK_SIZE));
|
||||
kernel_fpu_end();
|
||||
- skcipher_walk_done(walk, walk->nbytes % AEGIS128_BLOCK_SIZE);
|
||||
+ err = skcipher_walk_done(walk,
|
||||
+ walk->nbytes % AEGIS128_BLOCK_SIZE);
|
||||
kernel_fpu_begin();
|
||||
}
|
||||
|
||||
@@ -134,9 +137,10 @@ crypto_aegis128_aesni_process_crypt(stru
|
||||
walk->dst.virt.addr,
|
||||
walk->nbytes);
|
||||
kernel_fpu_end();
|
||||
- skcipher_walk_done(walk, 0);
|
||||
+ err = skcipher_walk_done(walk, 0);
|
||||
kernel_fpu_begin();
|
||||
}
|
||||
+ return err;
|
||||
}
|
||||
|
||||
static struct aegis_ctx *crypto_aegis128_aesni_ctx(struct crypto_aead *aead)
|
||||
@@ -169,7 +173,7 @@ static int crypto_aegis128_aesni_setauth
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static __always_inline void
|
||||
+static __always_inline int
|
||||
crypto_aegis128_aesni_crypt(struct aead_request *req,
|
||||
struct aegis_block *tag_xor,
|
||||
unsigned int cryptlen, bool enc)
|
||||
@@ -178,20 +182,24 @@ crypto_aegis128_aesni_crypt(struct aead_
|
||||
struct aegis_ctx *ctx = crypto_aegis128_aesni_ctx(tfm);
|
||||
struct skcipher_walk walk;
|
||||
struct aegis_state state;
|
||||
+ int err;
|
||||
|
||||
if (enc)
|
||||
- skcipher_walk_aead_encrypt(&walk, req, false);
|
||||
+ err = skcipher_walk_aead_encrypt(&walk, req, false);
|
||||
else
|
||||
- skcipher_walk_aead_decrypt(&walk, req, false);
|
||||
+ err = skcipher_walk_aead_decrypt(&walk, req, false);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
|
||||
kernel_fpu_begin();
|
||||
|
||||
aegis128_aesni_init(&state, &ctx->key, req->iv);
|
||||
crypto_aegis128_aesni_process_ad(&state, req->src, req->assoclen);
|
||||
- crypto_aegis128_aesni_process_crypt(&state, &walk, enc);
|
||||
- aegis128_aesni_final(&state, tag_xor, req->assoclen, cryptlen);
|
||||
-
|
||||
+ err = crypto_aegis128_aesni_process_crypt(&state, &walk, enc);
|
||||
+ if (err == 0)
|
||||
+ aegis128_aesni_final(&state, tag_xor, req->assoclen, cryptlen);
|
||||
kernel_fpu_end();
|
||||
+ return err;
|
||||
}
|
||||
|
||||
static int crypto_aegis128_aesni_encrypt(struct aead_request *req)
|
||||
@@ -200,8 +208,11 @@ static int crypto_aegis128_aesni_encrypt
|
||||
struct aegis_block tag = {};
|
||||
unsigned int authsize = crypto_aead_authsize(tfm);
|
||||
unsigned int cryptlen = req->cryptlen;
|
||||
+ int err;
|
||||
|
||||
- crypto_aegis128_aesni_crypt(req, &tag, cryptlen, true);
|
||||
+ err = crypto_aegis128_aesni_crypt(req, &tag, cryptlen, true);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
|
||||
scatterwalk_map_and_copy(tag.bytes, req->dst,
|
||||
req->assoclen + cryptlen, authsize, 1);
|
||||
@@ -216,11 +227,14 @@ static int crypto_aegis128_aesni_decrypt
|
||||
struct aegis_block tag;
|
||||
unsigned int authsize = crypto_aead_authsize(tfm);
|
||||
unsigned int cryptlen = req->cryptlen - authsize;
|
||||
+ int err;
|
||||
|
||||
scatterwalk_map_and_copy(tag.bytes, req->src,
|
||||
req->assoclen + cryptlen, authsize, 0);
|
||||
|
||||
- crypto_aegis128_aesni_crypt(req, &tag, cryptlen, false);
|
||||
+ err = crypto_aegis128_aesni_crypt(req, &tag, cryptlen, false);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
|
||||
return crypto_memneq(tag.bytes, zeros.bytes, authsize) ? -EBADMSG : 0;
|
||||
}
|
54
debian/patches/patchset-pf/steady/0015-hwmon-gsc-hwmon-fix-fan-pwm-setpoint-show-functions.patch
vendored
Normal file
54
debian/patches/patchset-pf/steady/0015-hwmon-gsc-hwmon-fix-fan-pwm-setpoint-show-functions.patch
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
From 8b4284861b77422d25c46fe00402754ab1a156cc Mon Sep 17 00:00:00 2001
|
||||
From: Tim Harvey <tharvey@gateworks.com>
|
||||
Date: Fri, 18 Jul 2025 13:02:59 -0700
|
||||
Subject: hwmon: (gsc-hwmon) fix fan pwm setpoint show functions
|
||||
|
||||
The Linux hwmon sysfs API values for pwmX_auto_pointY_pwm represent an
|
||||
integer value between 0 (0%) to 255 (100%) and the pwmX_auto_pointY_temp
|
||||
represent millidegrees Celcius.
|
||||
|
||||
Commit a6d80df47ee2 ("hwmon: (gsc-hwmon) fix fan pwm temperature
|
||||
scaling") properly addressed the incorrect scaling in the
|
||||
pwm_auto_point_temp_store implementation but erroneously scaled
|
||||
the pwm_auto_point_pwm_show (pwm value) instead of the
|
||||
pwm_auto_point_temp_show (temp value) resulting in:
|
||||
# cat /sys/class/hwmon/hwmon0/pwm1_auto_point6_pwm
|
||||
25500
|
||||
# cat /sys/class/hwmon/hwmon0/pwm1_auto_point6_temp
|
||||
4500
|
||||
|
||||
Fix the scaling of these attributes:
|
||||
# cat /sys/class/hwmon/hwmon0/pwm1_auto_point6_pwm
|
||||
255
|
||||
# cat /sys/class/hwmon/hwmon0/pwm1_auto_point6_temp
|
||||
45000
|
||||
|
||||
Fixes: a6d80df47ee2 ("hwmon: (gsc-hwmon) fix fan pwm temperature scaling")
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Tim Harvey <tharvey@gateworks.com>
|
||||
Link: https://lore.kernel.org/r/20250718200259.1840792-1-tharvey@gateworks.com
|
||||
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
|
||||
---
|
||||
drivers/hwmon/gsc-hwmon.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/hwmon/gsc-hwmon.c
|
||||
+++ b/drivers/hwmon/gsc-hwmon.c
|
||||
@@ -64,7 +64,7 @@ static ssize_t pwm_auto_point_temp_show(
|
||||
return ret;
|
||||
|
||||
ret = regs[0] | regs[1] << 8;
|
||||
- return sprintf(buf, "%d\n", ret * 10);
|
||||
+ return sprintf(buf, "%d\n", ret * 100);
|
||||
}
|
||||
|
||||
static ssize_t pwm_auto_point_temp_store(struct device *dev,
|
||||
@@ -99,7 +99,7 @@ static ssize_t pwm_auto_point_pwm_show(s
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
|
||||
- return sprintf(buf, "%d\n", 255 * (50 + (attr->index * 10)));
|
||||
+ return sprintf(buf, "%d\n", 255 * (50 + (attr->index * 10)) / 100);
|
||||
}
|
||||
|
||||
static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point1_pwm, pwm_auto_point_pwm, 0);
|
@@ -0,0 +1,31 @@
|
||||
From 3f91f07c241bea4ec294315cb41df81f123fa0bb Mon Sep 17 00:00:00 2001
|
||||
From: Myrrh Periwinkle <myrrhperiwinkle@qtmlabs.xyz>
|
||||
Date: Wed, 2 Jul 2025 21:17:57 +0700
|
||||
Subject: vt: keyboard: Don't process Unicode characters in K_OFF mode
|
||||
|
||||
We don't process Unicode characters if the virtual terminal is in raw
|
||||
mode, so there's no reason why we shouldn't do the same for K_OFF
|
||||
(especially since people would expect K_OFF to actually turn off all VT
|
||||
key processing).
|
||||
|
||||
Fixes: 9fc3de9c8356 ("vt: Add virtual console keyboard mode OFF")
|
||||
Signed-off-by: Myrrh Periwinkle <myrrhperiwinkle@qtmlabs.xyz>
|
||||
Cc: stable <stable@kernel.org>
|
||||
Reviewed-by: Jiri Slaby <jirislaby@kernel.org>
|
||||
Link: https://lore.kernel.org/r/20250702-vt-misc-unicode-fixes-v1-1-c27e143cc2eb@qtmlabs.xyz
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/tty/vt/keyboard.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/tty/vt/keyboard.c
|
||||
+++ b/drivers/tty/vt/keyboard.c
|
||||
@@ -1487,7 +1487,7 @@ static void kbd_keycode(unsigned int key
|
||||
rc = atomic_notifier_call_chain(&keyboard_notifier_list,
|
||||
KBD_UNICODE, ¶m);
|
||||
if (rc != NOTIFY_STOP)
|
||||
- if (down && !raw_mode)
|
||||
+ if (down && !(raw_mode || kbd->kbdmode == VC_OFF))
|
||||
k_unicode(vc, keysym, !down);
|
||||
return;
|
||||
}
|
190
debian/patches/patchset-pf/steady/0017-vt-defkeymap-Map-keycodes-above-127-to-K_HOLE.patch
vendored
Normal file
190
debian/patches/patchset-pf/steady/0017-vt-defkeymap-Map-keycodes-above-127-to-K_HOLE.patch
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
From f575281d91029d2dbfa0fa628cdc72e80fcd626f Mon Sep 17 00:00:00 2001
|
||||
From: Myrrh Periwinkle <myrrhperiwinkle@qtmlabs.xyz>
|
||||
Date: Wed, 2 Jul 2025 21:17:58 +0700
|
||||
Subject: vt: defkeymap: Map keycodes above 127 to K_HOLE
|
||||
|
||||
The maximum number of keycodes got bumped to 256 a very long time ago,
|
||||
but the default keymaps were never adjusted to match. This is causing
|
||||
the kernel to interpret keycodes above 127 as U+0000 if the shipped
|
||||
generated keymap is used.
|
||||
|
||||
Fix this by mapping all keycodes above 127 to K_HOLE so the kernel
|
||||
ignores them.
|
||||
|
||||
The contents of this patche were generated by rerunning `loadkeys
|
||||
--mktable --unicode` and only including the changes to map keycodes
|
||||
above 127 to K_HOLE.
|
||||
|
||||
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
|
||||
Signed-off-by: Myrrh Periwinkle <myrrhperiwinkle@qtmlabs.xyz>
|
||||
Cc: stable <stable@kernel.org>
|
||||
Reviewed-by: Jiri Slaby <jirislaby@kernel.org>
|
||||
Link: https://lore.kernel.org/r/20250702-vt-misc-unicode-fixes-v1-2-c27e143cc2eb@qtmlabs.xyz
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/tty/vt/defkeymap.c_shipped | 112 +++++++++++++++++++++++++++++
|
||||
1 file changed, 112 insertions(+)
|
||||
|
||||
--- a/drivers/tty/vt/defkeymap.c_shipped
|
||||
+++ b/drivers/tty/vt/defkeymap.c_shipped
|
||||
@@ -23,6 +23,22 @@ unsigned short plain_map[NR_KEYS] = {
|
||||
0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
|
||||
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
|
||||
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
};
|
||||
|
||||
static unsigned short shift_map[NR_KEYS] = {
|
||||
@@ -42,6 +58,22 @@ static unsigned short shift_map[NR_KEYS]
|
||||
0xf20b, 0xf601, 0xf602, 0xf117, 0xf600, 0xf20a, 0xf115, 0xf116,
|
||||
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
|
||||
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
};
|
||||
|
||||
static unsigned short altgr_map[NR_KEYS] = {
|
||||
@@ -61,6 +93,22 @@ static unsigned short altgr_map[NR_KEYS]
|
||||
0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
|
||||
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
|
||||
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
};
|
||||
|
||||
static unsigned short ctrl_map[NR_KEYS] = {
|
||||
@@ -80,6 +128,22 @@ static unsigned short ctrl_map[NR_KEYS]
|
||||
0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
|
||||
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
|
||||
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
};
|
||||
|
||||
static unsigned short shift_ctrl_map[NR_KEYS] = {
|
||||
@@ -99,6 +163,22 @@ static unsigned short shift_ctrl_map[NR_
|
||||
0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
|
||||
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
|
||||
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
};
|
||||
|
||||
static unsigned short alt_map[NR_KEYS] = {
|
||||
@@ -118,6 +198,22 @@ static unsigned short alt_map[NR_KEYS] =
|
||||
0xf118, 0xf210, 0xf211, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
|
||||
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
|
||||
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
};
|
||||
|
||||
static unsigned short ctrl_alt_map[NR_KEYS] = {
|
||||
@@ -137,6 +233,22 @@ static unsigned short ctrl_alt_map[NR_KE
|
||||
0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf20c,
|
||||
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
|
||||
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
|
||||
};
|
||||
|
||||
unsigned short *key_maps[MAX_NR_KEYMAPS] = {
|
55
debian/patches/patchset-pf/steady/0018-serial-8250-fix-panic-due-to-PSLVERR.patch
vendored
Normal file
55
debian/patches/patchset-pf/steady/0018-serial-8250-fix-panic-due-to-PSLVERR.patch
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
From c0bcd8c710c48ab93f0b72c1a3611c39a68c3a74 Mon Sep 17 00:00:00 2001
|
||||
From: Yunhui Cui <cuiyunhui@bytedance.com>
|
||||
Date: Wed, 23 Jul 2025 10:33:22 +0800
|
||||
Subject: serial: 8250: fix panic due to PSLVERR
|
||||
|
||||
When the PSLVERR_RESP_EN parameter is set to 1, the device generates
|
||||
an error response if an attempt is made to read an empty RBR (Receive
|
||||
Buffer Register) while the FIFO is enabled.
|
||||
|
||||
In serial8250_do_startup(), calling serial_port_out(port, UART_LCR,
|
||||
UART_LCR_WLEN8) triggers dw8250_check_lcr(), which invokes
|
||||
dw8250_force_idle() and serial8250_clear_and_reinit_fifos(). The latter
|
||||
function enables the FIFO via serial_out(p, UART_FCR, p->fcr).
|
||||
Execution proceeds to the serial_port_in(port, UART_RX).
|
||||
This satisfies the PSLVERR trigger condition.
|
||||
|
||||
When another CPU (e.g., using printk()) is accessing the UART (UART
|
||||
is busy), the current CPU fails the check (value & ~UART_LCR_SPAR) ==
|
||||
(lcr & ~UART_LCR_SPAR) in dw8250_check_lcr(), causing it to enter
|
||||
dw8250_force_idle().
|
||||
|
||||
Put serial_port_out(port, UART_LCR, UART_LCR_WLEN8) under the port->lock
|
||||
to fix this issue.
|
||||
|
||||
Panic backtrace:
|
||||
[ 0.442336] Oops - unknown exception [#1]
|
||||
[ 0.442343] epc : dw8250_serial_in32+0x1e/0x4a
|
||||
[ 0.442351] ra : serial8250_do_startup+0x2c8/0x88e
|
||||
...
|
||||
[ 0.442416] console_on_rootfs+0x26/0x70
|
||||
|
||||
Fixes: c49436b657d0 ("serial: 8250_dw: Improve unwritable LCR workaround")
|
||||
Link: https://lore.kernel.org/all/84cydt5peu.fsf@jogness.linutronix.de/T/
|
||||
Signed-off-by: Yunhui Cui <cuiyunhui@bytedance.com>
|
||||
Reviewed-by: John Ogness <john.ogness@linutronix.de>
|
||||
Cc: stable <stable@kernel.org>
|
||||
Link: https://lore.kernel.org/r/20250723023322.464-2-cuiyunhui@bytedance.com
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/tty/serial/8250/8250_port.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/tty/serial/8250/8250_port.c
|
||||
+++ b/drivers/tty/serial/8250/8250_port.c
|
||||
@@ -2376,9 +2376,9 @@ int serial8250_do_startup(struct uart_po
|
||||
/*
|
||||
* Now, initialize the UART
|
||||
*/
|
||||
+ uart_port_lock_irqsave(port, &flags);
|
||||
serial_port_out(port, UART_LCR, UART_LCR_WLEN8);
|
||||
|
||||
- uart_port_lock_irqsave(port, &flags);
|
||||
if (up->port.flags & UPF_FOURPORT) {
|
||||
if (!up->port.irq)
|
||||
up->port.mctrl |= TIOCM_OUT1;
|
@@ -0,0 +1,74 @@
|
||||
From 2ee6decb1435c8331404d590f7a5a2d6a5711760 Mon Sep 17 00:00:00 2001
|
||||
From: SeongJae Park <sj@kernel.org>
|
||||
Date: Mon, 16 Jun 2025 10:23:44 -0700
|
||||
Subject: mm/damon/paddr: use alloc_migartion_target() with no migration
|
||||
fallback nodemask
|
||||
|
||||
Patch series "mm/damon: use alloc_migrate_target() for
|
||||
DAMOS_MIGRATE_{HOT,COLD}".
|
||||
|
||||
DAMOS_MIGRATE_{HOT,COLD} implementation resembles that for demotion, and
|
||||
hence the behavior is also similar to that. But, since those are not only
|
||||
for demotion but general migrations, it would be better to match with that
|
||||
for move_pages() system call. Make the implementation and the behavior
|
||||
more similar to move_pages() by not setting migration fallback nodes, and
|
||||
using alloc_migration_target() instead of alloc_migrate_folio().
|
||||
|
||||
alloc_migrate_folio() was renamed from alloc_demote_folio() and been
|
||||
non-static function, to let DAMOS_MIGRATE_{HOT,COLD} call it. As
|
||||
alloc_migration_target() is called instead, the renaming and de-static
|
||||
changes are no more required but could only make future code readers be
|
||||
confused. Revert the changes, too.
|
||||
|
||||
|
||||
This patch (of 3):
|
||||
|
||||
DAMOS_MIGRATE_{HOT,COLD} implementation resembles that for
|
||||
demote_folio_list(). Because those are not only for demotion but general
|
||||
folio migrations, it makes more sense to behave similarly to move_pages()
|
||||
system call. Make the behavior more similar to move_pages(), by using
|
||||
alloc_migration_target() instead of alloc_migrate_folio(), without
|
||||
fallback nodemask.
|
||||
|
||||
Link: https://lkml.kernel.org/r/20250616172346.67659-2-sj@kernel.org
|
||||
Signed-off-by: SeongJae Park <sj@kernel.org>
|
||||
Reviewed-by: Joshua Hahn <joshua.hahnjy@gmail.com>
|
||||
Cc: David Hildenbrand <david@redhat.com>
|
||||
Cc: Honggyu Kim <honggyu.kim@sk.com>
|
||||
Cc: Johannes Weiner <hannes@cmpxchg.org>
|
||||
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
|
||||
Cc: Michal Hocko <mhocko@kernel.org>
|
||||
Cc: Qi Zheng <zhengqi.arch@bytedance.com>
|
||||
Cc: Shakeel Butt <shakeel.butt@linux.dev>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
---
|
||||
mm/damon/paddr.c | 4 +---
|
||||
1 file changed, 1 insertion(+), 3 deletions(-)
|
||||
|
||||
--- a/mm/damon/paddr.c
|
||||
+++ b/mm/damon/paddr.c
|
||||
@@ -386,7 +386,6 @@ static unsigned int __damon_pa_migrate_f
|
||||
int target_nid)
|
||||
{
|
||||
unsigned int nr_succeeded = 0;
|
||||
- nodemask_t allowed_mask = NODE_MASK_NONE;
|
||||
struct migration_target_control mtc = {
|
||||
/*
|
||||
* Allocate from 'node', or fail quickly and quietly.
|
||||
@@ -396,7 +395,6 @@ static unsigned int __damon_pa_migrate_f
|
||||
.gfp_mask = (GFP_HIGHUSER_MOVABLE & ~__GFP_RECLAIM) |
|
||||
__GFP_NOWARN | __GFP_NOMEMALLOC | GFP_NOWAIT,
|
||||
.nid = target_nid,
|
||||
- .nmask = &allowed_mask
|
||||
};
|
||||
|
||||
if (pgdat->node_id == target_nid || target_nid == NUMA_NO_NODE)
|
||||
@@ -406,7 +404,7 @@ static unsigned int __damon_pa_migrate_f
|
||||
return 0;
|
||||
|
||||
/* Migration ignores all cpuset and mempolicy settings */
|
||||
- migrate_pages(migrate_folios, alloc_migrate_folio, NULL,
|
||||
+ migrate_pages(migrate_folios, alloc_migration_target, NULL,
|
||||
(unsigned long)&mtc, MIGRATE_ASYNC, MR_DAMON,
|
||||
&nr_succeeded);
|
||||
|
318
debian/patches/patchset-pf/steady/0020-mm-damon-move-migration-helpers-from-paddr-to-ops-co.patch
vendored
Normal file
318
debian/patches/patchset-pf/steady/0020-mm-damon-move-migration-helpers-from-paddr-to-ops-co.patch
vendored
Normal file
@@ -0,0 +1,318 @@
|
||||
From 9292d9753eeab6dd9492ec28b79045ab4890652a Mon Sep 17 00:00:00 2001
|
||||
From: Bijan Tabatabai <bijantabatab@micron.com>
|
||||
Date: Tue, 8 Jul 2025 19:59:38 -0500
|
||||
Subject: mm/damon: move migration helpers from paddr to ops-common
|
||||
|
||||
This patch moves the damon_pa_migrate_pages function along with its
|
||||
corresponding helper functions from paddr to ops-common. The function
|
||||
prefix of "damon_pa_" was also changed to just "damon_" accordingly.
|
||||
|
||||
This patch will allow page migration to be available to vaddr schemes as
|
||||
well as paddr schemes.
|
||||
|
||||
Link: https://lkml.kernel.org/r/20250709005952.17776-9-bijan311@gmail.com
|
||||
Co-developed-by: Ravi Shankar Jonnalagadda <ravis.opensrc@micron.com>
|
||||
Signed-off-by: Ravi Shankar Jonnalagadda <ravis.opensrc@micron.com>
|
||||
Signed-off-by: Bijan Tabatabai <bijantabatab@micron.com>
|
||||
Reviewed-by: SeongJae Park <sj@kernel.org>
|
||||
Cc: Jonathan Corbet <corbet@lwn.net>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
---
|
||||
mm/damon/ops-common.c | 120 +++++++++++++++++++++++++++++++++++++++++
|
||||
mm/damon/ops-common.h | 2 +
|
||||
mm/damon/paddr.c | 122 +-----------------------------------------
|
||||
3 files changed, 123 insertions(+), 121 deletions(-)
|
||||
|
||||
--- a/mm/damon/ops-common.c
|
||||
+++ b/mm/damon/ops-common.c
|
||||
@@ -5,6 +5,7 @@
|
||||
* Author: SeongJae Park <sj@kernel.org>
|
||||
*/
|
||||
|
||||
+#include <linux/migrate.h>
|
||||
#include <linux/mmu_notifier.h>
|
||||
#include <linux/page_idle.h>
|
||||
#include <linux/pagemap.h>
|
||||
@@ -12,6 +13,7 @@
|
||||
#include <linux/swap.h>
|
||||
#include <linux/swapops.h>
|
||||
|
||||
+#include "../internal.h"
|
||||
#include "ops-common.h"
|
||||
|
||||
/*
|
||||
@@ -138,3 +140,121 @@ int damon_cold_score(struct damon_ctx *c
|
||||
/* Return coldness of the region */
|
||||
return DAMOS_MAX_SCORE - hotness;
|
||||
}
|
||||
+
|
||||
+static unsigned int __damon_migrate_folio_list(
|
||||
+ struct list_head *migrate_folios, struct pglist_data *pgdat,
|
||||
+ int target_nid)
|
||||
+{
|
||||
+ unsigned int nr_succeeded = 0;
|
||||
+ struct migration_target_control mtc = {
|
||||
+ /*
|
||||
+ * Allocate from 'node', or fail quickly and quietly.
|
||||
+ * When this happens, 'page' will likely just be discarded
|
||||
+ * instead of migrated.
|
||||
+ */
|
||||
+ .gfp_mask = (GFP_HIGHUSER_MOVABLE & ~__GFP_RECLAIM) |
|
||||
+ __GFP_NOWARN | __GFP_NOMEMALLOC | GFP_NOWAIT,
|
||||
+ .nid = target_nid,
|
||||
+ };
|
||||
+
|
||||
+ if (pgdat->node_id == target_nid || target_nid == NUMA_NO_NODE)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (list_empty(migrate_folios))
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Migration ignores all cpuset and mempolicy settings */
|
||||
+ migrate_pages(migrate_folios, alloc_migration_target, NULL,
|
||||
+ (unsigned long)&mtc, MIGRATE_ASYNC, MR_DAMON,
|
||||
+ &nr_succeeded);
|
||||
+
|
||||
+ return nr_succeeded;
|
||||
+}
|
||||
+
|
||||
+static unsigned int damon_migrate_folio_list(struct list_head *folio_list,
|
||||
+ struct pglist_data *pgdat,
|
||||
+ int target_nid)
|
||||
+{
|
||||
+ unsigned int nr_migrated = 0;
|
||||
+ struct folio *folio;
|
||||
+ LIST_HEAD(ret_folios);
|
||||
+ LIST_HEAD(migrate_folios);
|
||||
+
|
||||
+ while (!list_empty(folio_list)) {
|
||||
+ struct folio *folio;
|
||||
+
|
||||
+ cond_resched();
|
||||
+
|
||||
+ folio = lru_to_folio(folio_list);
|
||||
+ list_del(&folio->lru);
|
||||
+
|
||||
+ if (!folio_trylock(folio))
|
||||
+ goto keep;
|
||||
+
|
||||
+ /* Relocate its contents to another node. */
|
||||
+ list_add(&folio->lru, &migrate_folios);
|
||||
+ folio_unlock(folio);
|
||||
+ continue;
|
||||
+keep:
|
||||
+ list_add(&folio->lru, &ret_folios);
|
||||
+ }
|
||||
+ /* 'folio_list' is always empty here */
|
||||
+
|
||||
+ /* Migrate folios selected for migration */
|
||||
+ nr_migrated += __damon_migrate_folio_list(
|
||||
+ &migrate_folios, pgdat, target_nid);
|
||||
+ /*
|
||||
+ * Folios that could not be migrated are still in @migrate_folios. Add
|
||||
+ * those back on @folio_list
|
||||
+ */
|
||||
+ if (!list_empty(&migrate_folios))
|
||||
+ list_splice_init(&migrate_folios, folio_list);
|
||||
+
|
||||
+ try_to_unmap_flush();
|
||||
+
|
||||
+ list_splice(&ret_folios, folio_list);
|
||||
+
|
||||
+ while (!list_empty(folio_list)) {
|
||||
+ folio = lru_to_folio(folio_list);
|
||||
+ list_del(&folio->lru);
|
||||
+ folio_putback_lru(folio);
|
||||
+ }
|
||||
+
|
||||
+ return nr_migrated;
|
||||
+}
|
||||
+
|
||||
+unsigned long damon_migrate_pages(struct list_head *folio_list, int target_nid)
|
||||
+{
|
||||
+ int nid;
|
||||
+ unsigned long nr_migrated = 0;
|
||||
+ LIST_HEAD(node_folio_list);
|
||||
+ unsigned int noreclaim_flag;
|
||||
+
|
||||
+ if (list_empty(folio_list))
|
||||
+ return nr_migrated;
|
||||
+
|
||||
+ noreclaim_flag = memalloc_noreclaim_save();
|
||||
+
|
||||
+ nid = folio_nid(lru_to_folio(folio_list));
|
||||
+ do {
|
||||
+ struct folio *folio = lru_to_folio(folio_list);
|
||||
+
|
||||
+ if (nid == folio_nid(folio)) {
|
||||
+ list_move(&folio->lru, &node_folio_list);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ nr_migrated += damon_migrate_folio_list(&node_folio_list,
|
||||
+ NODE_DATA(nid),
|
||||
+ target_nid);
|
||||
+ nid = folio_nid(lru_to_folio(folio_list));
|
||||
+ } while (!list_empty(folio_list));
|
||||
+
|
||||
+ nr_migrated += damon_migrate_folio_list(&node_folio_list,
|
||||
+ NODE_DATA(nid),
|
||||
+ target_nid);
|
||||
+
|
||||
+ memalloc_noreclaim_restore(noreclaim_flag);
|
||||
+
|
||||
+ return nr_migrated;
|
||||
+}
|
||||
--- a/mm/damon/ops-common.h
|
||||
+++ b/mm/damon/ops-common.h
|
||||
@@ -16,3 +16,5 @@ int damon_cold_score(struct damon_ctx *c
|
||||
struct damos *s);
|
||||
int damon_hot_score(struct damon_ctx *c, struct damon_region *r,
|
||||
struct damos *s);
|
||||
+
|
||||
+unsigned long damon_migrate_pages(struct list_head *folio_list, int target_nid);
|
||||
--- a/mm/damon/paddr.c
|
||||
+++ b/mm/damon/paddr.c
|
||||
@@ -13,7 +13,6 @@
|
||||
#include <linux/rmap.h>
|
||||
#include <linux/swap.h>
|
||||
#include <linux/memory-tiers.h>
|
||||
-#include <linux/migrate.h>
|
||||
#include <linux/mm_inline.h>
|
||||
|
||||
#include "../internal.h"
|
||||
@@ -381,125 +380,6 @@ static unsigned long damon_pa_deactivate
|
||||
sz_filter_passed);
|
||||
}
|
||||
|
||||
-static unsigned int __damon_pa_migrate_folio_list(
|
||||
- struct list_head *migrate_folios, struct pglist_data *pgdat,
|
||||
- int target_nid)
|
||||
-{
|
||||
- unsigned int nr_succeeded = 0;
|
||||
- struct migration_target_control mtc = {
|
||||
- /*
|
||||
- * Allocate from 'node', or fail quickly and quietly.
|
||||
- * When this happens, 'page' will likely just be discarded
|
||||
- * instead of migrated.
|
||||
- */
|
||||
- .gfp_mask = (GFP_HIGHUSER_MOVABLE & ~__GFP_RECLAIM) |
|
||||
- __GFP_NOWARN | __GFP_NOMEMALLOC | GFP_NOWAIT,
|
||||
- .nid = target_nid,
|
||||
- };
|
||||
-
|
||||
- if (pgdat->node_id == target_nid || target_nid == NUMA_NO_NODE)
|
||||
- return 0;
|
||||
-
|
||||
- if (list_empty(migrate_folios))
|
||||
- return 0;
|
||||
-
|
||||
- /* Migration ignores all cpuset and mempolicy settings */
|
||||
- migrate_pages(migrate_folios, alloc_migration_target, NULL,
|
||||
- (unsigned long)&mtc, MIGRATE_ASYNC, MR_DAMON,
|
||||
- &nr_succeeded);
|
||||
-
|
||||
- return nr_succeeded;
|
||||
-}
|
||||
-
|
||||
-static unsigned int damon_pa_migrate_folio_list(struct list_head *folio_list,
|
||||
- struct pglist_data *pgdat,
|
||||
- int target_nid)
|
||||
-{
|
||||
- unsigned int nr_migrated = 0;
|
||||
- struct folio *folio;
|
||||
- LIST_HEAD(ret_folios);
|
||||
- LIST_HEAD(migrate_folios);
|
||||
-
|
||||
- while (!list_empty(folio_list)) {
|
||||
- struct folio *folio;
|
||||
-
|
||||
- cond_resched();
|
||||
-
|
||||
- folio = lru_to_folio(folio_list);
|
||||
- list_del(&folio->lru);
|
||||
-
|
||||
- if (!folio_trylock(folio))
|
||||
- goto keep;
|
||||
-
|
||||
- /* Relocate its contents to another node. */
|
||||
- list_add(&folio->lru, &migrate_folios);
|
||||
- folio_unlock(folio);
|
||||
- continue;
|
||||
-keep:
|
||||
- list_add(&folio->lru, &ret_folios);
|
||||
- }
|
||||
- /* 'folio_list' is always empty here */
|
||||
-
|
||||
- /* Migrate folios selected for migration */
|
||||
- nr_migrated += __damon_pa_migrate_folio_list(
|
||||
- &migrate_folios, pgdat, target_nid);
|
||||
- /*
|
||||
- * Folios that could not be migrated are still in @migrate_folios. Add
|
||||
- * those back on @folio_list
|
||||
- */
|
||||
- if (!list_empty(&migrate_folios))
|
||||
- list_splice_init(&migrate_folios, folio_list);
|
||||
-
|
||||
- try_to_unmap_flush();
|
||||
-
|
||||
- list_splice(&ret_folios, folio_list);
|
||||
-
|
||||
- while (!list_empty(folio_list)) {
|
||||
- folio = lru_to_folio(folio_list);
|
||||
- list_del(&folio->lru);
|
||||
- folio_putback_lru(folio);
|
||||
- }
|
||||
-
|
||||
- return nr_migrated;
|
||||
-}
|
||||
-
|
||||
-static unsigned long damon_pa_migrate_pages(struct list_head *folio_list,
|
||||
- int target_nid)
|
||||
-{
|
||||
- int nid;
|
||||
- unsigned long nr_migrated = 0;
|
||||
- LIST_HEAD(node_folio_list);
|
||||
- unsigned int noreclaim_flag;
|
||||
-
|
||||
- if (list_empty(folio_list))
|
||||
- return nr_migrated;
|
||||
-
|
||||
- noreclaim_flag = memalloc_noreclaim_save();
|
||||
-
|
||||
- nid = folio_nid(lru_to_folio(folio_list));
|
||||
- do {
|
||||
- struct folio *folio = lru_to_folio(folio_list);
|
||||
-
|
||||
- if (nid == folio_nid(folio)) {
|
||||
- list_move(&folio->lru, &node_folio_list);
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- nr_migrated += damon_pa_migrate_folio_list(&node_folio_list,
|
||||
- NODE_DATA(nid),
|
||||
- target_nid);
|
||||
- nid = folio_nid(lru_to_folio(folio_list));
|
||||
- } while (!list_empty(folio_list));
|
||||
-
|
||||
- nr_migrated += damon_pa_migrate_folio_list(&node_folio_list,
|
||||
- NODE_DATA(nid),
|
||||
- target_nid);
|
||||
-
|
||||
- memalloc_noreclaim_restore(noreclaim_flag);
|
||||
-
|
||||
- return nr_migrated;
|
||||
-}
|
||||
-
|
||||
static unsigned long damon_pa_migrate(struct damon_region *r, struct damos *s,
|
||||
unsigned long *sz_filter_passed)
|
||||
{
|
||||
@@ -527,7 +407,7 @@ put_folio:
|
||||
addr += folio_size(folio);
|
||||
folio_put(folio);
|
||||
}
|
||||
- applied = damon_pa_migrate_pages(&folio_list, s->target_nid);
|
||||
+ applied = damon_migrate_pages(&folio_list, s->target_nid);
|
||||
cond_resched();
|
||||
s->last_applied = folio;
|
||||
return applied * PAGE_SIZE;
|
381
debian/patches/patchset-pf/steady/0021-mm-damon-move-folio-filtering-from-paddr-to-ops-comm.patch
vendored
Normal file
381
debian/patches/patchset-pf/steady/0021-mm-damon-move-folio-filtering-from-paddr-to-ops-comm.patch
vendored
Normal file
@@ -0,0 +1,381 @@
|
||||
From 98fbe2f62c4263248a325867c439f9d7222a3c64 Mon Sep 17 00:00:00 2001
|
||||
From: Bijan Tabatabai <bijantabatab@micron.com>
|
||||
Date: Tue, 8 Jul 2025 19:59:42 -0500
|
||||
Subject: mm/damon: move folio filtering from paddr to ops-common
|
||||
|
||||
This patch moves damos_pa_filter_match and the functions it calls to
|
||||
ops-common, renaming it to damos_folio_filter_match. Doing so allows us
|
||||
to share the filtering logic for the vaddr version of the
|
||||
migrate_{hot,cold} schemes.
|
||||
|
||||
Link: https://lkml.kernel.org/r/20250709005952.17776-13-bijan311@gmail.com
|
||||
Co-developed-by: Ravi Shankar Jonnalagadda <ravis.opensrc@micron.com>
|
||||
Signed-off-by: Ravi Shankar Jonnalagadda <ravis.opensrc@micron.com>
|
||||
Signed-off-by: Bijan Tabatabai <bijantabatab@micron.com>
|
||||
Reviewed-by: SeongJae Park <sj@kernel.org>
|
||||
Cc: Jonathan Corbet <corbet@lwn.net>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
---
|
||||
mm/damon/ops-common.c | 150 +++++++++++++++++++++++++++++++++++++++++
|
||||
mm/damon/ops-common.h | 3 +
|
||||
mm/damon/paddr.c | 153 +-----------------------------------------
|
||||
3 files changed, 154 insertions(+), 152 deletions(-)
|
||||
|
||||
--- a/mm/damon/ops-common.c
|
||||
+++ b/mm/damon/ops-common.c
|
||||
@@ -141,6 +141,156 @@ int damon_cold_score(struct damon_ctx *c
|
||||
return DAMOS_MAX_SCORE - hotness;
|
||||
}
|
||||
|
||||
+static bool damon_folio_mkold_one(struct folio *folio,
|
||||
+ struct vm_area_struct *vma, unsigned long addr, void *arg)
|
||||
+{
|
||||
+ DEFINE_FOLIO_VMA_WALK(pvmw, folio, vma, addr, 0);
|
||||
+
|
||||
+ while (page_vma_mapped_walk(&pvmw)) {
|
||||
+ addr = pvmw.address;
|
||||
+ if (pvmw.pte)
|
||||
+ damon_ptep_mkold(pvmw.pte, vma, addr);
|
||||
+ else
|
||||
+ damon_pmdp_mkold(pvmw.pmd, vma, addr);
|
||||
+ }
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+void damon_folio_mkold(struct folio *folio)
|
||||
+{
|
||||
+ struct rmap_walk_control rwc = {
|
||||
+ .rmap_one = damon_folio_mkold_one,
|
||||
+ .anon_lock = folio_lock_anon_vma_read,
|
||||
+ };
|
||||
+ bool need_lock;
|
||||
+
|
||||
+ if (!folio_mapped(folio) || !folio_raw_mapping(folio)) {
|
||||
+ folio_set_idle(folio);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ need_lock = !folio_test_anon(folio) || folio_test_ksm(folio);
|
||||
+ if (need_lock && !folio_trylock(folio))
|
||||
+ return;
|
||||
+
|
||||
+ rmap_walk(folio, &rwc);
|
||||
+
|
||||
+ if (need_lock)
|
||||
+ folio_unlock(folio);
|
||||
+
|
||||
+}
|
||||
+
|
||||
+static bool damon_folio_young_one(struct folio *folio,
|
||||
+ struct vm_area_struct *vma, unsigned long addr, void *arg)
|
||||
+{
|
||||
+ bool *accessed = arg;
|
||||
+ DEFINE_FOLIO_VMA_WALK(pvmw, folio, vma, addr, 0);
|
||||
+ pte_t pte;
|
||||
+
|
||||
+ *accessed = false;
|
||||
+ while (page_vma_mapped_walk(&pvmw)) {
|
||||
+ addr = pvmw.address;
|
||||
+ if (pvmw.pte) {
|
||||
+ pte = ptep_get(pvmw.pte);
|
||||
+
|
||||
+ /*
|
||||
+ * PFN swap PTEs, such as device-exclusive ones, that
|
||||
+ * actually map pages are "old" from a CPU perspective.
|
||||
+ * The MMU notifier takes care of any device aspects.
|
||||
+ */
|
||||
+ *accessed = (pte_present(pte) && pte_young(pte)) ||
|
||||
+ !folio_test_idle(folio) ||
|
||||
+ mmu_notifier_test_young(vma->vm_mm, addr);
|
||||
+ } else {
|
||||
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
+ *accessed = pmd_young(pmdp_get(pvmw.pmd)) ||
|
||||
+ !folio_test_idle(folio) ||
|
||||
+ mmu_notifier_test_young(vma->vm_mm, addr);
|
||||
+#else
|
||||
+ WARN_ON_ONCE(1);
|
||||
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
|
||||
+ }
|
||||
+ if (*accessed) {
|
||||
+ page_vma_mapped_walk_done(&pvmw);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* If accessed, stop walking */
|
||||
+ return *accessed == false;
|
||||
+}
|
||||
+
|
||||
+bool damon_folio_young(struct folio *folio)
|
||||
+{
|
||||
+ bool accessed = false;
|
||||
+ struct rmap_walk_control rwc = {
|
||||
+ .arg = &accessed,
|
||||
+ .rmap_one = damon_folio_young_one,
|
||||
+ .anon_lock = folio_lock_anon_vma_read,
|
||||
+ };
|
||||
+ bool need_lock;
|
||||
+
|
||||
+ if (!folio_mapped(folio) || !folio_raw_mapping(folio)) {
|
||||
+ if (folio_test_idle(folio))
|
||||
+ return false;
|
||||
+ else
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ need_lock = !folio_test_anon(folio) || folio_test_ksm(folio);
|
||||
+ if (need_lock && !folio_trylock(folio))
|
||||
+ return false;
|
||||
+
|
||||
+ rmap_walk(folio, &rwc);
|
||||
+
|
||||
+ if (need_lock)
|
||||
+ folio_unlock(folio);
|
||||
+
|
||||
+ return accessed;
|
||||
+}
|
||||
+
|
||||
+bool damos_folio_filter_match(struct damos_filter *filter, struct folio *folio)
|
||||
+{
|
||||
+ bool matched = false;
|
||||
+ struct mem_cgroup *memcg;
|
||||
+ size_t folio_sz;
|
||||
+
|
||||
+ switch (filter->type) {
|
||||
+ case DAMOS_FILTER_TYPE_ANON:
|
||||
+ matched = folio_test_anon(folio);
|
||||
+ break;
|
||||
+ case DAMOS_FILTER_TYPE_ACTIVE:
|
||||
+ matched = folio_test_active(folio);
|
||||
+ break;
|
||||
+ case DAMOS_FILTER_TYPE_MEMCG:
|
||||
+ rcu_read_lock();
|
||||
+ memcg = folio_memcg_check(folio);
|
||||
+ if (!memcg)
|
||||
+ matched = false;
|
||||
+ else
|
||||
+ matched = filter->memcg_id == mem_cgroup_id(memcg);
|
||||
+ rcu_read_unlock();
|
||||
+ break;
|
||||
+ case DAMOS_FILTER_TYPE_YOUNG:
|
||||
+ matched = damon_folio_young(folio);
|
||||
+ if (matched)
|
||||
+ damon_folio_mkold(folio);
|
||||
+ break;
|
||||
+ case DAMOS_FILTER_TYPE_HUGEPAGE_SIZE:
|
||||
+ folio_sz = folio_size(folio);
|
||||
+ matched = filter->sz_range.min <= folio_sz &&
|
||||
+ folio_sz <= filter->sz_range.max;
|
||||
+ break;
|
||||
+ case DAMOS_FILTER_TYPE_UNMAPPED:
|
||||
+ matched = !folio_mapped(folio) || !folio_raw_mapping(folio);
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return matched == filter->matching;
|
||||
+}
|
||||
+
|
||||
static unsigned int __damon_migrate_folio_list(
|
||||
struct list_head *migrate_folios, struct pglist_data *pgdat,
|
||||
int target_nid)
|
||||
--- a/mm/damon/ops-common.h
|
||||
+++ b/mm/damon/ops-common.h
|
||||
@@ -11,10 +11,13 @@ struct folio *damon_get_folio(unsigned l
|
||||
|
||||
void damon_ptep_mkold(pte_t *pte, struct vm_area_struct *vma, unsigned long addr);
|
||||
void damon_pmdp_mkold(pmd_t *pmd, struct vm_area_struct *vma, unsigned long addr);
|
||||
+void damon_folio_mkold(struct folio *folio);
|
||||
+bool damon_folio_young(struct folio *folio);
|
||||
|
||||
int damon_cold_score(struct damon_ctx *c, struct damon_region *r,
|
||||
struct damos *s);
|
||||
int damon_hot_score(struct damon_ctx *c, struct damon_region *r,
|
||||
struct damos *s);
|
||||
|
||||
+bool damos_folio_filter_match(struct damos_filter *filter, struct folio *folio);
|
||||
unsigned long damon_migrate_pages(struct list_head *folio_list, int target_nid);
|
||||
--- a/mm/damon/paddr.c
|
||||
+++ b/mm/damon/paddr.c
|
||||
@@ -18,45 +18,6 @@
|
||||
#include "../internal.h"
|
||||
#include "ops-common.h"
|
||||
|
||||
-static bool damon_folio_mkold_one(struct folio *folio,
|
||||
- struct vm_area_struct *vma, unsigned long addr, void *arg)
|
||||
-{
|
||||
- DEFINE_FOLIO_VMA_WALK(pvmw, folio, vma, addr, 0);
|
||||
-
|
||||
- while (page_vma_mapped_walk(&pvmw)) {
|
||||
- addr = pvmw.address;
|
||||
- if (pvmw.pte)
|
||||
- damon_ptep_mkold(pvmw.pte, vma, addr);
|
||||
- else
|
||||
- damon_pmdp_mkold(pvmw.pmd, vma, addr);
|
||||
- }
|
||||
- return true;
|
||||
-}
|
||||
-
|
||||
-static void damon_folio_mkold(struct folio *folio)
|
||||
-{
|
||||
- struct rmap_walk_control rwc = {
|
||||
- .rmap_one = damon_folio_mkold_one,
|
||||
- .anon_lock = folio_lock_anon_vma_read,
|
||||
- };
|
||||
- bool need_lock;
|
||||
-
|
||||
- if (!folio_mapped(folio) || !folio_raw_mapping(folio)) {
|
||||
- folio_set_idle(folio);
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- need_lock = !folio_test_anon(folio) || folio_test_ksm(folio);
|
||||
- if (need_lock && !folio_trylock(folio))
|
||||
- return;
|
||||
-
|
||||
- rmap_walk(folio, &rwc);
|
||||
-
|
||||
- if (need_lock)
|
||||
- folio_unlock(folio);
|
||||
-
|
||||
-}
|
||||
-
|
||||
static void damon_pa_mkold(unsigned long paddr)
|
||||
{
|
||||
struct folio *folio = damon_get_folio(PHYS_PFN(paddr));
|
||||
@@ -86,75 +47,6 @@ static void damon_pa_prepare_access_chec
|
||||
}
|
||||
}
|
||||
|
||||
-static bool damon_folio_young_one(struct folio *folio,
|
||||
- struct vm_area_struct *vma, unsigned long addr, void *arg)
|
||||
-{
|
||||
- bool *accessed = arg;
|
||||
- DEFINE_FOLIO_VMA_WALK(pvmw, folio, vma, addr, 0);
|
||||
- pte_t pte;
|
||||
-
|
||||
- *accessed = false;
|
||||
- while (page_vma_mapped_walk(&pvmw)) {
|
||||
- addr = pvmw.address;
|
||||
- if (pvmw.pte) {
|
||||
- pte = ptep_get(pvmw.pte);
|
||||
-
|
||||
- /*
|
||||
- * PFN swap PTEs, such as device-exclusive ones, that
|
||||
- * actually map pages are "old" from a CPU perspective.
|
||||
- * The MMU notifier takes care of any device aspects.
|
||||
- */
|
||||
- *accessed = (pte_present(pte) && pte_young(pte)) ||
|
||||
- !folio_test_idle(folio) ||
|
||||
- mmu_notifier_test_young(vma->vm_mm, addr);
|
||||
- } else {
|
||||
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
- *accessed = pmd_young(pmdp_get(pvmw.pmd)) ||
|
||||
- !folio_test_idle(folio) ||
|
||||
- mmu_notifier_test_young(vma->vm_mm, addr);
|
||||
-#else
|
||||
- WARN_ON_ONCE(1);
|
||||
-#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
|
||||
- }
|
||||
- if (*accessed) {
|
||||
- page_vma_mapped_walk_done(&pvmw);
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- /* If accessed, stop walking */
|
||||
- return *accessed == false;
|
||||
-}
|
||||
-
|
||||
-static bool damon_folio_young(struct folio *folio)
|
||||
-{
|
||||
- bool accessed = false;
|
||||
- struct rmap_walk_control rwc = {
|
||||
- .arg = &accessed,
|
||||
- .rmap_one = damon_folio_young_one,
|
||||
- .anon_lock = folio_lock_anon_vma_read,
|
||||
- };
|
||||
- bool need_lock;
|
||||
-
|
||||
- if (!folio_mapped(folio) || !folio_raw_mapping(folio)) {
|
||||
- if (folio_test_idle(folio))
|
||||
- return false;
|
||||
- else
|
||||
- return true;
|
||||
- }
|
||||
-
|
||||
- need_lock = !folio_test_anon(folio) || folio_test_ksm(folio);
|
||||
- if (need_lock && !folio_trylock(folio))
|
||||
- return false;
|
||||
-
|
||||
- rmap_walk(folio, &rwc);
|
||||
-
|
||||
- if (need_lock)
|
||||
- folio_unlock(folio);
|
||||
-
|
||||
- return accessed;
|
||||
-}
|
||||
-
|
||||
static bool damon_pa_young(unsigned long paddr, unsigned long *folio_sz)
|
||||
{
|
||||
struct folio *folio = damon_get_folio(PHYS_PFN(paddr));
|
||||
@@ -205,49 +97,6 @@ static unsigned int damon_pa_check_acces
|
||||
return max_nr_accesses;
|
||||
}
|
||||
|
||||
-static bool damos_pa_filter_match(struct damos_filter *filter,
|
||||
- struct folio *folio)
|
||||
-{
|
||||
- bool matched = false;
|
||||
- struct mem_cgroup *memcg;
|
||||
- size_t folio_sz;
|
||||
-
|
||||
- switch (filter->type) {
|
||||
- case DAMOS_FILTER_TYPE_ANON:
|
||||
- matched = folio_test_anon(folio);
|
||||
- break;
|
||||
- case DAMOS_FILTER_TYPE_ACTIVE:
|
||||
- matched = folio_test_active(folio);
|
||||
- break;
|
||||
- case DAMOS_FILTER_TYPE_MEMCG:
|
||||
- rcu_read_lock();
|
||||
- memcg = folio_memcg_check(folio);
|
||||
- if (!memcg)
|
||||
- matched = false;
|
||||
- else
|
||||
- matched = filter->memcg_id == mem_cgroup_id(memcg);
|
||||
- rcu_read_unlock();
|
||||
- break;
|
||||
- case DAMOS_FILTER_TYPE_YOUNG:
|
||||
- matched = damon_folio_young(folio);
|
||||
- if (matched)
|
||||
- damon_folio_mkold(folio);
|
||||
- break;
|
||||
- case DAMOS_FILTER_TYPE_HUGEPAGE_SIZE:
|
||||
- folio_sz = folio_size(folio);
|
||||
- matched = filter->sz_range.min <= folio_sz &&
|
||||
- folio_sz <= filter->sz_range.max;
|
||||
- break;
|
||||
- case DAMOS_FILTER_TYPE_UNMAPPED:
|
||||
- matched = !folio_mapped(folio) || !folio_raw_mapping(folio);
|
||||
- break;
|
||||
- default:
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- return matched == filter->matching;
|
||||
-}
|
||||
-
|
||||
/*
|
||||
* damos_pa_filter_out - Return true if the page should be filtered out.
|
||||
*/
|
||||
@@ -259,7 +108,7 @@ static bool damos_pa_filter_out(struct d
|
||||
return false;
|
||||
|
||||
damos_for_each_ops_filter(filter, scheme) {
|
||||
- if (damos_pa_filter_match(filter, folio))
|
||||
+ if (damos_folio_filter_match(filter, folio))
|
||||
return !filter->allow;
|
||||
}
|
||||
return scheme->ops_filters_default_reject;
|
@@ -0,0 +1,58 @@
|
||||
From 28ceaa34f71077b305a2fae3abf9e8af606fbae7 Mon Sep 17 00:00:00 2001
|
||||
From: SeongJae Park <sj@kernel.org>
|
||||
Date: Sun, 20 Jul 2025 11:58:22 -0700
|
||||
Subject: mm/damon/ops-common: ignore migration request to invalid nodes
|
||||
|
||||
damon_migrate_pages() tries migration even if the target node is invalid.
|
||||
If users mistakenly make such invalid requests via
|
||||
DAMOS_MIGRATE_{HOT,COLD} action, the below kernel BUG can happen.
|
||||
|
||||
[ 7831.883495] BUG: unable to handle page fault for address: 0000000000001f48
|
||||
[ 7831.884160] #PF: supervisor read access in kernel mode
|
||||
[ 7831.884681] #PF: error_code(0x0000) - not-present page
|
||||
[ 7831.885203] PGD 0 P4D 0
|
||||
[ 7831.885468] Oops: Oops: 0000 [#1] SMP PTI
|
||||
[ 7831.885852] CPU: 31 UID: 0 PID: 94202 Comm: kdamond.0 Not tainted 6.16.0-rc5-mm-new-damon+ #93 PREEMPT(voluntary)
|
||||
[ 7831.886913] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-4.el9 04/01/2014
|
||||
[ 7831.887777] RIP: 0010:__alloc_frozen_pages_noprof (include/linux/mmzone.h:1724 include/linux/mmzone.h:1750 mm/page_alloc.c:4936 mm/page_alloc.c:5137)
|
||||
[...]
|
||||
[ 7831.895953] Call Trace:
|
||||
[ 7831.896195] <TASK>
|
||||
[ 7831.896397] __folio_alloc_noprof (mm/page_alloc.c:5183 mm/page_alloc.c:5192)
|
||||
[ 7831.896787] migrate_pages_batch (mm/migrate.c:1189 mm/migrate.c:1851)
|
||||
[ 7831.897228] ? __pfx_alloc_migration_target (mm/migrate.c:2137)
|
||||
[ 7831.897735] migrate_pages (mm/migrate.c:2078)
|
||||
[ 7831.898141] ? __pfx_alloc_migration_target (mm/migrate.c:2137)
|
||||
[ 7831.898664] damon_migrate_folio_list (mm/damon/ops-common.c:321 mm/damon/ops-common.c:354)
|
||||
[ 7831.899140] damon_migrate_pages (mm/damon/ops-common.c:405)
|
||||
[...]
|
||||
|
||||
Add a target node validity check in damon_migrate_pages(). The validity
|
||||
check is stolen from that of do_pages_move(), which is being used for the
|
||||
move_pages() system call.
|
||||
|
||||
Link: https://lkml.kernel.org/r/20250720185822.1451-1-sj@kernel.org
|
||||
Fixes: b51820ebea65 ("mm/damon/paddr: introduce DAMOS_MIGRATE_COLD action for demotion") [6.11.x]
|
||||
Signed-off-by: SeongJae Park <sj@kernel.org>
|
||||
Reviewed-by: Joshua Hahn <joshua.hahnjy@gmail.com>
|
||||
Cc: Honggyu Kim <honggyu.kim@sk.com>
|
||||
Cc: Hyeongtak Ji <hyeongtak.ji@sk.com>
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
---
|
||||
mm/damon/ops-common.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
--- a/mm/damon/ops-common.c
|
||||
+++ b/mm/damon/ops-common.c
|
||||
@@ -383,6 +383,10 @@ unsigned long damon_migrate_pages(struct
|
||||
if (list_empty(folio_list))
|
||||
return nr_migrated;
|
||||
|
||||
+ if (target_nid < 0 || target_nid >= MAX_NUMNODES ||
|
||||
+ !node_state(target_nid, N_MEMORY))
|
||||
+ return nr_migrated;
|
||||
+
|
||||
noreclaim_flag = memalloc_noreclaim_save();
|
||||
|
||||
nid = folio_nid(lru_to_folio(folio_list));
|
@@ -0,0 +1,28 @@
|
||||
From 20235e70d4e5f0f66e0b037e9e02ca7ec0cf97a5 Mon Sep 17 00:00:00 2001
|
||||
From: Johan Hovold <johan@kernel.org>
|
||||
Date: Thu, 24 Jul 2025 11:19:08 +0200
|
||||
Subject: usb: gadget: udc: renesas_usb3: fix device leak at unbind
|
||||
|
||||
Make sure to drop the reference to the companion device taken during
|
||||
probe when the driver is unbound.
|
||||
|
||||
Fixes: 39facfa01c9f ("usb: gadget: udc: renesas_usb3: Add register of usb role switch")
|
||||
Cc: stable@vger.kernel.org # 4.19
|
||||
Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
|
||||
Signed-off-by: Johan Hovold <johan@kernel.org>
|
||||
Link: https://lore.kernel.org/r/20250724091910.21092-4-johan@kernel.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/usb/gadget/udc/renesas_usb3.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/drivers/usb/gadget/udc/renesas_usb3.c
|
||||
+++ b/drivers/usb/gadget/udc/renesas_usb3.c
|
||||
@@ -2657,6 +2657,7 @@ static void renesas_usb3_remove(struct p
|
||||
struct renesas_usb3 *usb3 = platform_get_drvdata(pdev);
|
||||
|
||||
debugfs_remove_recursive(usb3->dentry);
|
||||
+ put_device(usb3->host_dev);
|
||||
device_remove_file(&pdev->dev, &dev_attr_role);
|
||||
|
||||
cancel_work_sync(&usb3->role_work);
|
@@ -0,0 +1,36 @@
|
||||
From b958aba8ee0d90742627dd46324cd29fd3e3abce Mon Sep 17 00:00:00 2001
|
||||
From: Lukas Wunner <lukas@wunner.de>
|
||||
Date: Sun, 13 Jul 2025 16:31:02 +0200
|
||||
Subject: PCI/portdrv: Use is_pciehp instead of is_hotplug_bridge
|
||||
|
||||
The PCIe port driver erroneously creates a subdevice for hotplug on ACPI
|
||||
slots which are handled by the ACPI hotplug driver.
|
||||
|
||||
Avoid by checking the is_pciehp flag instead of is_hotplug_bridge when
|
||||
deciding whether to create a subdevice. The latter encompasses ACPI slots
|
||||
whereas the former doesn't.
|
||||
|
||||
The superfluous subdevice has no real negative impact, it occupies memory
|
||||
and interrupt resources but otherwise just sits there waiting for
|
||||
interrupts from the slot that are never signaled.
|
||||
|
||||
Fixes: f8415222837b ("PCI: Use cached copy of PCI_EXP_SLTCAP_HPC bit")
|
||||
Signed-off-by: Lukas Wunner <lukas@wunner.de>
|
||||
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
|
||||
Cc: stable@vger.kernel.org # v4.7+
|
||||
Link: https://patch.msgid.link/40d5a5fe8d40595d505949c620a067fa110ee85e.1752390102.git.lukas@wunner.de
|
||||
---
|
||||
drivers/pci/pcie/portdrv.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/pci/pcie/portdrv.c
|
||||
+++ b/drivers/pci/pcie/portdrv.c
|
||||
@@ -220,7 +220,7 @@ static int get_port_device_capability(st
|
||||
struct pci_host_bridge *host = pci_find_host_bridge(dev->bus);
|
||||
int services = 0;
|
||||
|
||||
- if (dev->is_hotplug_bridge &&
|
||||
+ if (dev->is_pciehp &&
|
||||
(pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT ||
|
||||
pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) &&
|
||||
(pcie_ports_native || host->native_pcie_hotplug)) {
|
@@ -0,0 +1,85 @@
|
||||
From eb5df6a83646eb2ecd7eda995b5632031acf94b3 Mon Sep 17 00:00:00 2001
|
||||
From: Damien Le Moal <dlemoal@kernel.org>
|
||||
Date: Tue, 29 Jul 2025 18:28:07 +0900
|
||||
Subject: ata: libata-scsi: Fix ata_to_sense_error() status handling
|
||||
|
||||
Commit 8ae720449fca ("libata: whitespace fixes in ata_to_sense_error()")
|
||||
inadvertantly added the entry 0x40 (ATA_DRDY) to the stat_table array in
|
||||
the function ata_to_sense_error(). This entry ties a failed qc which has
|
||||
a status filed equal to ATA_DRDY to the sense key ILLEGAL REQUEST with
|
||||
the additional sense code UNALIGNED WRITE COMMAND. This entry will be
|
||||
used to generate a failed qc sense key and sense code when the qc is
|
||||
missing sense data and there is no match for the qc error field in the
|
||||
sense_table array of ata_to_sense_error().
|
||||
|
||||
As a result, for a failed qc for which we failed to get sense data (e.g.
|
||||
read log 10h failed if qc is an NCQ command, or REQUEST SENSE EXT
|
||||
command failed for the non-ncq case, the user very often end up seeing
|
||||
the completely misleading "unaligned write command" error, even if qc
|
||||
was not a write command. E.g.:
|
||||
|
||||
sd 0:0:0:0: [sda] tag#12 FAILED Result: hostbyte=DID_OK driverbyte=DRIVER_OK cmd_age=0s
|
||||
sd 0:0:0:0: [sda] tag#12 Sense Key : Illegal Request [current]
|
||||
sd 0:0:0:0: [sda] tag#12 Add. Sense: Unaligned write command
|
||||
sd 0:0:0:0: [sda] tag#12 CDB: Read(10) 28 00 00 00 10 00 00 00 08 00
|
||||
I/O error, dev sda, sector 4096 op 0x0:(READ) flags 0x80700 phys_seg 1 prio class 0
|
||||
|
||||
Fix this by removing the ATA_DRDY entry from the stat_table array so
|
||||
that we default to always returning ABORTED COMMAND without any
|
||||
additional sense code, since we do not know any better. The entry 0x08
|
||||
(ATA_DRQ) is also removed since signaling ABORTED COMMAND with a parity
|
||||
error is also misleading (as a parity error would likely be signaled
|
||||
through a bus error). So for this case, also default to returning
|
||||
ABORTED COMMAND without any additional sense code. With this, the
|
||||
previous example error case becomes:
|
||||
|
||||
sd 0:0:0:0: [sda] tag#17 FAILED Result: hostbyte=DID_OK driverbyte=DRIVER_OK cmd_age=0s
|
||||
sd 0:0:0:0: [sda] tag#17 Sense Key : Aborted Command [current]
|
||||
sd 0:0:0:0: [sda] tag#17 Add. Sense: No additional sense information
|
||||
sd 0:0:0:0: [sda] tag#17 CDB: Read(10) 28 00 00 00 10 00 00 00 08 00
|
||||
I/O error, dev sda, sector 4096 op 0x0:(READ) flags 0x80700 phys_seg 1 prio class 0
|
||||
|
||||
Together with these fixes, refactor stat_table to make it more readable
|
||||
by putting the entries comments in front of the entries and using the
|
||||
defined status bits macros instead of hardcoded values.
|
||||
|
||||
Reported-by: Lorenz Brun <lorenz@brun.one>
|
||||
Reported-by: Brandon Schwartz <Brandon.Schwartz@wdc.com>
|
||||
Fixes: 8ae720449fca ("libata: whitespace fixes in ata_to_sense_error()")
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
|
||||
Reviewed-by: Hannes Reinecke <hare@suse.de>
|
||||
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
|
||||
---
|
||||
drivers/ata/libata-scsi.c | 20 ++++++++------------
|
||||
1 file changed, 8 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/drivers/ata/libata-scsi.c
|
||||
+++ b/drivers/ata/libata-scsi.c
|
||||
@@ -859,18 +859,14 @@ static void ata_to_sense_error(u8 drv_st
|
||||
{0xFF, 0xFF, 0xFF, 0xFF}, // END mark
|
||||
};
|
||||
static const unsigned char stat_table[][4] = {
|
||||
- /* Must be first because BUSY means no other bits valid */
|
||||
- {0x80, ABORTED_COMMAND, 0x47, 0x00},
|
||||
- // Busy, fake parity for now
|
||||
- {0x40, ILLEGAL_REQUEST, 0x21, 0x04},
|
||||
- // Device ready, unaligned write command
|
||||
- {0x20, HARDWARE_ERROR, 0x44, 0x00},
|
||||
- // Device fault, internal target failure
|
||||
- {0x08, ABORTED_COMMAND, 0x47, 0x00},
|
||||
- // Timed out in xfer, fake parity for now
|
||||
- {0x04, RECOVERED_ERROR, 0x11, 0x00},
|
||||
- // Recovered ECC error Medium error, recovered
|
||||
- {0xFF, 0xFF, 0xFF, 0xFF}, // END mark
|
||||
+ /* Busy: must be first because BUSY means no other bits valid */
|
||||
+ { ATA_BUSY, ABORTED_COMMAND, 0x00, 0x00 },
|
||||
+ /* Device fault: INTERNAL TARGET FAILURE */
|
||||
+ { ATA_DF, HARDWARE_ERROR, 0x44, 0x00 },
|
||||
+ /* Corrected data error */
|
||||
+ { ATA_CORR, RECOVERED_ERROR, 0x00, 0x00 },
|
||||
+
|
||||
+ { 0xFF, 0xFF, 0xFF, 0xFF }, /* END mark */
|
||||
};
|
||||
|
||||
/*
|
@@ -0,0 +1,69 @@
|
||||
From 222f2d776f617895a876ccd7047cbebc82175f38 Mon Sep 17 00:00:00 2001
|
||||
From: Damien Le Moal <dlemoal@kernel.org>
|
||||
Date: Tue, 29 Jul 2025 19:37:12 +0900
|
||||
Subject: ata: libata-scsi: Return aborted command when missing sense and
|
||||
result TF
|
||||
|
||||
ata_gen_ata_sense() is always called for a failed qc missing sense data
|
||||
so that a sense key, code and code qualifier can be generated using
|
||||
ata_to_sense_error() from the qc status and error fields of its result
|
||||
task file. However, if the qc does not have its result task file filled,
|
||||
ata_gen_ata_sense() returns early without setting a sense key.
|
||||
|
||||
Improve this by defaulting to returning ABORTED COMMAND without any
|
||||
additional sense code, since we do not know the reason for the failure.
|
||||
The same fix is also applied in ata_gen_passthru_sense() with the
|
||||
additional check that the qc failed (qc->err_mask is set).
|
||||
|
||||
Fixes: 816be86c7993 ("ata: libata-scsi: Check ATA_QCFLAG_RTF_FILLED before using result_tf")
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
|
||||
Reviewed-by: Hannes Reinecke <hare@suse.de>
|
||||
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
|
||||
---
|
||||
drivers/ata/libata-scsi.c | 18 +++++++++++-------
|
||||
1 file changed, 11 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/drivers/ata/libata-scsi.c
|
||||
+++ b/drivers/ata/libata-scsi.c
|
||||
@@ -938,6 +938,8 @@ static void ata_gen_passthru_sense(struc
|
||||
if (!(qc->flags & ATA_QCFLAG_RTF_FILLED)) {
|
||||
ata_dev_dbg(dev,
|
||||
"missing result TF: can't generate ATA PT sense data\n");
|
||||
+ if (qc->err_mask)
|
||||
+ ata_scsi_set_sense(dev, cmd, ABORTED_COMMAND, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -992,8 +994,8 @@ static void ata_gen_ata_sense(struct ata
|
||||
|
||||
if (!(qc->flags & ATA_QCFLAG_RTF_FILLED)) {
|
||||
ata_dev_dbg(dev,
|
||||
- "missing result TF: can't generate sense data\n");
|
||||
- return;
|
||||
+ "Missing result TF: reporting aborted command\n");
|
||||
+ goto aborted;
|
||||
}
|
||||
|
||||
/* Use ata_to_sense_error() to map status register bits
|
||||
@@ -1004,13 +1006,15 @@ static void ata_gen_ata_sense(struct ata
|
||||
ata_to_sense_error(tf->status, tf->error,
|
||||
&sense_key, &asc, &ascq);
|
||||
ata_scsi_set_sense(dev, cmd, sense_key, asc, ascq);
|
||||
- } else {
|
||||
- /* Could not decode error */
|
||||
- ata_dev_warn(dev, "could not decode error status 0x%x err_mask 0x%x\n",
|
||||
- tf->status, qc->err_mask);
|
||||
- ata_scsi_set_sense(dev, cmd, ABORTED_COMMAND, 0, 0);
|
||||
return;
|
||||
}
|
||||
+
|
||||
+ /* Could not decode error */
|
||||
+ ata_dev_warn(dev,
|
||||
+ "Could not decode error 0x%x, status 0x%x (err_mask=0x%x)\n",
|
||||
+ tf->error, tf->status, qc->err_mask);
|
||||
+aborted:
|
||||
+ ata_scsi_set_sense(dev, cmd, ABORTED_COMMAND, 0, 0);
|
||||
}
|
||||
|
||||
void ata_scsi_sdev_config(struct scsi_device *sdev)
|
48
debian/patches/patchset-pf/steady/0027-vhost-vsock-Avoid-allocating-arbitrarily-sized-SKBs.patch
vendored
Normal file
48
debian/patches/patchset-pf/steady/0027-vhost-vsock-Avoid-allocating-arbitrarily-sized-SKBs.patch
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
From 1696616a3e6e9d5eef2c39723ddaafb78a9a6eeb Mon Sep 17 00:00:00 2001
|
||||
From: Will Deacon <will@kernel.org>
|
||||
Date: Thu, 17 Jul 2025 10:01:08 +0100
|
||||
Subject: vhost/vsock: Avoid allocating arbitrarily-sized SKBs
|
||||
|
||||
vhost_vsock_alloc_skb() returns NULL for packets advertising a length
|
||||
larger than VIRTIO_VSOCK_MAX_PKT_BUF_SIZE in the packet header. However,
|
||||
this is only checked once the SKB has been allocated and, if the length
|
||||
in the packet header is zero, the SKB may not be freed immediately.
|
||||
|
||||
Hoist the size check before the SKB allocation so that an iovec larger
|
||||
than VIRTIO_VSOCK_MAX_PKT_BUF_SIZE + the header size is rejected
|
||||
outright. The subsequent check on the length field in the header can
|
||||
then simply check that the allocated SKB is indeed large enough to hold
|
||||
the packet.
|
||||
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Fixes: 71dc9ec9ac7d ("virtio/vsock: replace virtio_vsock_pkt with sk_buff")
|
||||
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
|
||||
Signed-off-by: Will Deacon <will@kernel.org>
|
||||
Message-Id: <20250717090116.11987-2-will@kernel.org>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
---
|
||||
drivers/vhost/vsock.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/vhost/vsock.c
|
||||
+++ b/drivers/vhost/vsock.c
|
||||
@@ -344,6 +344,9 @@ vhost_vsock_alloc_skb(struct vhost_virtq
|
||||
|
||||
len = iov_length(vq->iov, out);
|
||||
|
||||
+ if (len > VIRTIO_VSOCK_MAX_PKT_BUF_SIZE + VIRTIO_VSOCK_SKB_HEADROOM)
|
||||
+ return NULL;
|
||||
+
|
||||
/* len contains both payload and hdr */
|
||||
skb = virtio_vsock_alloc_skb(len, GFP_KERNEL);
|
||||
if (!skb)
|
||||
@@ -367,8 +370,7 @@ vhost_vsock_alloc_skb(struct vhost_virtq
|
||||
return skb;
|
||||
|
||||
/* The pkt is too big or the length in the header is invalid */
|
||||
- if (payload_len > VIRTIO_VSOCK_MAX_PKT_BUF_SIZE ||
|
||||
- payload_len + sizeof(*hdr) > len) {
|
||||
+ if (payload_len + sizeof(*hdr) > len) {
|
||||
kfree_skb(skb);
|
||||
return NULL;
|
||||
}
|
@@ -0,0 +1,57 @@
|
||||
From cfb5ffceff501d3ffe6529706d65a35e6068b638 Mon Sep 17 00:00:00 2001
|
||||
From: Will Deacon <will@kernel.org>
|
||||
Date: Thu, 17 Jul 2025 10:01:09 +0100
|
||||
Subject: vsock/virtio: Validate length in packet header before skb_put()
|
||||
|
||||
When receiving a vsock packet in the guest, only the virtqueue buffer
|
||||
size is validated prior to virtio_vsock_skb_rx_put(). Unfortunately,
|
||||
virtio_vsock_skb_rx_put() uses the length from the packet header as the
|
||||
length argument to skb_put(), potentially resulting in SKB overflow if
|
||||
the host has gone wonky.
|
||||
|
||||
Validate the length as advertised by the packet header before calling
|
||||
virtio_vsock_skb_rx_put().
|
||||
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Fixes: 71dc9ec9ac7d ("virtio/vsock: replace virtio_vsock_pkt with sk_buff")
|
||||
Signed-off-by: Will Deacon <will@kernel.org>
|
||||
Message-Id: <20250717090116.11987-3-will@kernel.org>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
|
||||
---
|
||||
net/vmw_vsock/virtio_transport.c | 12 ++++++++++--
|
||||
1 file changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/net/vmw_vsock/virtio_transport.c
|
||||
+++ b/net/vmw_vsock/virtio_transport.c
|
||||
@@ -624,8 +624,9 @@ static void virtio_transport_rx_work(str
|
||||
do {
|
||||
virtqueue_disable_cb(vq);
|
||||
for (;;) {
|
||||
+ unsigned int len, payload_len;
|
||||
+ struct virtio_vsock_hdr *hdr;
|
||||
struct sk_buff *skb;
|
||||
- unsigned int len;
|
||||
|
||||
if (!virtio_transport_more_replies(vsock)) {
|
||||
/* Stop rx until the device processes already
|
||||
@@ -642,11 +643,18 @@ static void virtio_transport_rx_work(str
|
||||
vsock->rx_buf_nr--;
|
||||
|
||||
/* Drop short/long packets */
|
||||
- if (unlikely(len < sizeof(struct virtio_vsock_hdr) ||
|
||||
+ if (unlikely(len < sizeof(*hdr) ||
|
||||
len > virtio_vsock_skb_len(skb))) {
|
||||
kfree_skb(skb);
|
||||
continue;
|
||||
}
|
||||
+
|
||||
+ hdr = virtio_vsock_hdr(skb);
|
||||
+ payload_len = le32_to_cpu(hdr->len);
|
||||
+ if (unlikely(payload_len > len - sizeof(*hdr))) {
|
||||
+ kfree_skb(skb);
|
||||
+ continue;
|
||||
+ }
|
||||
|
||||
virtio_vsock_skb_rx_put(skb);
|
||||
virtio_transport_deliver_tap_pkt(skb);
|
105
debian/patches/patchset-pf/steady/0029-fs-proc-task_mmu-remove-conversion-of-seq_file-posit.patch
vendored
Normal file
105
debian/patches/patchset-pf/steady/0029-fs-proc-task_mmu-remove-conversion-of-seq_file-posit.patch
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
From b7e9e555a80801d33d94287307e7b7606501cffb Mon Sep 17 00:00:00 2001
|
||||
From: Suren Baghdasaryan <surenb@google.com>
|
||||
Date: Sat, 19 Jul 2025 11:28:53 -0700
|
||||
Subject: fs/proc/task_mmu: remove conversion of seq_file position to unsigned
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Back in 2.6 era, last_addr used to be stored in seq_file->version
|
||||
variable, which was unsigned long. As a result, sentinels to represent
|
||||
gate vma and end of all vmas used unsigned values. In more recent kernels
|
||||
we don't used seq_file->version anymore and therefore conversion from
|
||||
loff_t into unsigned type is not needed. Similarly, sentinel values don't
|
||||
need to be unsigned. Remove type conversion for set_file position and
|
||||
change sentinel values to signed. While at it, change the hardcoded
|
||||
sentinel values with named definitions for better documentation.
|
||||
|
||||
Link: https://lkml.kernel.org/r/20250719182854.3166724-6-surenb@google.com
|
||||
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
|
||||
Reviewed-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
|
||||
Reviewed-by: Vlastimil Babka <vbabka@suse.cz>
|
||||
Acked-by: David Hildenbrand <david@redhat.com>
|
||||
Cc: Alexey Dobriyan <adobriyan@gmail.com>
|
||||
Cc: Andrii Nakryiko <andrii@kernel.org>
|
||||
Cc: Christian Brauner <brauner@kernel.org>
|
||||
Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
|
||||
Cc: Jann Horn <jannh@google.com>
|
||||
Cc: Jeongjun Park <aha310510@gmail.com>
|
||||
Cc: Johannes Weiner <hannes@cmpxchg.org>
|
||||
Cc: Josef Bacik <josef@toxicpanda.com>
|
||||
Cc: Kalesh Singh <kaleshsingh@google.com>
|
||||
Cc: Liam Howlett <liam.howlett@oracle.com>
|
||||
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
|
||||
Cc: Michal Hocko <mhocko@kernel.org>
|
||||
Cc: Oscar Salvador <osalvador@suse.de>
|
||||
Cc: "Paul E . McKenney" <paulmck@kernel.org>
|
||||
Cc: Peter Xu <peterx@redhat.com>
|
||||
Cc: Ryan Roberts <ryan.roberts@arm.com>
|
||||
Cc: Shuah Khan <shuah@kernel.org>
|
||||
Cc: Thomas Weißschuh <linux@weissschuh.net>
|
||||
Cc: T.J. Mercier <tjmercier@google.com>
|
||||
Cc: Ye Bin <yebin10@huawei.com>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
---
|
||||
fs/proc/task_mmu.c | 17 ++++++++++-------
|
||||
1 file changed, 10 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/fs/proc/task_mmu.c
|
||||
+++ b/fs/proc/task_mmu.c
|
||||
@@ -29,6 +29,9 @@
|
||||
#include <asm/tlbflush.h>
|
||||
#include "internal.h"
|
||||
|
||||
+#define SENTINEL_VMA_END -1
|
||||
+#define SENTINEL_VMA_GATE -2
|
||||
+
|
||||
#define SEQ_PUT_DEC(str, val) \
|
||||
seq_put_decimal_ull_width(m, str, (val) << (PAGE_SHIFT-10), 8)
|
||||
void task_mem(struct seq_file *m, struct mm_struct *mm)
|
||||
@@ -135,7 +138,7 @@ static struct vm_area_struct *proc_get_v
|
||||
if (vma) {
|
||||
*ppos = vma->vm_start;
|
||||
} else {
|
||||
- *ppos = -2UL;
|
||||
+ *ppos = SENTINEL_VMA_GATE;
|
||||
vma = get_gate_vma(priv->mm);
|
||||
}
|
||||
|
||||
@@ -145,11 +148,11 @@ static struct vm_area_struct *proc_get_v
|
||||
static void *m_start(struct seq_file *m, loff_t *ppos)
|
||||
{
|
||||
struct proc_maps_private *priv = m->private;
|
||||
- unsigned long last_addr = *ppos;
|
||||
+ loff_t last_addr = *ppos;
|
||||
struct mm_struct *mm;
|
||||
|
||||
/* See m_next(). Zero at the start or after lseek. */
|
||||
- if (last_addr == -1UL)
|
||||
+ if (last_addr == SENTINEL_VMA_END)
|
||||
return NULL;
|
||||
|
||||
priv->task = get_proc_task(priv->inode);
|
||||
@@ -170,9 +173,9 @@ static void *m_start(struct seq_file *m,
|
||||
return ERR_PTR(-EINTR);
|
||||
}
|
||||
|
||||
- vma_iter_init(&priv->iter, mm, last_addr);
|
||||
+ vma_iter_init(&priv->iter, mm, (unsigned long)last_addr);
|
||||
hold_task_mempolicy(priv);
|
||||
- if (last_addr == -2UL)
|
||||
+ if (last_addr == SENTINEL_VMA_GATE)
|
||||
return get_gate_vma(mm);
|
||||
|
||||
return proc_get_vma(priv, ppos);
|
||||
@@ -180,8 +183,8 @@ static void *m_start(struct seq_file *m,
|
||||
|
||||
static void *m_next(struct seq_file *m, void *v, loff_t *ppos)
|
||||
{
|
||||
- if (*ppos == -2UL) {
|
||||
- *ppos = -1UL;
|
||||
+ if (*ppos == SENTINEL_VMA_GATE) {
|
||||
+ *ppos = SENTINEL_VMA_END;
|
||||
return NULL;
|
||||
}
|
||||
return proc_get_vma(m->private, ppos);
|
@@ -0,0 +1,36 @@
|
||||
From 49442fb626f151f886cb5a860c972c300307fdff Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= <thomas.weissschuh@linutronix.de>
|
||||
Date: Mon, 28 Jul 2025 15:47:37 +0200
|
||||
Subject: kbuild: userprogs: use correct linker when mixing clang and GNU ld
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The userprogs infrastructure does not expect clang being used with GNU ld
|
||||
and in that case uses /usr/bin/ld for linking, not the configured $(LD).
|
||||
This fallback is problematic as it will break when cross-compiling.
|
||||
Mixing clang and GNU ld is used for example when building for SPARC64,
|
||||
as ld.lld is not sufficient; see Documentation/kbuild/llvm.rst.
|
||||
|
||||
Relax the check around --ld-path so it gets used for all linkers.
|
||||
|
||||
Fixes: dfc1b168a8c4 ("kbuild: userprogs: use correct lld when linking through clang")
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
|
||||
Reviewed-by: Nathan Chancellor <nathan@kernel.org>
|
||||
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
|
||||
---
|
||||
Makefile | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -1154,7 +1154,7 @@ KBUILD_USERCFLAGS += $(filter -m32 -m64
|
||||
KBUILD_USERLDFLAGS += $(filter -m32 -m64 --target=%, $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS))
|
||||
|
||||
# userspace programs are linked via the compiler, use the correct linker
|
||||
-ifeq ($(CONFIG_CC_IS_CLANG)$(CONFIG_LD_IS_LLD),yy)
|
||||
+ifdef CONFIG_CC_IS_CLANG
|
||||
KBUILD_USERLDFLAGS += --ld-path=$(LD)
|
||||
endif
|
||||
|
@@ -0,0 +1,36 @@
|
||||
From 31a1e00a65d88e2f051fb6e9551340cc815d54d4 Mon Sep 17 00:00:00 2001
|
||||
From: Helge Deller <deller@gmx.de>
|
||||
Date: Sat, 2 Aug 2025 21:34:37 +0200
|
||||
Subject: Revert "vgacon: Add check for vc_origin address range in
|
||||
vgacon_scroll()"
|
||||
|
||||
This reverts commit 864f9963ec6b4b76d104d595ba28110b87158003.
|
||||
|
||||
The patch is wrong as it checks vc_origin against vc_screenbuf,
|
||||
while in text mode it should compare against vga_vram_base.
|
||||
|
||||
As such it broke VGA text scrolling, which can be reproduced like this:
|
||||
(1) boot a kernel that is configured to use text mode VGA-console
|
||||
(2) type commands: ls -l /usr/bin | less -S
|
||||
(3) scroll up/down with cursor-down/up keys
|
||||
|
||||
Reported-by: Jari Ruusu <jariruusu@protonmail.com>
|
||||
Cc: stable@vger.kernel.org
|
||||
Cc: Yi Yang <yiyang13@huawei.com>
|
||||
Cc: GONG Ruiqi <gongruiqi1@huawei.com>
|
||||
Signed-off-by: Helge Deller <deller@gmx.de>
|
||||
---
|
||||
drivers/video/console/vgacon.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/video/console/vgacon.c
|
||||
+++ b/drivers/video/console/vgacon.c
|
||||
@@ -1168,7 +1168,7 @@ static bool vgacon_scroll(struct vc_data
|
||||
c->vc_screenbuf_size - delta);
|
||||
c->vc_origin = vga_vram_end - c->vc_screenbuf_size;
|
||||
vga_rolled_over = 0;
|
||||
- } else if (oldo - delta >= (unsigned long)c->vc_screenbuf)
|
||||
+ } else
|
||||
c->vc_origin -= delta;
|
||||
c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
|
||||
scr_memsetw((u16 *) (c->vc_origin), c->vc_video_erase_char,
|
@@ -0,0 +1,28 @@
|
||||
From 5c50d7a4d6580d6cc83d1231aa358defe43bc46d Mon Sep 17 00:00:00 2001
|
||||
From: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
Date: Thu, 31 Jul 2025 09:41:47 +0800
|
||||
Subject: crypto: hash - Increase HASH_MAX_DESCSIZE for hmac(sha3-224-s390)
|
||||
|
||||
The value of HASH_MAX_DESCSIZE is off by one for hmac(sha3-224-s390).
|
||||
Fix this so that hmac(sha3-224-s390) can be registered.
|
||||
|
||||
Reported-by: Ingo Franzki <ifranzki@linux.ibm.com>
|
||||
Reported-by: Eric Biggers <ebiggers@kernel.org>
|
||||
Fixes: 6f90ba706551 ("crypto: s390/sha3 - Use API partial block handling")
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
include/crypto/hash.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/include/crypto/hash.h
|
||||
+++ b/include/crypto/hash.h
|
||||
@@ -184,7 +184,7 @@ struct shash_desc {
|
||||
* Worst case is hmac(sha3-224-s390). Its context is a nested 'shash_desc'
|
||||
* containing a 'struct s390_sha_ctx'.
|
||||
*/
|
||||
-#define HASH_MAX_DESCSIZE (sizeof(struct shash_desc) + 360)
|
||||
+#define HASH_MAX_DESCSIZE (sizeof(struct shash_desc) + 361)
|
||||
#define MAX_SYNC_HASH_REQSIZE (sizeof(struct ahash_request) + \
|
||||
HASH_MAX_DESCSIZE)
|
||||
|
478
debian/patches/patchset-pf/steady/0033-cifs-Add-support-for-creating-reparse-points-over-SM.patch
vendored
Normal file
478
debian/patches/patchset-pf/steady/0033-cifs-Add-support-for-creating-reparse-points-over-SM.patch
vendored
Normal file
@@ -0,0 +1,478 @@
|
||||
From 1b49e1eaff6d1d665cacad667a1fc03c38fc8533 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
|
||||
Date: Thu, 26 Dec 2024 00:43:22 +0100
|
||||
Subject: cifs: Add support for creating reparse points over SMB1
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
SMB1 already supports querying reparse points and detecting types of
|
||||
symlink, fifo, socket, block and char.
|
||||
|
||||
This change implements the missing part - ability to create a new reparse
|
||||
points over SMB1. This includes everything which SMB2+ already supports:
|
||||
- native SMB symlinks and sockets
|
||||
- NFS style of special files (symlinks, fifos, sockets, char/block devs)
|
||||
- WSL style of special files (symlinks, fifos, sockets, char/block devs)
|
||||
|
||||
Attaching a reparse point to an existing file or directory is done via
|
||||
SMB1 SMB_COM_NT_TRANSACT/NT_TRANSACT_IOCTL/FSCTL_SET_REPARSE_POINT command
|
||||
and implemented in a new cifs_create_reparse_inode() function.
|
||||
|
||||
This change introduce a new callback ->create_reparse_inode() which creates
|
||||
a new reperse point file or directory and returns inode. For SMB1 it is
|
||||
provided via that new cifs_create_reparse_inode() function.
|
||||
|
||||
Existing reparse.c code was only slightly updated to call new protocol
|
||||
callback ->create_reparse_inode() instead of hardcoded SMB2+ function.
|
||||
This make the whole reparse.c code to work with every SMB dialect.
|
||||
|
||||
The original callback ->create_reparse_symlink() is not needed anymore as
|
||||
the implementation of new create_reparse_symlink() function is dialect
|
||||
agnostic too. So the link.c code was updated to call that function directly
|
||||
(and not via callback).
|
||||
|
||||
Signed-off-by: Pali Rohár <pali@kernel.org>
|
||||
Signed-off-by: Steve French <stfrench@microsoft.com>
|
||||
---
|
||||
fs/smb/client/cifsglob.h | 14 +++--
|
||||
fs/smb/client/cifsproto.h | 8 +++
|
||||
fs/smb/client/cifssmb.c | 128 ++++++++++++++++++++++++++++++++++++++
|
||||
fs/smb/client/link.c | 13 ++--
|
||||
fs/smb/client/reparse.c | 16 +++--
|
||||
fs/smb/client/reparse.h | 4 +-
|
||||
fs/smb/client/smb1ops.c | 31 ++++++---
|
||||
fs/smb/client/smb2inode.c | 2 +-
|
||||
fs/smb/client/smb2ops.c | 10 +--
|
||||
fs/smb/client/smb2proto.h | 5 +-
|
||||
10 files changed, 188 insertions(+), 43 deletions(-)
|
||||
|
||||
--- a/fs/smb/client/cifsglob.h
|
||||
+++ b/fs/smb/client/cifsglob.h
|
||||
@@ -627,12 +627,14 @@ struct smb_version_operations {
|
||||
bool (*is_network_name_deleted)(char *buf, struct TCP_Server_Info *srv);
|
||||
struct reparse_data_buffer * (*get_reparse_point_buffer)(const struct kvec *rsp_iov,
|
||||
u32 *plen);
|
||||
- int (*create_reparse_symlink)(const unsigned int xid,
|
||||
- struct inode *inode,
|
||||
- struct dentry *dentry,
|
||||
- struct cifs_tcon *tcon,
|
||||
- const char *full_path,
|
||||
- const char *symname);
|
||||
+ struct inode * (*create_reparse_inode)(struct cifs_open_info_data *data,
|
||||
+ struct super_block *sb,
|
||||
+ const unsigned int xid,
|
||||
+ struct cifs_tcon *tcon,
|
||||
+ const char *full_path,
|
||||
+ bool directory,
|
||||
+ struct kvec *reparse_iov,
|
||||
+ struct kvec *xattr_iov);
|
||||
};
|
||||
|
||||
struct smb_version_values {
|
||||
--- a/fs/smb/client/cifsproto.h
|
||||
+++ b/fs/smb/client/cifsproto.h
|
||||
@@ -483,6 +483,14 @@ extern int cifs_query_reparse_point(cons
|
||||
const char *full_path,
|
||||
u32 *tag, struct kvec *rsp,
|
||||
int *rsp_buftype);
|
||||
+extern struct inode *cifs_create_reparse_inode(struct cifs_open_info_data *data,
|
||||
+ struct super_block *sb,
|
||||
+ const unsigned int xid,
|
||||
+ struct cifs_tcon *tcon,
|
||||
+ const char *full_path,
|
||||
+ bool directory,
|
||||
+ struct kvec *reparse_iov,
|
||||
+ struct kvec *xattr_iov);
|
||||
extern int CIFSSMB_set_compression(const unsigned int xid,
|
||||
struct cifs_tcon *tcon, __u16 fid);
|
||||
extern int CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms,
|
||||
--- a/fs/smb/client/cifssmb.c
|
||||
+++ b/fs/smb/client/cifssmb.c
|
||||
@@ -2851,6 +2851,134 @@ error:
|
||||
return rc;
|
||||
}
|
||||
|
||||
+struct inode *cifs_create_reparse_inode(struct cifs_open_info_data *data,
|
||||
+ struct super_block *sb,
|
||||
+ const unsigned int xid,
|
||||
+ struct cifs_tcon *tcon,
|
||||
+ const char *full_path,
|
||||
+ bool directory,
|
||||
+ struct kvec *reparse_iov,
|
||||
+ struct kvec *xattr_iov)
|
||||
+{
|
||||
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
+ struct cifs_open_parms oparms;
|
||||
+ TRANSACT_IOCTL_REQ *io_req;
|
||||
+ struct inode *new = NULL;
|
||||
+ struct kvec in_iov[2];
|
||||
+ struct kvec out_iov;
|
||||
+ struct cifs_fid fid;
|
||||
+ int io_req_len;
|
||||
+ int oplock = 0;
|
||||
+ int buf_type = 0;
|
||||
+ int rc;
|
||||
+
|
||||
+ cifs_tcon_dbg(FYI, "%s: path=%s\n", __func__, full_path);
|
||||
+
|
||||
+ /*
|
||||
+ * If server filesystem does not support reparse points then do not
|
||||
+ * attempt to create reparse point. This will prevent creating unusable
|
||||
+ * empty object on the server.
|
||||
+ */
|
||||
+ if (!(le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS))
|
||||
+ return ERR_PTR(-EOPNOTSUPP);
|
||||
+
|
||||
+#ifndef CONFIG_CIFS_XATTR
|
||||
+ if (xattr_iov)
|
||||
+ return ERR_PTR(-EOPNOTSUPP);
|
||||
+#endif
|
||||
+
|
||||
+ oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
|
||||
+ FILE_READ_ATTRIBUTES | FILE_WRITE_DATA | FILE_WRITE_EA,
|
||||
+ FILE_CREATE,
|
||||
+ (directory ? CREATE_NOT_FILE : CREATE_NOT_DIR) | OPEN_REPARSE_POINT,
|
||||
+ ACL_NO_MODE);
|
||||
+ oparms.fid = &fid;
|
||||
+
|
||||
+ rc = CIFS_open(xid, &oparms, &oplock, NULL);
|
||||
+ if (rc)
|
||||
+ return ERR_PTR(rc);
|
||||
+
|
||||
+#ifdef CONFIG_CIFS_XATTR
|
||||
+ if (xattr_iov) {
|
||||
+ struct smb2_file_full_ea_info *ea;
|
||||
+
|
||||
+ ea = &((struct smb2_create_ea_ctx *)xattr_iov->iov_base)->ea;
|
||||
+ while (1) {
|
||||
+ rc = CIFSSMBSetEA(xid,
|
||||
+ tcon,
|
||||
+ full_path,
|
||||
+ &ea->ea_data[0],
|
||||
+ &ea->ea_data[ea->ea_name_length+1],
|
||||
+ le16_to_cpu(ea->ea_value_length),
|
||||
+ cifs_sb->local_nls,
|
||||
+ cifs_sb);
|
||||
+ if (rc)
|
||||
+ goto out_close;
|
||||
+ if (le32_to_cpu(ea->next_entry_offset) == 0)
|
||||
+ break;
|
||||
+ ea = (struct smb2_file_full_ea_info *)((u8 *)ea +
|
||||
+ le32_to_cpu(ea->next_entry_offset));
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
+ rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **)&io_req, NULL);
|
||||
+ if (rc)
|
||||
+ goto out_close;
|
||||
+
|
||||
+ inc_rfc1001_len(io_req, sizeof(io_req->Pad));
|
||||
+
|
||||
+ io_req_len = be32_to_cpu(io_req->hdr.smb_buf_length) + sizeof(io_req->hdr.smb_buf_length);
|
||||
+
|
||||
+ /* NT IOCTL response contains one-word long output setup buffer with size of output data. */
|
||||
+ io_req->MaxSetupCount = 1;
|
||||
+ /* NT IOCTL response does not contain output parameters. */
|
||||
+ io_req->MaxParameterCount = cpu_to_le32(0);
|
||||
+ /* FSCTL_SET_REPARSE_POINT response contains empty output data. */
|
||||
+ io_req->MaxDataCount = cpu_to_le32(0);
|
||||
+
|
||||
+ io_req->TotalParameterCount = cpu_to_le32(0);
|
||||
+ io_req->TotalDataCount = cpu_to_le32(reparse_iov->iov_len);
|
||||
+ io_req->ParameterCount = io_req->TotalParameterCount;
|
||||
+ io_req->ParameterOffset = cpu_to_le32(0);
|
||||
+ io_req->DataCount = io_req->TotalDataCount;
|
||||
+ io_req->DataOffset = cpu_to_le32(offsetof(typeof(*io_req), Data) -
|
||||
+ sizeof(io_req->hdr.smb_buf_length));
|
||||
+ io_req->SetupCount = 4;
|
||||
+ io_req->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
|
||||
+ io_req->FunctionCode = cpu_to_le32(FSCTL_SET_REPARSE_POINT);
|
||||
+ io_req->Fid = fid.netfid;
|
||||
+ io_req->IsFsctl = 1;
|
||||
+ io_req->IsRootFlag = 0;
|
||||
+ io_req->ByteCount = cpu_to_le16(le32_to_cpu(io_req->DataCount) + sizeof(io_req->Pad));
|
||||
+
|
||||
+ inc_rfc1001_len(io_req, reparse_iov->iov_len);
|
||||
+
|
||||
+ in_iov[0].iov_base = (char *)io_req;
|
||||
+ in_iov[0].iov_len = io_req_len;
|
||||
+ in_iov[1] = *reparse_iov;
|
||||
+ rc = SendReceive2(xid, tcon->ses, in_iov, ARRAY_SIZE(in_iov), &buf_type,
|
||||
+ CIFS_NO_RSP_BUF, &out_iov);
|
||||
+
|
||||
+ cifs_buf_release(io_req);
|
||||
+
|
||||
+ if (!rc)
|
||||
+ rc = cifs_get_inode_info(&new, full_path, data, sb, xid, NULL);
|
||||
+
|
||||
+out_close:
|
||||
+ CIFSSMBClose(xid, tcon, fid.netfid);
|
||||
+
|
||||
+ /*
|
||||
+ * If CREATE was successful but FSCTL_SET_REPARSE_POINT failed then
|
||||
+ * remove the intermediate object created by CREATE. Otherwise
|
||||
+ * empty object stay on the server when reparse call failed.
|
||||
+ */
|
||||
+ if (rc)
|
||||
+ CIFSSMBDelFile(xid, tcon, full_path, cifs_sb, NULL);
|
||||
+
|
||||
+ return rc ? ERR_PTR(rc) : new;
|
||||
+}
|
||||
+
|
||||
int
|
||||
CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
__u16 fid)
|
||||
--- a/fs/smb/client/link.c
|
||||
+++ b/fs/smb/client/link.c
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "smb2proto.h"
|
||||
#include "cifs_ioctl.h"
|
||||
#include "fs_context.h"
|
||||
+#include "reparse.h"
|
||||
|
||||
/*
|
||||
* M-F Symlink Functions - Begin
|
||||
@@ -570,7 +571,6 @@ cifs_symlink(struct mnt_idmap *idmap, st
|
||||
int rc = -EOPNOTSUPP;
|
||||
unsigned int xid;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
- struct TCP_Server_Info *server;
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_tcon *pTcon;
|
||||
const char *full_path;
|
||||
@@ -593,7 +593,6 @@ cifs_symlink(struct mnt_idmap *idmap, st
|
||||
goto symlink_exit;
|
||||
}
|
||||
pTcon = tlink_tcon(tlink);
|
||||
- server = cifs_pick_channel(pTcon->ses);
|
||||
|
||||
full_path = build_path_from_dentry(direntry, page);
|
||||
if (IS_ERR(full_path)) {
|
||||
@@ -636,13 +635,9 @@ cifs_symlink(struct mnt_idmap *idmap, st
|
||||
case CIFS_SYMLINK_TYPE_NATIVE:
|
||||
case CIFS_SYMLINK_TYPE_NFS:
|
||||
case CIFS_SYMLINK_TYPE_WSL:
|
||||
- if (server->ops->create_reparse_symlink &&
|
||||
- (le32_to_cpu(pTcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS)) {
|
||||
- rc = server->ops->create_reparse_symlink(xid, inode,
|
||||
- direntry,
|
||||
- pTcon,
|
||||
- full_path,
|
||||
- symname);
|
||||
+ if (le32_to_cpu(pTcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS) {
|
||||
+ rc = create_reparse_symlink(xid, inode, direntry, pTcon,
|
||||
+ full_path, symname);
|
||||
goto symlink_exit;
|
||||
}
|
||||
break;
|
||||
--- a/fs/smb/client/reparse.c
|
||||
+++ b/fs/smb/client/reparse.c
|
||||
@@ -34,7 +34,7 @@ static int detect_directory_symlink_targ
|
||||
const char *symname,
|
||||
bool *directory);
|
||||
|
||||
-int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode,
|
||||
+int create_reparse_symlink(const unsigned int xid, struct inode *inode,
|
||||
struct dentry *dentry, struct cifs_tcon *tcon,
|
||||
const char *full_path, const char *symname)
|
||||
{
|
||||
@@ -227,7 +227,8 @@ static int create_native_symlink(const u
|
||||
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = len;
|
||||
- new = smb2_get_reparse_inode(&data, inode->i_sb, xid,
|
||||
+ new = tcon->ses->server->ops->create_reparse_inode(
|
||||
+ &data, inode->i_sb, xid,
|
||||
tcon, full_path, directory,
|
||||
&iov, NULL);
|
||||
if (!IS_ERR(new))
|
||||
@@ -399,7 +400,8 @@ static int create_native_socket(const un
|
||||
struct inode *new;
|
||||
int rc = 0;
|
||||
|
||||
- new = smb2_get_reparse_inode(&data, inode->i_sb, xid,
|
||||
+ new = tcon->ses->server->ops->create_reparse_inode(
|
||||
+ &data, inode->i_sb, xid,
|
||||
tcon, full_path, false, &iov, NULL);
|
||||
if (!IS_ERR(new))
|
||||
d_instantiate(dentry, new);
|
||||
@@ -492,7 +494,8 @@ static int mknod_nfs(unsigned int xid, s
|
||||
.symlink_target = kstrdup(symname, GFP_KERNEL),
|
||||
};
|
||||
|
||||
- new = smb2_get_reparse_inode(&data, inode->i_sb, xid,
|
||||
+ new = tcon->ses->server->ops->create_reparse_inode(
|
||||
+ &data, inode->i_sb, xid,
|
||||
tcon, full_path, false, &iov, NULL);
|
||||
if (!IS_ERR(new))
|
||||
d_instantiate(dentry, new);
|
||||
@@ -685,7 +688,8 @@ static int mknod_wsl(unsigned int xid, s
|
||||
memcpy(data.wsl.eas, &cc->ea, len);
|
||||
data.wsl.eas_len = len;
|
||||
|
||||
- new = smb2_get_reparse_inode(&data, inode->i_sb,
|
||||
+ new = tcon->ses->server->ops->create_reparse_inode(
|
||||
+ &data, inode->i_sb,
|
||||
xid, tcon, full_path, false,
|
||||
&reparse_iov, &xattr_iov);
|
||||
if (!IS_ERR(new))
|
||||
@@ -698,7 +702,7 @@ static int mknod_wsl(unsigned int xid, s
|
||||
return rc;
|
||||
}
|
||||
|
||||
-int smb2_mknod_reparse(unsigned int xid, struct inode *inode,
|
||||
+int mknod_reparse(unsigned int xid, struct inode *inode,
|
||||
struct dentry *dentry, struct cifs_tcon *tcon,
|
||||
const char *full_path, umode_t mode, dev_t dev)
|
||||
{
|
||||
--- a/fs/smb/client/reparse.h
|
||||
+++ b/fs/smb/client/reparse.h
|
||||
@@ -129,10 +129,10 @@ static inline bool cifs_open_data_repars
|
||||
bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,
|
||||
struct cifs_fattr *fattr,
|
||||
struct cifs_open_info_data *data);
|
||||
-int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode,
|
||||
+int create_reparse_symlink(const unsigned int xid, struct inode *inode,
|
||||
struct dentry *dentry, struct cifs_tcon *tcon,
|
||||
const char *full_path, const char *symname);
|
||||
-int smb2_mknod_reparse(unsigned int xid, struct inode *inode,
|
||||
+int mknod_reparse(unsigned int xid, struct inode *inode,
|
||||
struct dentry *dentry, struct cifs_tcon *tcon,
|
||||
const char *full_path, umode_t mode, dev_t dev);
|
||||
struct reparse_data_buffer *smb2_get_reparse_point_buffer(const struct kvec *rsp_iov, u32 *len);
|
||||
--- a/fs/smb/client/smb1ops.c
|
||||
+++ b/fs/smb/client/smb1ops.c
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "fs_context.h"
|
||||
#include "nterr.h"
|
||||
#include "smberr.h"
|
||||
+#include "reparse.h"
|
||||
|
||||
/*
|
||||
* An NT cancel request header looks just like the original request except:
|
||||
@@ -1263,17 +1264,26 @@ cifs_make_node(unsigned int xid, struct
|
||||
if (rc == 0)
|
||||
d_instantiate(dentry, newinode);
|
||||
return rc;
|
||||
+ } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
|
||||
+ /*
|
||||
+ * Check if mounted with mount parm 'sfu' mount parm.
|
||||
+ * SFU emulation should work with all servers
|
||||
+ * and was used by default in earlier versions of Windows.
|
||||
+ */
|
||||
+ return cifs_sfu_make_node(xid, inode, dentry, tcon,
|
||||
+ full_path, mode, dev);
|
||||
+ } else if (le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS) {
|
||||
+ /*
|
||||
+ * mknod via reparse points requires server support for
|
||||
+ * storing reparse points, which is available since
|
||||
+ * Windows 2000, but was not widely used until release
|
||||
+ * of Windows Server 2012 by the Windows NFS server.
|
||||
+ */
|
||||
+ return mknod_reparse(xid, inode, dentry, tcon,
|
||||
+ full_path, mode, dev);
|
||||
+ } else {
|
||||
+ return -EOPNOTSUPP;
|
||||
}
|
||||
- /*
|
||||
- * Check if mounted with mount parm 'sfu' mount parm.
|
||||
- * SFU emulation should work with all servers, but only
|
||||
- * supports block and char device, socket & fifo,
|
||||
- * and was used by default in earlier versions of Windows
|
||||
- */
|
||||
- if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
|
||||
- return -EPERM;
|
||||
- return cifs_sfu_make_node(xid, inode, dentry, tcon,
|
||||
- full_path, mode, dev);
|
||||
}
|
||||
|
||||
static bool
|
||||
@@ -1370,6 +1380,7 @@ struct smb_version_operations smb1_opera
|
||||
.create_hardlink = CIFSCreateHardLink,
|
||||
.query_symlink = cifs_query_symlink,
|
||||
.get_reparse_point_buffer = cifs_get_reparse_point_buffer,
|
||||
+ .create_reparse_inode = cifs_create_reparse_inode,
|
||||
.open = cifs_open_file,
|
||||
.set_fid = cifs_set_fid,
|
||||
.close = cifs_close_file,
|
||||
--- a/fs/smb/client/smb2inode.c
|
||||
+++ b/fs/smb/client/smb2inode.c
|
||||
@@ -1320,7 +1320,7 @@ smb2_set_file_info(struct inode *inode,
|
||||
return rc;
|
||||
}
|
||||
|
||||
-struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data,
|
||||
+struct inode *smb2_create_reparse_inode(struct cifs_open_info_data *data,
|
||||
struct super_block *sb,
|
||||
const unsigned int xid,
|
||||
struct cifs_tcon *tcon,
|
||||
--- a/fs/smb/client/smb2ops.c
|
||||
+++ b/fs/smb/client/smb2ops.c
|
||||
@@ -5271,7 +5271,7 @@ static int smb2_make_node(unsigned int x
|
||||
full_path, mode, dev);
|
||||
} else if ((le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS)
|
||||
|| (tcon->posix_extensions)) {
|
||||
- rc = smb2_mknod_reparse(xid, inode, dentry, tcon,
|
||||
+ rc = mknod_reparse(xid, inode, dentry, tcon,
|
||||
full_path, mode, dev);
|
||||
}
|
||||
return rc;
|
||||
@@ -5330,7 +5330,7 @@ struct smb_version_operations smb20_oper
|
||||
.get_reparse_point_buffer = smb2_get_reparse_point_buffer,
|
||||
.query_mf_symlink = smb3_query_mf_symlink,
|
||||
.create_mf_symlink = smb3_create_mf_symlink,
|
||||
- .create_reparse_symlink = smb2_create_reparse_symlink,
|
||||
+ .create_reparse_inode = smb2_create_reparse_inode,
|
||||
.open = smb2_open_file,
|
||||
.set_fid = smb2_set_fid,
|
||||
.close = smb2_close_file,
|
||||
@@ -5433,7 +5433,7 @@ struct smb_version_operations smb21_oper
|
||||
.get_reparse_point_buffer = smb2_get_reparse_point_buffer,
|
||||
.query_mf_symlink = smb3_query_mf_symlink,
|
||||
.create_mf_symlink = smb3_create_mf_symlink,
|
||||
- .create_reparse_symlink = smb2_create_reparse_symlink,
|
||||
+ .create_reparse_inode = smb2_create_reparse_inode,
|
||||
.open = smb2_open_file,
|
||||
.set_fid = smb2_set_fid,
|
||||
.close = smb2_close_file,
|
||||
@@ -5540,7 +5540,7 @@ struct smb_version_operations smb30_oper
|
||||
.get_reparse_point_buffer = smb2_get_reparse_point_buffer,
|
||||
.query_mf_symlink = smb3_query_mf_symlink,
|
||||
.create_mf_symlink = smb3_create_mf_symlink,
|
||||
- .create_reparse_symlink = smb2_create_reparse_symlink,
|
||||
+ .create_reparse_inode = smb2_create_reparse_inode,
|
||||
.open = smb2_open_file,
|
||||
.set_fid = smb2_set_fid,
|
||||
.close = smb2_close_file,
|
||||
@@ -5656,7 +5656,7 @@ struct smb_version_operations smb311_ope
|
||||
.get_reparse_point_buffer = smb2_get_reparse_point_buffer,
|
||||
.query_mf_symlink = smb3_query_mf_symlink,
|
||||
.create_mf_symlink = smb3_create_mf_symlink,
|
||||
- .create_reparse_symlink = smb2_create_reparse_symlink,
|
||||
+ .create_reparse_inode = smb2_create_reparse_inode,
|
||||
.open = smb2_open_file,
|
||||
.set_fid = smb2_set_fid,
|
||||
.close = smb2_close_file,
|
||||
--- a/fs/smb/client/smb2proto.h
|
||||
+++ b/fs/smb/client/smb2proto.h
|
||||
@@ -54,7 +54,7 @@ extern int smb3_handle_read_data(struct
|
||||
extern int smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct cifs_sb_info *cifs_sb, const char *path,
|
||||
__u32 *reparse_tag);
|
||||
-struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data,
|
||||
+struct inode *smb2_create_reparse_inode(struct cifs_open_info_data *data,
|
||||
struct super_block *sb,
|
||||
const unsigned int xid,
|
||||
struct cifs_tcon *tcon,
|
||||
@@ -314,9 +314,6 @@ int smb311_posix_query_path_info(const u
|
||||
int posix_info_parse(const void *beg, const void *end,
|
||||
struct smb2_posix_info_parsed *out);
|
||||
int posix_info_sid_size(const void *beg, const void *end);
|
||||
-int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode,
|
||||
- struct dentry *dentry, struct cifs_tcon *tcon,
|
||||
- const char *full_path, const char *symname);
|
||||
int smb2_make_nfs_node(unsigned int xid, struct inode *inode,
|
||||
struct dentry *dentry, struct cifs_tcon *tcon,
|
||||
const char *full_path, umode_t mode, dev_t dev);
|
109
debian/patches/patchset-pf/steady/0034-smb-client-fix-creating-symlinks-under-POSIX-mounts.patch
vendored
Normal file
109
debian/patches/patchset-pf/steady/0034-smb-client-fix-creating-symlinks-under-POSIX-mounts.patch
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
From c027b463e9389e4421b21f170128f35c0f2941b9 Mon Sep 17 00:00:00 2001
|
||||
From: Paulo Alcantara <pc@manguebit.org>
|
||||
Date: Thu, 31 Jul 2025 20:46:43 -0300
|
||||
Subject: smb: client: fix creating symlinks under POSIX mounts
|
||||
|
||||
SMB3.1.1 POSIX mounts support native symlinks that are created with
|
||||
IO_REPARSE_TAG_SYMLINK reparse points, so skip the checking of
|
||||
FILE_SUPPORTS_REPARSE_POINTS as some servers might not have it set.
|
||||
|
||||
Cc: linux-cifs@vger.kernel.org
|
||||
Cc: Ralph Boehme <slow@samba.org>
|
||||
Cc: David Howells <dhowells@redhat.com>
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Reported-by: Matthew Richardson <m.richardson@ed.ac.uk>
|
||||
Closes: https://marc.info/?i=1124e7cd-6a46-40a6-9f44-b7664a66654b@ed.ac.uk
|
||||
Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.org>
|
||||
Signed-off-by: Steve French <stfrench@microsoft.com>
|
||||
---
|
||||
fs/smb/client/cifsglob.h | 5 +++++
|
||||
fs/smb/client/cifssmb.c | 4 ++--
|
||||
fs/smb/client/link.c | 2 +-
|
||||
fs/smb/client/smb1ops.c | 2 +-
|
||||
fs/smb/client/smb2inode.c | 5 ++---
|
||||
fs/smb/client/smb2ops.c | 5 ++---
|
||||
6 files changed, 13 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/fs/smb/client/cifsglob.h
|
||||
+++ b/fs/smb/client/cifsglob.h
|
||||
@@ -2377,4 +2377,9 @@ static inline bool cifs_netbios_name(con
|
||||
return ret;
|
||||
}
|
||||
|
||||
+#define CIFS_REPARSE_SUPPORT(tcon) \
|
||||
+ ((tcon)->posix_extensions || \
|
||||
+ (le32_to_cpu((tcon)->fsAttrInfo.Attributes) & \
|
||||
+ FILE_SUPPORTS_REPARSE_POINTS))
|
||||
+
|
||||
#endif /* _CIFS_GLOB_H */
|
||||
--- a/fs/smb/client/cifssmb.c
|
||||
+++ b/fs/smb/client/cifssmb.c
|
||||
@@ -2751,7 +2751,7 @@ int cifs_query_reparse_point(const unsig
|
||||
if (cap_unix(tcon->ses))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
- if (!(le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS))
|
||||
+ if (!CIFS_REPARSE_SUPPORT(tcon))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
oparms = (struct cifs_open_parms) {
|
||||
@@ -2879,7 +2879,7 @@ struct inode *cifs_create_reparse_inode(
|
||||
* attempt to create reparse point. This will prevent creating unusable
|
||||
* empty object on the server.
|
||||
*/
|
||||
- if (!(le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS))
|
||||
+ if (!CIFS_REPARSE_SUPPORT(tcon))
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
|
||||
#ifndef CONFIG_CIFS_XATTR
|
||||
--- a/fs/smb/client/link.c
|
||||
+++ b/fs/smb/client/link.c
|
||||
@@ -635,7 +635,7 @@ cifs_symlink(struct mnt_idmap *idmap, st
|
||||
case CIFS_SYMLINK_TYPE_NATIVE:
|
||||
case CIFS_SYMLINK_TYPE_NFS:
|
||||
case CIFS_SYMLINK_TYPE_WSL:
|
||||
- if (le32_to_cpu(pTcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS) {
|
||||
+ if (CIFS_REPARSE_SUPPORT(pTcon)) {
|
||||
rc = create_reparse_symlink(xid, inode, direntry, pTcon,
|
||||
full_path, symname);
|
||||
goto symlink_exit;
|
||||
--- a/fs/smb/client/smb1ops.c
|
||||
+++ b/fs/smb/client/smb1ops.c
|
||||
@@ -1272,7 +1272,7 @@ cifs_make_node(unsigned int xid, struct
|
||||
*/
|
||||
return cifs_sfu_make_node(xid, inode, dentry, tcon,
|
||||
full_path, mode, dev);
|
||||
- } else if (le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS) {
|
||||
+ } else if (CIFS_REPARSE_SUPPORT(tcon)) {
|
||||
/*
|
||||
* mknod via reparse points requires server support for
|
||||
* storing reparse points, which is available since
|
||||
--- a/fs/smb/client/smb2inode.c
|
||||
+++ b/fs/smb/client/smb2inode.c
|
||||
@@ -1345,9 +1345,8 @@ struct inode *smb2_create_reparse_inode(
|
||||
* attempt to create reparse point. This will prevent creating unusable
|
||||
* empty object on the server.
|
||||
*/
|
||||
- if (!(le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS))
|
||||
- if (!tcon->posix_extensions)
|
||||
- return ERR_PTR(-EOPNOTSUPP);
|
||||
+ if (!CIFS_REPARSE_SUPPORT(tcon))
|
||||
+ return ERR_PTR(-EOPNOTSUPP);
|
||||
|
||||
oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
|
||||
SYNCHRONIZE | DELETE |
|
||||
--- a/fs/smb/client/smb2ops.c
|
||||
+++ b/fs/smb/client/smb2ops.c
|
||||
@@ -5269,10 +5269,9 @@ static int smb2_make_node(unsigned int x
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
|
||||
rc = cifs_sfu_make_node(xid, inode, dentry, tcon,
|
||||
full_path, mode, dev);
|
||||
- } else if ((le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS)
|
||||
- || (tcon->posix_extensions)) {
|
||||
+ } else if (CIFS_REPARSE_SUPPORT(tcon)) {
|
||||
rc = mknod_reparse(xid, inode, dentry, tcon,
|
||||
- full_path, mode, dev);
|
||||
+ full_path, mode, dev);
|
||||
}
|
||||
return rc;
|
||||
}
|
45
debian/patches/patchset-pf/steady/0035-kasan-test-fix-protection-against-compiler-elision.patch
vendored
Normal file
45
debian/patches/patchset-pf/steady/0035-kasan-test-fix-protection-against-compiler-elision.patch
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
From 8c47c2c4bebf98d0624c15cecef00536d50d79a6 Mon Sep 17 00:00:00 2001
|
||||
From: Jann Horn <jannh@google.com>
|
||||
Date: Mon, 28 Jul 2025 22:11:54 +0200
|
||||
Subject: kasan/test: fix protection against compiler elision
|
||||
|
||||
The kunit test is using assignments to
|
||||
"static volatile void *kasan_ptr_result" to prevent elision of memory
|
||||
loads, but that's not working:
|
||||
In this variable definition, the "volatile" applies to the "void", not to
|
||||
the pointer.
|
||||
To make "volatile" apply to the pointer as intended, it must follow
|
||||
after the "*".
|
||||
|
||||
This makes the kasan_memchr test pass again on my system. The
|
||||
kasan_strings test is still failing because all the definitions of
|
||||
load_unaligned_zeropad() are lacking explicit instrumentation hooks and
|
||||
ASAN does not instrument asm() memory operands.
|
||||
|
||||
Link: https://lkml.kernel.org/r/20250728-kasan-kunit-fix-volatile-v1-1-e7157c9af82d@google.com
|
||||
Fixes: 5f1c8108e7ad ("mm:kasan: fix sparse warnings: Should it be static?")
|
||||
Signed-off-by: Jann Horn <jannh@google.com>
|
||||
Cc: Alexander Potapenko <glider@google.com>
|
||||
Cc: Andrey Konovalov <andreyknvl@gmail.com>
|
||||
Cc: Andrey Ryabinin <ryabinin.a.a@gmail.com>
|
||||
Cc: Dmitriy Vyukov <dvyukov@google.com>
|
||||
Cc: Jann Horn <jannh@google.com>
|
||||
Cc: Nihar Chaithanya <niharchaithanya@gmail.com>
|
||||
Cc: Vincenzo Frascino <vincenzo.frascino@arm.com>
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
---
|
||||
mm/kasan/kasan_test_c.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/mm/kasan/kasan_test_c.c
|
||||
+++ b/mm/kasan/kasan_test_c.c
|
||||
@@ -47,7 +47,7 @@ static struct {
|
||||
* Some tests use these global variables to store return values from function
|
||||
* calls that could otherwise be eliminated by the compiler as dead code.
|
||||
*/
|
||||
-static volatile void *kasan_ptr_result;
|
||||
+static void *volatile kasan_ptr_result;
|
||||
static volatile int kasan_int_result;
|
||||
|
||||
/* Probe for console output: obtains test_status lines of interest. */
|
@@ -0,0 +1,42 @@
|
||||
From d22a1695f7b89c228e60a9310d597597a6710666 Mon Sep 17 00:00:00 2001
|
||||
From: Jialin Wang <wjl.linux@gmail.com>
|
||||
Date: Fri, 8 Aug 2025 00:54:55 +0800
|
||||
Subject: proc: proc_maps_open allow proc_mem_open to return NULL
|
||||
|
||||
The commit 65c66047259f ("proc: fix the issue of proc_mem_open returning
|
||||
NULL") caused proc_maps_open() to return -ESRCH when proc_mem_open()
|
||||
returns NULL. This breaks legitimate /proc/<pid>/maps access for kernel
|
||||
threads since kernel threads have NULL mm_struct.
|
||||
|
||||
The regression causes perf to fail and exit when profiling a kernel
|
||||
thread:
|
||||
|
||||
# perf record -v -g -p $(pgrep kswapd0)
|
||||
...
|
||||
couldn't open /proc/65/task/65/maps
|
||||
|
||||
This patch partially reverts the commit to fix it.
|
||||
|
||||
Link: https://lkml.kernel.org/r/20250807165455.73656-1-wjl.linux@gmail.com
|
||||
Fixes: 65c66047259f ("proc: fix the issue of proc_mem_open returning NULL")
|
||||
Signed-off-by: Jialin Wang <wjl.linux@gmail.com>
|
||||
Cc: Penglei Jiang <superman.xpt@gmail.com>
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
---
|
||||
fs/proc/task_mmu.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/fs/proc/task_mmu.c
|
||||
+++ b/fs/proc/task_mmu.c
|
||||
@@ -215,8 +215,8 @@ static int proc_maps_open(struct inode *
|
||||
|
||||
priv->inode = inode;
|
||||
priv->mm = proc_mem_open(inode, PTRACE_MODE_READ);
|
||||
- if (IS_ERR_OR_NULL(priv->mm)) {
|
||||
- int err = priv->mm ? PTR_ERR(priv->mm) : -ESRCH;
|
||||
+ if (IS_ERR(priv->mm)) {
|
||||
+ int err = PTR_ERR(priv->mm);
|
||||
|
||||
seq_release_private(inode, file);
|
||||
return err;
|
56
debian/patches/patchset-pf/steady/0037-block-restore-default-wbt-enablement.patch
vendored
Normal file
56
debian/patches/patchset-pf/steady/0037-block-restore-default-wbt-enablement.patch
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
From ca0b04683be7bba50703eaec260167ec494d80b8 Mon Sep 17 00:00:00 2001
|
||||
From: Julian Sun <sunjunchao2870@gmail.com>
|
||||
Date: Tue, 12 Aug 2025 23:42:57 +0800
|
||||
Subject: block: restore default wbt enablement
|
||||
|
||||
The commit 245618f8e45f ("block: protect wbt_lat_usec using
|
||||
q->elevator_lock") protected wbt_enable_default() with
|
||||
q->elevator_lock; however, it also placed wbt_enable_default()
|
||||
before blk_queue_flag_set(QUEUE_FLAG_REGISTERED, q);, resulting
|
||||
in wbt failing to be enabled.
|
||||
|
||||
Moreover, the protection of wbt_enable_default() by q->elevator_lock
|
||||
was removed in commit 78c271344b6f ("block: move wbt_enable_default()
|
||||
out of queue freezing from sched ->exit()"), so we can directly fix
|
||||
this issue by placing wbt_enable_default() after
|
||||
blk_queue_flag_set(QUEUE_FLAG_REGISTERED, q);.
|
||||
|
||||
Additionally, this issue also causes the inability to read the
|
||||
wbt_lat_usec file, and the scenario is as follows:
|
||||
|
||||
root@q:/sys/block/sda/queue# cat wbt_lat_usec
|
||||
cat: wbt_lat_usec: Invalid argument
|
||||
|
||||
root@q:/data00/sjc/linux# ls /sys/kernel/debug/block/sda/rqos
|
||||
cannot access '/sys/kernel/debug/block/sda/rqos': No such file or directory
|
||||
|
||||
root@q:/data00/sjc/linux# find /sys -name wbt
|
||||
/sys/kernel/debug/tracing/events/wbt
|
||||
|
||||
After testing with this patch, wbt can be enabled normally.
|
||||
|
||||
Signed-off-by: Julian Sun <sunjunchao@bytedance.com>
|
||||
Cc: stable@vger.kernel.org
|
||||
Fixes: 245618f8e45f ("block: protect wbt_lat_usec using q->elevator_lock")
|
||||
Reviewed-by: Nilay Shroff <nilay@linux.ibm.com>
|
||||
Reviewed-by: Yu Kuai <yukuai3@huawei.com>
|
||||
Reviewed-by: Ming Lei <ming.lei@redhat.com>
|
||||
Link: https://lore.kernel.org/r/20250812154257.57540-1-sunjunchao@bytedance.com
|
||||
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
||||
---
|
||||
block/blk-sysfs.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/block/blk-sysfs.c
|
||||
+++ b/block/blk-sysfs.c
|
||||
@@ -876,9 +876,9 @@ int blk_register_queue(struct gendisk *d
|
||||
|
||||
if (queue_is_mq(q))
|
||||
elevator_set_default(q);
|
||||
- wbt_enable_default(disk);
|
||||
|
||||
blk_queue_flag_set(QUEUE_FLAG_REGISTERED, q);
|
||||
+ wbt_enable_default(disk);
|
||||
|
||||
/* Now everything is ready and send out KOBJ_ADD uevent */
|
||||
kobject_uevent(&disk->queue_kobj, KOBJ_ADD);
|
@@ -0,0 +1,50 @@
|
||||
From 599815c47256ca7901fc5b0de5cbc6f08e803e48 Mon Sep 17 00:00:00 2001
|
||||
From: Christoph Hellwig <hch@lst.de>
|
||||
Date: Wed, 23 Jul 2025 14:19:44 +0200
|
||||
Subject: xfs: fully decouple XFS_IBULK* flags from XFS_IWALK* flags
|
||||
|
||||
Fix up xfs_inumbers to now pass in the XFS_IBULK* flags into the flags
|
||||
argument to xfs_inobt_walk, which expects the XFS_IWALK* flags.
|
||||
|
||||
Currently passing the wrong flags works for non-debug builds because
|
||||
the only XFS_IWALK* flag has the same encoding as the corresponding
|
||||
XFS_IBULK* flag, but in debug builds it can trigger an assert that no
|
||||
incorrect flag is passed. Instead just extra the relevant flag.
|
||||
|
||||
Fixes: 5b35d922c52798 ("xfs: Decouple XFS_IBULK flags from XFS_IWALK flags")
|
||||
Cc: <stable@vger.kernel.org> # v5.19
|
||||
Reported-by: cen zhang <zzzccc427@gmail.com>
|
||||
Signed-off-by: Christoph Hellwig <hch@lst.de>
|
||||
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
|
||||
Signed-off-by: Carlos Maiolino <cem@kernel.org>
|
||||
---
|
||||
fs/xfs/xfs_itable.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/fs/xfs/xfs_itable.c
|
||||
+++ b/fs/xfs/xfs_itable.c
|
||||
@@ -455,11 +455,15 @@ xfs_inumbers(
|
||||
.breq = breq,
|
||||
};
|
||||
struct xfs_trans *tp;
|
||||
+ unsigned int iwalk_flags = 0;
|
||||
int error = 0;
|
||||
|
||||
if (xfs_bulkstat_already_done(breq->mp, breq->startino))
|
||||
return 0;
|
||||
|
||||
+ if (breq->flags & XFS_IBULK_SAME_AG)
|
||||
+ iwalk_flags |= XFS_IWALK_SAME_AG;
|
||||
+
|
||||
/*
|
||||
* Grab an empty transaction so that we can use its recursive buffer
|
||||
* locking abilities to detect cycles in the inobt without deadlocking.
|
||||
@@ -468,7 +472,7 @@ xfs_inumbers(
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
- error = xfs_inobt_walk(breq->mp, tp, breq->startino, breq->flags,
|
||||
+ error = xfs_inobt_walk(breq->mp, tp, breq->startino, iwalk_flags,
|
||||
xfs_inumbers_walk, breq->icount, &ic);
|
||||
xfs_trans_cancel(tp);
|
||||
out:
|
@@ -0,0 +1,66 @@
|
||||
From d2a99ecf2d0479f78a21568eee08f4ca27652629 Mon Sep 17 00:00:00 2001
|
||||
From: Guenter Roeck <linux@roeck-us.net>
|
||||
Date: Sun, 17 Aug 2025 07:48:17 -0700
|
||||
Subject: watchdog: intel_oc_wdt: Do not try to write into const memory
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The code tries to update the intel_oc_wdt_info data structure if the
|
||||
watchdog is locked. That data structure is marked as const and can not
|
||||
be written into. Copy it into struct intel_oc_wdt and modify it there
|
||||
to fix the problem.
|
||||
|
||||
Reported-by: Petar Kulić <cooleech@gmail.com>
|
||||
Cc: Diogo Ivo <diogo.ivo@siemens.com>
|
||||
Fixes: 535d1784d8a9 ("watchdog: Add driver for Intel OC WDT")
|
||||
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
|
||||
---
|
||||
drivers/watchdog/intel_oc_wdt.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/watchdog/intel_oc_wdt.c
|
||||
+++ b/drivers/watchdog/intel_oc_wdt.c
|
||||
@@ -41,6 +41,7 @@
|
||||
struct intel_oc_wdt {
|
||||
struct watchdog_device wdd;
|
||||
struct resource *ctrl_res;
|
||||
+ struct watchdog_info info;
|
||||
bool locked;
|
||||
};
|
||||
|
||||
@@ -115,7 +116,6 @@ static const struct watchdog_ops intel_o
|
||||
|
||||
static int intel_oc_wdt_setup(struct intel_oc_wdt *oc_wdt)
|
||||
{
|
||||
- struct watchdog_info *info;
|
||||
unsigned long val;
|
||||
|
||||
val = inl(INTEL_OC_WDT_CTRL_REG(oc_wdt));
|
||||
@@ -134,7 +134,6 @@ static int intel_oc_wdt_setup(struct int
|
||||
set_bit(WDOG_HW_RUNNING, &oc_wdt->wdd.status);
|
||||
|
||||
if (oc_wdt->locked) {
|
||||
- info = (struct watchdog_info *)&intel_oc_wdt_info;
|
||||
/*
|
||||
* Set nowayout unconditionally as we cannot stop
|
||||
* the watchdog.
|
||||
@@ -145,7 +144,7 @@ static int intel_oc_wdt_setup(struct int
|
||||
* and inform the core we can't change it.
|
||||
*/
|
||||
oc_wdt->wdd.timeout = (val & INTEL_OC_WDT_TOV) + 1;
|
||||
- info->options &= ~WDIOF_SETTIMEOUT;
|
||||
+ oc_wdt->info.options &= ~WDIOF_SETTIMEOUT;
|
||||
|
||||
dev_info(oc_wdt->wdd.parent,
|
||||
"Register access locked, heartbeat fixed at: %u s\n",
|
||||
@@ -193,7 +192,8 @@ static int intel_oc_wdt_probe(struct pla
|
||||
wdd->min_timeout = INTEL_OC_WDT_MIN_TOV;
|
||||
wdd->max_timeout = INTEL_OC_WDT_MAX_TOV;
|
||||
wdd->timeout = INTEL_OC_WDT_DEF_TOV;
|
||||
- wdd->info = &intel_oc_wdt_info;
|
||||
+ oc_wdt->info = intel_oc_wdt_info;
|
||||
+ wdd->info = &oc_wdt->info;
|
||||
wdd->ops = &intel_oc_wdt_ops;
|
||||
wdd->parent = dev;
|
||||
|
62
debian/patches/patchset-pf/steady/0040-cgroup-avoid-null-de-ref-in-css_rstat_exit.patch
vendored
Normal file
62
debian/patches/patchset-pf/steady/0040-cgroup-avoid-null-de-ref-in-css_rstat_exit.patch
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
From 76511b0ae1da7f401fe06c8b4dd18a40c3a2b52b Mon Sep 17 00:00:00 2001
|
||||
From: JP Kobryn <inwardvessel@gmail.com>
|
||||
Date: Wed, 6 Aug 2025 17:33:50 -0700
|
||||
Subject: cgroup: avoid null de-ref in css_rstat_exit()
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
css_rstat_exit() may be called asynchronously in scenarios where preceding
|
||||
calls to css_rstat_init() have not completed. One such example is this
|
||||
sequence below:
|
||||
|
||||
css_create(...)
|
||||
{
|
||||
...
|
||||
init_and_link_css(css, ...);
|
||||
|
||||
err = percpu_ref_init(...);
|
||||
if (err)
|
||||
goto err_free_css;
|
||||
err = cgroup_idr_alloc(...);
|
||||
if (err)
|
||||
goto err_free_css;
|
||||
err = css_rstat_init(css, ...);
|
||||
if (err)
|
||||
goto err_free_css;
|
||||
...
|
||||
err_free_css:
|
||||
INIT_RCU_WORK(&css->destroy_rwork, css_free_rwork_fn);
|
||||
queue_rcu_work(cgroup_destroy_wq, &css->destroy_rwork);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
If any of the three goto jumps are taken, async cleanup will begin and
|
||||
css_rstat_exit() will be invoked on an uninitialized css->rstat_cpu.
|
||||
|
||||
Avoid accessing the unitialized field by returning early in
|
||||
css_rstat_exit() if this is the case.
|
||||
|
||||
Signed-off-by: JP Kobryn <inwardvessel@gmail.com>
|
||||
Suggested-by: Michal Koutný <mkoutny@suse.com>
|
||||
Fixes: 5da3bfa029d68 ("cgroup: use separate rstat trees for each subsystem")
|
||||
Cc: stable@vger.kernel.org # v6.16
|
||||
Reported-by: syzbot+8d052e8b99e40bc625ed@syzkaller.appspotmail.com
|
||||
Acked-by: Shakeel Butt <shakeel.butt@linux.dev>
|
||||
Signed-off-by: Tejun Heo <tj@kernel.org>
|
||||
---
|
||||
kernel/cgroup/rstat.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
--- a/kernel/cgroup/rstat.c
|
||||
+++ b/kernel/cgroup/rstat.c
|
||||
@@ -488,6 +488,9 @@ void css_rstat_exit(struct cgroup_subsys
|
||||
if (!css_uses_rstat(css))
|
||||
return;
|
||||
|
||||
+ if (!css->rstat_cpu)
|
||||
+ return;
|
||||
+
|
||||
css_rstat_flush(css);
|
||||
|
||||
/* sanity check */
|
@@ -0,0 +1,43 @@
|
||||
From 1b24003064570fdf29c55bac14d4728977195133 Mon Sep 17 00:00:00 2001
|
||||
From: Aleksa Sarai <cyphar@cyphar.com>
|
||||
Date: Fri, 8 Aug 2025 03:55:05 +1000
|
||||
Subject: open_tree_attr: do not allow id-mapping changes without
|
||||
OPEN_TREE_CLONE
|
||||
|
||||
As described in commit 7a54947e727b ('Merge patch series "fs: allow
|
||||
changing idmappings"'), open_tree_attr(2) was necessary in order to
|
||||
allow for a detached mount to be created and have its idmappings changed
|
||||
without the risk of any racing threads operating on it. For this reason,
|
||||
mount_setattr(2) still does not allow for id-mappings to be changed.
|
||||
|
||||
However, there was a bug in commit 2462651ffa76 ("fs: allow changing
|
||||
idmappings") which allowed users to bypass this restriction by calling
|
||||
open_tree_attr(2) *without* OPEN_TREE_CLONE.
|
||||
|
||||
can_idmap_mount() prevented this bug from allowing an attached
|
||||
mountpoint's id-mapping from being modified (thanks to an is_anon_ns()
|
||||
check), but this still allows for detached (but visible) mounts to have
|
||||
their be id-mapping changed. This risks the same UAF and locking issues
|
||||
as described in the merge commit, and was likely unintentional.
|
||||
|
||||
Fixes: 2462651ffa76 ("fs: allow changing idmappings")
|
||||
Cc: stable@vger.kernel.org # v6.15+
|
||||
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
|
||||
Link: https://lore.kernel.org/20250808-open_tree_attr-bugfix-idmap-v1-1-0ec7bc05646c@cyphar.com
|
||||
Signed-off-by: Christian Brauner <brauner@kernel.org>
|
||||
---
|
||||
fs/namespace.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/fs/namespace.c
|
||||
+++ b/fs/namespace.c
|
||||
@@ -5302,7 +5302,8 @@ SYSCALL_DEFINE5(open_tree_attr, int, dfd
|
||||
int ret;
|
||||
struct mount_kattr kattr = {};
|
||||
|
||||
- kattr.kflags = MOUNT_KATTR_IDMAP_REPLACE;
|
||||
+ if (flags & OPEN_TREE_CLONE)
|
||||
+ kattr.kflags = MOUNT_KATTR_IDMAP_REPLACE;
|
||||
if (flags & AT_RECURSIVE)
|
||||
kattr.kflags |= MOUNT_KATTR_RECURSE;
|
||||
|
@@ -0,0 +1,53 @@
|
||||
From 2435722a492f57a060202726a820b0da64f42105 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Kara <jack@suse.cz>
|
||||
Date: Wed, 30 Jul 2025 12:28:41 +0200
|
||||
Subject: iomap: Fix broken data integrity guarantees for O_SYNC writes
|
||||
|
||||
Commit d279c80e0bac ("iomap: inline iomap_dio_bio_opflags()") has broken
|
||||
the logic in iomap_dio_bio_iter() in a way that when the device does
|
||||
support FUA (or has no writeback cache) and the direct IO happens to
|
||||
freshly allocated or unwritten extents, we will *not* issue fsync after
|
||||
completing direct IO O_SYNC / O_DSYNC write because the
|
||||
IOMAP_DIO_WRITE_THROUGH flag stays mistakenly set. Fix the problem by
|
||||
clearing IOMAP_DIO_WRITE_THROUGH whenever we do not perform FUA write as
|
||||
it was originally intended.
|
||||
|
||||
CC: John Garry <john.g.garry@oracle.com>
|
||||
CC: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
|
||||
Fixes: d279c80e0bac ("iomap: inline iomap_dio_bio_opflags()")
|
||||
CC: stable@vger.kernel.org
|
||||
Signed-off-by: Jan Kara <jack@suse.cz>
|
||||
Link: https://lore.kernel.org/20250730102840.20470-2-jack@suse.cz
|
||||
Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
|
||||
Reviewed-by: John Garry <john.g.garry@oracle.com>
|
||||
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
|
||||
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||
Signed-off-by: Christian Brauner <brauner@kernel.org>
|
||||
---
|
||||
fs/iomap/direct-io.c | 14 +++++++-------
|
||||
1 file changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/fs/iomap/direct-io.c
|
||||
+++ b/fs/iomap/direct-io.c
|
||||
@@ -368,14 +368,14 @@ static int iomap_dio_bio_iter(struct iom
|
||||
if (iomap->flags & IOMAP_F_SHARED)
|
||||
dio->flags |= IOMAP_DIO_COW;
|
||||
|
||||
- if (iomap->flags & IOMAP_F_NEW) {
|
||||
+ if (iomap->flags & IOMAP_F_NEW)
|
||||
need_zeroout = true;
|
||||
- } else if (iomap->type == IOMAP_MAPPED) {
|
||||
- if (iomap_dio_can_use_fua(iomap, dio))
|
||||
- bio_opf |= REQ_FUA;
|
||||
- else
|
||||
- dio->flags &= ~IOMAP_DIO_WRITE_THROUGH;
|
||||
- }
|
||||
+ else if (iomap->type == IOMAP_MAPPED &&
|
||||
+ iomap_dio_can_use_fua(iomap, dio))
|
||||
+ bio_opf |= REQ_FUA;
|
||||
+
|
||||
+ if (!(bio_opf & REQ_FUA))
|
||||
+ dio->flags &= ~IOMAP_DIO_WRITE_THROUGH;
|
||||
|
||||
/*
|
||||
* We can only do deferred completion for pure overwrites that
|
@@ -0,0 +1,60 @@
|
||||
From 77f4f1ca7b68d33c3841e740ae6b03378a77d281 Mon Sep 17 00:00:00 2001
|
||||
From: Andrea Righi <arighi@nvidia.com>
|
||||
Date: Tue, 5 Aug 2025 10:59:11 +0200
|
||||
Subject: sched/ext: Fix invalid task state transitions on class switch
|
||||
|
||||
When enabling a sched_ext scheduler, we may trigger invalid task state
|
||||
transitions, resulting in warnings like the following (which can be
|
||||
easily reproduced by running the hotplug selftest in a loop):
|
||||
|
||||
sched_ext: Invalid task state transition 0 -> 3 for fish[770]
|
||||
WARNING: CPU: 18 PID: 787 at kernel/sched/ext.c:3862 scx_set_task_state+0x7c/0xc0
|
||||
...
|
||||
RIP: 0010:scx_set_task_state+0x7c/0xc0
|
||||
...
|
||||
Call Trace:
|
||||
<TASK>
|
||||
scx_enable_task+0x11f/0x2e0
|
||||
switching_to_scx+0x24/0x110
|
||||
scx_enable.isra.0+0xd14/0x13d0
|
||||
bpf_struct_ops_link_create+0x136/0x1a0
|
||||
__sys_bpf+0x1edd/0x2c30
|
||||
__x64_sys_bpf+0x21/0x30
|
||||
do_syscall_64+0xbb/0x370
|
||||
entry_SYSCALL_64_after_hwframe+0x77/0x7f
|
||||
|
||||
This happens because we skip initialization for tasks that are already
|
||||
dead (with their usage counter set to zero), but we don't exclude them
|
||||
during the scheduling class transition phase.
|
||||
|
||||
Fix this by also skipping dead tasks during class swiching, preventing
|
||||
invalid task state transitions.
|
||||
|
||||
Fixes: a8532fac7b5d2 ("sched_ext: TASK_DEAD tasks must be switched into SCX on ops_enable")
|
||||
Cc: stable@vger.kernel.org # v6.12+
|
||||
Signed-off-by: Andrea Righi <arighi@nvidia.com>
|
||||
Signed-off-by: Tejun Heo <tj@kernel.org>
|
||||
---
|
||||
kernel/sched/ext.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
--- a/kernel/sched/ext.c
|
||||
+++ b/kernel/sched/ext.c
|
||||
@@ -5694,6 +5694,9 @@ static int scx_enable(struct sched_ext_o
|
||||
__setscheduler_class(p->policy, p->prio);
|
||||
struct sched_enq_and_set_ctx ctx;
|
||||
|
||||
+ if (!tryget_task_struct(p))
|
||||
+ continue;
|
||||
+
|
||||
if (old_class != new_class && p->se.sched_delayed)
|
||||
dequeue_task(task_rq(p), p, DEQUEUE_SLEEP | DEQUEUE_DELAYED);
|
||||
|
||||
@@ -5706,6 +5709,7 @@ static int scx_enable(struct sched_ext_o
|
||||
sched_enq_and_set_task(&ctx);
|
||||
|
||||
check_class_changed(task_rq(p), p, old_class, p->prio);
|
||||
+ put_task_struct(p);
|
||||
}
|
||||
scx_task_iter_stop(&sti);
|
||||
percpu_up_write(&scx_fork_rwsem);
|
@@ -0,0 +1,39 @@
|
||||
From f64fb7c5338fde361fdaef01b98697a52ee8467b Mon Sep 17 00:00:00 2001
|
||||
From: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
|
||||
Date: Sun, 27 Jul 2025 14:05:13 -0700
|
||||
Subject: platform/x86/intel-uncore-freq: Check write blocked for ELC
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Add the missing write_blocked check for updating sysfs related to uncore
|
||||
efficiency latency control (ELC). If write operation is blocked return
|
||||
error.
|
||||
|
||||
Fixes: bb516dc79c4a ("platform/x86/intel-uncore-freq: Add support for efficiency latency control")
|
||||
Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
|
||||
Cc: stable@vger.kernel.org
|
||||
Link: https://lore.kernel.org/r/20250727210513.2898630-1-srinivas.pandruvada@linux.intel.com
|
||||
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
|
||||
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
|
||||
---
|
||||
.../x86/intel/uncore-frequency/uncore-frequency-tpmi.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
--- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
|
||||
+++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
|
||||
@@ -191,9 +191,14 @@ static int uncore_read_control_freq(stru
|
||||
static int write_eff_lat_ctrl(struct uncore_data *data, unsigned int val, enum uncore_index index)
|
||||
{
|
||||
struct tpmi_uncore_cluster_info *cluster_info;
|
||||
+ struct tpmi_uncore_struct *uncore_root;
|
||||
u64 control;
|
||||
|
||||
cluster_info = container_of(data, struct tpmi_uncore_cluster_info, uncore_data);
|
||||
+ uncore_root = cluster_info->uncore_root;
|
||||
+
|
||||
+ if (uncore_root->write_blocked)
|
||||
+ return -EPERM;
|
||||
|
||||
if (cluster_info->root_domain)
|
||||
return -ENODATA;
|
@@ -0,0 +1,28 @@
|
||||
From 882ab07bcf8574b1618863b6cd16200979cec30f Mon Sep 17 00:00:00 2001
|
||||
From: Miao Li <limiao@kylinos.cn>
|
||||
Date: Fri, 1 Aug 2025 16:27:28 +0800
|
||||
Subject: usb: quirks: Add DELAY_INIT quick for another SanDisk 3.2Gen1 Flash
|
||||
Drive
|
||||
|
||||
Another SanDisk 3.2Gen1 Flash Drive also need DELAY_INIT quick,
|
||||
or it will randomly work incorrectly on Huawei hisi platforms
|
||||
when doing reboot test.
|
||||
|
||||
Signed-off-by: Miao Li <limiao@kylinos.cn>
|
||||
Cc: stable <stable@kernel.org>
|
||||
Link: https://lore.kernel.org/r/20250801082728.469406-1-limiao870622@163.com
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/usb/core/quirks.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/drivers/usb/core/quirks.c
|
||||
+++ b/drivers/usb/core/quirks.c
|
||||
@@ -371,6 +371,7 @@ static const struct usb_device_id usb_qu
|
||||
{ USB_DEVICE(0x0781, 0x5591), .driver_info = USB_QUIRK_NO_LPM },
|
||||
|
||||
/* SanDisk Corp. SanDisk 3.2Gen1 */
|
||||
+ { USB_DEVICE(0x0781, 0x5596), .driver_info = USB_QUIRK_DELAY_INIT },
|
||||
{ USB_DEVICE(0x0781, 0x55a3), .driver_info = USB_QUIRK_DELAY_INIT },
|
||||
|
||||
/* SanDisk Extreme 55AE */
|
68
debian/patches/patchset-pf/steady/0046-usb-renesas-xhci-Fix-External-ROM-access-timeouts.patch
vendored
Normal file
68
debian/patches/patchset-pf/steady/0046-usb-renesas-xhci-Fix-External-ROM-access-timeouts.patch
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
From 024303e34931cae365cfeb28d00e3b9b704c1001 Mon Sep 17 00:00:00 2001
|
||||
From: Marek Vasut <marek.vasut+renesas@mailbox.org>
|
||||
Date: Sun, 3 Aug 2025 00:55:20 +0200
|
||||
Subject: usb: renesas-xhci: Fix External ROM access timeouts
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Increase the External ROM access timeouts to prevent failures during
|
||||
programming of External SPI EEPROM chips. The current timeouts are
|
||||
too short for some SPI EEPROMs used with uPD720201 controllers.
|
||||
|
||||
The current timeout for Chip Erase in renesas_rom_erase() is 100 ms ,
|
||||
the current timeout for Sector Erase issued by the controller before
|
||||
Page Program in renesas_fw_download_image() is also 100 ms. Neither
|
||||
timeout is sufficient for e.g. the Macronix MX25L5121E or MX25V5126F.
|
||||
|
||||
MX25L5121E reference manual [1] page 35 section "ERASE AND PROGRAMMING
|
||||
PERFORMANCE" and page 23 section "Table 8. AC CHARACTERISTICS (Temperature
|
||||
= 0°C to 70°C for Commercial grade, VCC = 2.7V ~ 3.6V)" row "tCE" indicate
|
||||
that the maximum time required for Chip Erase opcode to complete is 2 s,
|
||||
and for Sector Erase it is 300 ms .
|
||||
|
||||
MX25V5126F reference manual [2] page 47 section "13. ERASE AND PROGRAMMING
|
||||
PERFORMANCE (2.3V - 3.6V)" and page 42 section "Table 8. AC CHARACTERISTICS
|
||||
(Temperature = -40°C to 85°C for Industrial grade, VCC = 2.3V - 3.6V)" row
|
||||
"tCE" indicate that the maximum time required for Chip Erase opcode to
|
||||
complete is 3.2 s, and for Sector Erase it is 400 ms .
|
||||
|
||||
Update the timeouts such, that Chip Erase timeout is set to 5 seconds,
|
||||
and Sector Erase timeout is set to 500 ms. Such lengthy timeouts ought
|
||||
to be sufficient for majority of SPI EEPROM chips.
|
||||
|
||||
[1] https://www.macronix.com/Lists/Datasheet/Attachments/8634/MX25L5121E,%203V,%20512Kb,%20v1.3.pdf
|
||||
[2] https://www.macronix.com/Lists/Datasheet/Attachments/8750/MX25V5126F,%202.5V,%20512Kb,%20v1.1.pdf
|
||||
|
||||
Fixes: 2478be82de44 ("usb: renesas-xhci: Add ROM loader for uPD720201")
|
||||
Cc: stable <stable@kernel.org>
|
||||
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
|
||||
Link: https://lore.kernel.org/r/20250802225526.25431-1-marek.vasut+renesas@mailbox.org
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/usb/host/xhci-pci-renesas.c | 7 ++++---
|
||||
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/usb/host/xhci-pci-renesas.c
|
||||
+++ b/drivers/usb/host/xhci-pci-renesas.c
|
||||
@@ -47,8 +47,9 @@
|
||||
#define RENESAS_ROM_ERASE_MAGIC 0x5A65726F
|
||||
#define RENESAS_ROM_WRITE_MAGIC 0x53524F4D
|
||||
|
||||
-#define RENESAS_RETRY 10000
|
||||
-#define RENESAS_DELAY 10
|
||||
+#define RENESAS_RETRY 50000 /* 50000 * RENESAS_DELAY ~= 500ms */
|
||||
+#define RENESAS_CHIP_ERASE_RETRY 500000 /* 500000 * RENESAS_DELAY ~= 5s */
|
||||
+#define RENESAS_DELAY 10
|
||||
|
||||
#define RENESAS_FW_NAME "renesas_usb_fw.mem"
|
||||
|
||||
@@ -407,7 +408,7 @@ static void renesas_rom_erase(struct pci
|
||||
/* sleep a bit while ROM is erased */
|
||||
msleep(20);
|
||||
|
||||
- for (i = 0; i < RENESAS_RETRY; i++) {
|
||||
+ for (i = 0; i < RENESAS_CHIP_ERASE_RETRY; i++) {
|
||||
retval = pci_read_config_byte(pdev, RENESAS_ROM_STATUS,
|
||||
&status);
|
||||
status &= RENESAS_ROM_STATUS_ERASE;
|
@@ -0,0 +1,55 @@
|
||||
From ed08be11433715381e5a67569d2eadd9264523e0 Mon Sep 17 00:00:00 2001
|
||||
From: Xu Yang <xu.yang_2@nxp.com>
|
||||
Date: Wed, 6 Aug 2025 16:39:55 +0800
|
||||
Subject: usb: core: hcd: fix accessing unmapped memory in
|
||||
SINGLE_STEP_SET_FEATURE test
|
||||
|
||||
The USB core will unmap urb->transfer_dma after SETUP stage completes.
|
||||
Then the USB controller will access unmapped memory when it received
|
||||
device descriptor. If iommu is equipped, the entire test can't be
|
||||
completed due to the memory accessing is blocked.
|
||||
|
||||
Fix it by calling map_urb_for_dma() again for IN stage. To reduce
|
||||
redundant map for urb->transfer_buffer, this will also set
|
||||
URB_NO_TRANSFER_DMA_MAP flag before first map_urb_for_dma() to skip
|
||||
dma map for urb->transfer_buffer and clear URB_NO_TRANSFER_DMA_MAP
|
||||
flag before second map_urb_for_dma().
|
||||
|
||||
Fixes: 216e0e563d81 ("usb: core: hcd: use map_urb_for_dma for single step set feature urb")
|
||||
Cc: stable <stable@kernel.org>
|
||||
Reviewed-by: Jun Li <jun.li@nxp.com>
|
||||
Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
|
||||
Acked-by: Alan Stern <stern@rowland.harvard.edu>
|
||||
Link: https://lore.kernel.org/r/20250806083955.3325299-1-xu.yang_2@nxp.com
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/usb/core/hcd.c | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/usb/core/hcd.c
|
||||
+++ b/drivers/usb/core/hcd.c
|
||||
@@ -2153,7 +2153,7 @@ static struct urb *request_single_step_s
|
||||
urb->complete = usb_ehset_completion;
|
||||
urb->status = -EINPROGRESS;
|
||||
urb->actual_length = 0;
|
||||
- urb->transfer_flags = URB_DIR_IN;
|
||||
+ urb->transfer_flags = URB_DIR_IN | URB_NO_TRANSFER_DMA_MAP;
|
||||
usb_get_urb(urb);
|
||||
atomic_inc(&urb->use_count);
|
||||
atomic_inc(&urb->dev->urbnum);
|
||||
@@ -2217,9 +2217,15 @@ int ehset_single_step_set_feature(struct
|
||||
|
||||
/* Complete remaining DATA and STATUS stages using the same URB */
|
||||
urb->status = -EINPROGRESS;
|
||||
+ urb->transfer_flags &= ~URB_NO_TRANSFER_DMA_MAP;
|
||||
usb_get_urb(urb);
|
||||
atomic_inc(&urb->use_count);
|
||||
atomic_inc(&urb->dev->urbnum);
|
||||
+ if (map_urb_for_dma(hcd, urb, GFP_KERNEL)) {
|
||||
+ usb_put_urb(urb);
|
||||
+ goto out1;
|
||||
+ }
|
||||
+
|
||||
retval = hcd->driver->submit_single_step_set_feature(hcd, urb, 0);
|
||||
if (!retval && !wait_for_completion_timeout(&done,
|
||||
msecs_to_jiffies(2000))) {
|
@@ -0,0 +1,51 @@
|
||||
From 10e48c1c6c772eb9c6754dd2340843fe264f71f8 Mon Sep 17 00:00:00 2001
|
||||
From: Mael GUERIN <mael.guerin@murena.io>
|
||||
Date: Wed, 6 Aug 2025 18:44:03 +0200
|
||||
Subject: USB: storage: Add unusual-devs entry for Novatek NTK96550-based
|
||||
camera
|
||||
|
||||
Add the US_FL_BULK_IGNORE_TAG quirk for Novatek NTK96550-based camera
|
||||
to fix USB resets after sending SCSI vendor commands due to CBW and
|
||||
CSW tags difference, leading to undesired slowness while communicating
|
||||
with the device.
|
||||
|
||||
Please find below the copy of /sys/kernel/debug/usb/devices with my
|
||||
device plugged in (listed as TechSys USB mass storage here, the
|
||||
underlying chipset being the Novatek NTK96550-based camera):
|
||||
|
||||
T: Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 3 Spd=480 MxCh= 0
|
||||
D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1
|
||||
P: Vendor=0603 ProdID=8611 Rev= 0.01
|
||||
S: Manufacturer=TechSys
|
||||
S: Product=USB Mass Storage
|
||||
S: SerialNumber=966110000000100
|
||||
C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr=100mA
|
||||
I:* If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage
|
||||
E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
|
||||
E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
|
||||
|
||||
Signed-off-by: Mael GUERIN <mael.guerin@murena.io>
|
||||
Cc: stable <stable@kernel.org>
|
||||
Acked-by: Alan Stern <stern@rowland.harvard.edu>
|
||||
Link: https://lore.kernel.org/r/20250806164406.43450-1-mael.guerin@murena.io
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/usb/storage/unusual_devs.h | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
--- a/drivers/usb/storage/unusual_devs.h
|
||||
+++ b/drivers/usb/storage/unusual_devs.h
|
||||
@@ -934,6 +934,13 @@ UNUSUAL_DEV( 0x05e3, 0x0723, 0x9451, 0x
|
||||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
US_FL_SANE_SENSE ),
|
||||
|
||||
+/* Added by Maël GUERIN <mael.guerin@murena.io> */
|
||||
+UNUSUAL_DEV( 0x0603, 0x8611, 0x0000, 0xffff,
|
||||
+ "Novatek",
|
||||
+ "NTK96550-based camera",
|
||||
+ USB_SC_SCSI, USB_PR_BULK, NULL,
|
||||
+ US_FL_BULK_IGNORE_TAG ),
|
||||
+
|
||||
/*
|
||||
* Reported by Hanno Boeck <hanno@gmx.de>
|
||||
* Taken from the Lycoris Kernel
|
@@ -0,0 +1,42 @@
|
||||
From c6c200e7836ff1b131442200096a8fd14c600165 Mon Sep 17 00:00:00 2001
|
||||
From: Kuen-Han Tsai <khtsai@google.com>
|
||||
Date: Thu, 7 Aug 2025 17:06:55 +0800
|
||||
Subject: usb: dwc3: Ignore late xferNotReady event to prevent halt timeout
|
||||
|
||||
During a device-initiated disconnect, the End Transfer command resets
|
||||
the event filter, allowing a new xferNotReady event to be generated
|
||||
before the controller is fully halted. Processing this late event
|
||||
incorrectly triggers a Start Transfer, which prevents the controller
|
||||
from halting and results in a DSTS.DEVCTLHLT bit polling timeout.
|
||||
|
||||
Ignore the late xferNotReady event if the controller is already in a
|
||||
disconnected state.
|
||||
|
||||
Fixes: 72246da40f37 ("usb: Introduce DesignWare USB3 DRD Driver")
|
||||
Cc: stable <stable@kernel.org>
|
||||
Signed-off-by: Kuen-Han Tsai <khtsai@google.com>
|
||||
Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
|
||||
Link: https://lore.kernel.org/r/20250807090700.2397190-1-khtsai@google.com
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/usb/dwc3/gadget.c | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
--- a/drivers/usb/dwc3/gadget.c
|
||||
+++ b/drivers/usb/dwc3/gadget.c
|
||||
@@ -3779,6 +3779,15 @@ static void dwc3_gadget_endpoint_transfe
|
||||
static void dwc3_gadget_endpoint_transfer_not_ready(struct dwc3_ep *dep,
|
||||
const struct dwc3_event_depevt *event)
|
||||
{
|
||||
+ /*
|
||||
+ * During a device-initiated disconnect, a late xferNotReady event can
|
||||
+ * be generated after the End Transfer command resets the event filter,
|
||||
+ * but before the controller is halted. Ignore it to prevent a new
|
||||
+ * transfer from starting.
|
||||
+ */
|
||||
+ if (!dep->dwc->connected)
|
||||
+ return;
|
||||
+
|
||||
dwc3_gadget_endpoint_frame_from_event(dep, event);
|
||||
|
||||
/*
|
34
debian/patches/patchset-pf/steady/0050-usb-dwc3-pci-add-support-for-the-Intel-Wildcat-Lake.patch
vendored
Normal file
34
debian/patches/patchset-pf/steady/0050-usb-dwc3-pci-add-support-for-the-Intel-Wildcat-Lake.patch
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
From 50d8ed950819f18b60b2eaa7121e16cfb2dd16eb Mon Sep 17 00:00:00 2001
|
||||
From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
|
||||
Date: Tue, 12 Aug 2025 16:11:00 +0300
|
||||
Subject: usb: dwc3: pci: add support for the Intel Wildcat Lake
|
||||
|
||||
This patch adds the necessary PCI ID for Intel Wildcat Lake
|
||||
devices.
|
||||
|
||||
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
|
||||
Cc: stable <stable@kernel.org>
|
||||
Link: https://lore.kernel.org/r/20250812131101.2930199-1-heikki.krogerus@linux.intel.com
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/usb/dwc3/dwc3-pci.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- a/drivers/usb/dwc3/dwc3-pci.c
|
||||
+++ b/drivers/usb/dwc3/dwc3-pci.c
|
||||
@@ -41,6 +41,7 @@
|
||||
#define PCI_DEVICE_ID_INTEL_TGPLP 0xa0ee
|
||||
#define PCI_DEVICE_ID_INTEL_TGPH 0x43ee
|
||||
#define PCI_DEVICE_ID_INTEL_JSP 0x4dee
|
||||
+#define PCI_DEVICE_ID_INTEL_WCL 0x4d7e
|
||||
#define PCI_DEVICE_ID_INTEL_ADL 0x460e
|
||||
#define PCI_DEVICE_ID_INTEL_ADL_PCH 0x51ee
|
||||
#define PCI_DEVICE_ID_INTEL_ADLN 0x465e
|
||||
@@ -431,6 +432,7 @@ static const struct pci_device_id dwc3_p
|
||||
{ PCI_DEVICE_DATA(INTEL, TGPLP, &dwc3_pci_intel_swnode) },
|
||||
{ PCI_DEVICE_DATA(INTEL, TGPH, &dwc3_pci_intel_swnode) },
|
||||
{ PCI_DEVICE_DATA(INTEL, JSP, &dwc3_pci_intel_swnode) },
|
||||
+ { PCI_DEVICE_DATA(INTEL, WCL, &dwc3_pci_intel_swnode) },
|
||||
{ PCI_DEVICE_DATA(INTEL, ADL, &dwc3_pci_intel_swnode) },
|
||||
{ PCI_DEVICE_DATA(INTEL, ADL_PCH, &dwc3_pci_intel_swnode) },
|
||||
{ PCI_DEVICE_DATA(INTEL, ADLN, &dwc3_pci_intel_swnode) },
|
@@ -0,0 +1,31 @@
|
||||
From 3417b55b75b1ca1003f6a621c77b751958727729 Mon Sep 17 00:00:00 2001
|
||||
From: Thorsten Blum <thorsten.blum@linux.dev>
|
||||
Date: Wed, 13 Aug 2025 16:52:49 +0200
|
||||
Subject: usb: storage: realtek_cr: Use correct byte order for bcs->Residue
|
||||
|
||||
Since 'bcs->Residue' has the data type '__le32', convert it to the
|
||||
correct byte order of the CPU using this driver when assigning it to
|
||||
the local variable 'residue'.
|
||||
|
||||
Cc: stable <stable@kernel.org>
|
||||
Fixes: 50a6cb932d5c ("USB: usb_storage: add ums-realtek driver")
|
||||
Suggested-by: Alan Stern <stern@rowland.harvard.edu>
|
||||
Acked-by: Alan Stern <stern@rowland.harvard.edu>
|
||||
Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
|
||||
Link: https://lore.kernel.org/r/20250813145247.184717-3-thorsten.blum@linux.dev
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/usb/storage/realtek_cr.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/usb/storage/realtek_cr.c
|
||||
+++ b/drivers/usb/storage/realtek_cr.c
|
||||
@@ -252,7 +252,7 @@ static int rts51x_bulk_transport(struct
|
||||
return USB_STOR_TRANSPORT_ERROR;
|
||||
}
|
||||
|
||||
- residue = bcs->Residue;
|
||||
+ residue = le32_to_cpu(bcs->Residue);
|
||||
if (bcs->Tag != us->tag)
|
||||
return USB_STOR_TRANSPORT_ERROR;
|
||||
|
57
debian/patches/patchset-pf/steady/0052-ata-libata-scsi-Fix-CDL-control.patch
vendored
Normal file
57
debian/patches/patchset-pf/steady/0052-ata-libata-scsi-Fix-CDL-control.patch
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
From a9cbad46c051cf4467ba13638eddc86f96354c66 Mon Sep 17 00:00:00 2001
|
||||
From: Igor Pylypiv <ipylypiv@google.com>
|
||||
Date: Wed, 13 Aug 2025 19:22:56 -0700
|
||||
Subject: ata: libata-scsi: Fix CDL control
|
||||
|
||||
Delete extra checks for the ATA_DFLAG_CDL_ENABLED flag that prevent
|
||||
SET FEATURES command from being issued to a drive when NCQ commands
|
||||
are active.
|
||||
|
||||
ata_mselect_control_ata_feature() sets / clears the ATA_DFLAG_CDL_ENABLED
|
||||
flag during the translation of MODE SELECT to SET FEATURES. If SET FEATURES
|
||||
gets deferred due to outstanding NCQ commands, the original MODE SELECT
|
||||
command will be re-queued. When the re-queued MODE SELECT goes through
|
||||
the ata_mselect_control_ata_feature() translation again, SET FEATURES
|
||||
will not be issued because ATA_DFLAG_CDL_ENABLED has been already set or
|
||||
cleared by the initial translation of MODE SELECT.
|
||||
|
||||
The ATA_DFLAG_CDL_ENABLED checks in ata_mselect_control_ata_feature()
|
||||
are safe to remove because scsi_cdl_enable() implements a similar logic
|
||||
that avoids enabling CDL if it has been enabled already.
|
||||
|
||||
Fixes: 17e897a45675 ("ata: libata-scsi: Improve CDL control")
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Igor Pylypiv <ipylypiv@google.com>
|
||||
Reviewed-by: Niklas Cassel <cassel@kernel.org>
|
||||
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
|
||||
---
|
||||
drivers/ata/libata-scsi.c | 11 +++--------
|
||||
1 file changed, 3 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/ata/libata-scsi.c
|
||||
+++ b/drivers/ata/libata-scsi.c
|
||||
@@ -3905,21 +3905,16 @@ static int ata_mselect_control_ata_featu
|
||||
/* Check cdl_ctrl */
|
||||
switch (buf[0] & 0x03) {
|
||||
case 0:
|
||||
- /* Disable CDL if it is enabled */
|
||||
- if (!(dev->flags & ATA_DFLAG_CDL_ENABLED))
|
||||
- return 0;
|
||||
+ /* Disable CDL */
|
||||
ata_dev_dbg(dev, "Disabling CDL\n");
|
||||
cdl_action = 0;
|
||||
dev->flags &= ~ATA_DFLAG_CDL_ENABLED;
|
||||
break;
|
||||
case 0x02:
|
||||
/*
|
||||
- * Enable CDL if not already enabled. Since this is mutually
|
||||
- * exclusive with NCQ priority, allow this only if NCQ priority
|
||||
- * is disabled.
|
||||
+ * Enable CDL. Since CDL is mutually exclusive with NCQ
|
||||
+ * priority, allow this only if NCQ priority is disabled.
|
||||
*/
|
||||
- if (dev->flags & ATA_DFLAG_CDL_ENABLED)
|
||||
- return 0;
|
||||
if (dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLED) {
|
||||
ata_dev_err(dev,
|
||||
"NCQ priority must be disabled to enable CDL\n");
|
158
debian/patches/patchset-pf/steady/0053-netfs-Fix-unbuffered-write-error-handling.patch
vendored
Normal file
158
debian/patches/patchset-pf/steady/0053-netfs-Fix-unbuffered-write-error-handling.patch
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
From c9cb314a4e57bc486a8b563dd6df5f6975b97a2f Mon Sep 17 00:00:00 2001
|
||||
From: David Howells <dhowells@redhat.com>
|
||||
Date: Thu, 14 Aug 2025 22:45:50 +0100
|
||||
Subject: netfs: Fix unbuffered write error handling
|
||||
|
||||
If all the subrequests in an unbuffered write stream fail, the subrequest
|
||||
collector doesn't update the stream->transferred value and it retains its
|
||||
initial LONG_MAX value. Unfortunately, if all active streams fail, then we
|
||||
take the smallest value of { LONG_MAX, LONG_MAX, ... } as the value to set
|
||||
in wreq->transferred - which is then returned from ->write_iter().
|
||||
|
||||
LONG_MAX was chosen as the initial value so that all the streams can be
|
||||
quickly assessed by taking the smallest value of all stream->transferred -
|
||||
but this only works if we've set any of them.
|
||||
|
||||
Fix this by adding a flag to indicate whether the value in
|
||||
stream->transferred is valid and checking that when we integrate the
|
||||
values. stream->transferred can then be initialised to zero.
|
||||
|
||||
This was found by running the generic/750 xfstest against cifs with
|
||||
cache=none. It splices data to the target file. Once (if) it has used up
|
||||
all the available scratch space, the writes start failing with ENOSPC.
|
||||
This causes ->write_iter() to fail. However, it was returning
|
||||
wreq->transferred, i.e. LONG_MAX, rather than an error (because it thought
|
||||
the amount transferred was non-zero) and iter_file_splice_write() would
|
||||
then try to clean up that amount of pipe bufferage - leading to an oops
|
||||
when it overran. The kernel log showed:
|
||||
|
||||
CIFS: VFS: Send error in write = -28
|
||||
|
||||
followed by:
|
||||
|
||||
BUG: kernel NULL pointer dereference, address: 0000000000000008
|
||||
|
||||
with:
|
||||
|
||||
RIP: 0010:iter_file_splice_write+0x3a4/0x520
|
||||
do_splice+0x197/0x4e0
|
||||
|
||||
or:
|
||||
|
||||
RIP: 0010:pipe_buf_release (include/linux/pipe_fs_i.h:282)
|
||||
iter_file_splice_write (fs/splice.c:755)
|
||||
|
||||
Also put a warning check into splice to announce if ->write_iter() returned
|
||||
that it had written more than it was asked to.
|
||||
|
||||
Fixes: 288ace2f57c9 ("netfs: New writeback implementation")
|
||||
Reported-by: Xiaoli Feng <fengxiaoli0714@gmail.com>
|
||||
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220445
|
||||
Signed-off-by: David Howells <dhowells@redhat.com>
|
||||
Link: https://lore.kernel.org/915443.1755207950@warthog.procyon.org.uk
|
||||
cc: Paulo Alcantara <pc@manguebit.org>
|
||||
cc: Steve French <sfrench@samba.org>
|
||||
cc: Shyam Prasad N <sprasad@microsoft.com>
|
||||
cc: netfs@lists.linux.dev
|
||||
cc: linux-cifs@vger.kernel.org
|
||||
cc: linux-fsdevel@vger.kernel.org
|
||||
cc: stable@vger.kernel.org
|
||||
Signed-off-by: Christian Brauner <brauner@kernel.org>
|
||||
---
|
||||
fs/netfs/read_collect.c | 4 +++-
|
||||
fs/netfs/write_collect.c | 10 ++++++++--
|
||||
fs/netfs/write_issue.c | 4 ++--
|
||||
fs/splice.c | 3 +++
|
||||
include/linux/netfs.h | 1 +
|
||||
5 files changed, 17 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/fs/netfs/read_collect.c
|
||||
+++ b/fs/netfs/read_collect.c
|
||||
@@ -281,8 +281,10 @@ reassess:
|
||||
} else if (test_bit(NETFS_RREQ_SHORT_TRANSFER, &rreq->flags)) {
|
||||
notes |= MADE_PROGRESS;
|
||||
} else {
|
||||
- if (!stream->failed)
|
||||
+ if (!stream->failed) {
|
||||
stream->transferred += transferred;
|
||||
+ stream->transferred_valid = true;
|
||||
+ }
|
||||
if (front->transferred < front->len)
|
||||
set_bit(NETFS_RREQ_SHORT_TRANSFER, &rreq->flags);
|
||||
notes |= MADE_PROGRESS;
|
||||
--- a/fs/netfs/write_collect.c
|
||||
+++ b/fs/netfs/write_collect.c
|
||||
@@ -254,6 +254,7 @@ reassess_streams:
|
||||
if (front->start + front->transferred > stream->collected_to) {
|
||||
stream->collected_to = front->start + front->transferred;
|
||||
stream->transferred = stream->collected_to - wreq->start;
|
||||
+ stream->transferred_valid = true;
|
||||
notes |= MADE_PROGRESS;
|
||||
}
|
||||
if (test_bit(NETFS_SREQ_FAILED, &front->flags)) {
|
||||
@@ -356,6 +357,7 @@ bool netfs_write_collection(struct netfs
|
||||
{
|
||||
struct netfs_inode *ictx = netfs_inode(wreq->inode);
|
||||
size_t transferred;
|
||||
+ bool transferred_valid = false;
|
||||
int s;
|
||||
|
||||
_enter("R=%x", wreq->debug_id);
|
||||
@@ -376,12 +378,16 @@ bool netfs_write_collection(struct netfs
|
||||
continue;
|
||||
if (!list_empty(&stream->subrequests))
|
||||
return false;
|
||||
- if (stream->transferred < transferred)
|
||||
+ if (stream->transferred_valid &&
|
||||
+ stream->transferred < transferred) {
|
||||
transferred = stream->transferred;
|
||||
+ transferred_valid = true;
|
||||
+ }
|
||||
}
|
||||
|
||||
/* Okay, declare that all I/O is complete. */
|
||||
- wreq->transferred = transferred;
|
||||
+ if (transferred_valid)
|
||||
+ wreq->transferred = transferred;
|
||||
trace_netfs_rreq(wreq, netfs_rreq_trace_write_done);
|
||||
|
||||
if (wreq->io_streams[1].active &&
|
||||
--- a/fs/netfs/write_issue.c
|
||||
+++ b/fs/netfs/write_issue.c
|
||||
@@ -118,12 +118,12 @@ struct netfs_io_request *netfs_create_wr
|
||||
wreq->io_streams[0].prepare_write = ictx->ops->prepare_write;
|
||||
wreq->io_streams[0].issue_write = ictx->ops->issue_write;
|
||||
wreq->io_streams[0].collected_to = start;
|
||||
- wreq->io_streams[0].transferred = LONG_MAX;
|
||||
+ wreq->io_streams[0].transferred = 0;
|
||||
|
||||
wreq->io_streams[1].stream_nr = 1;
|
||||
wreq->io_streams[1].source = NETFS_WRITE_TO_CACHE;
|
||||
wreq->io_streams[1].collected_to = start;
|
||||
- wreq->io_streams[1].transferred = LONG_MAX;
|
||||
+ wreq->io_streams[1].transferred = 0;
|
||||
if (fscache_resources_valid(&wreq->cache_resources)) {
|
||||
wreq->io_streams[1].avail = true;
|
||||
wreq->io_streams[1].active = true;
|
||||
--- a/fs/splice.c
|
||||
+++ b/fs/splice.c
|
||||
@@ -739,6 +739,9 @@ iter_file_splice_write(struct pipe_inode
|
||||
sd.pos = kiocb.ki_pos;
|
||||
if (ret <= 0)
|
||||
break;
|
||||
+ WARN_ONCE(ret > sd.total_len - left,
|
||||
+ "Splice Exceeded! ret=%zd tot=%zu left=%zu\n",
|
||||
+ ret, sd.total_len, left);
|
||||
|
||||
sd.num_spliced += ret;
|
||||
sd.total_len -= ret;
|
||||
--- a/include/linux/netfs.h
|
||||
+++ b/include/linux/netfs.h
|
||||
@@ -150,6 +150,7 @@ struct netfs_io_stream {
|
||||
bool active; /* T if stream is active */
|
||||
bool need_retry; /* T if this stream needs retrying */
|
||||
bool failed; /* T if this stream failed */
|
||||
+ bool transferred_valid; /* T is ->transferred is valid */
|
||||
};
|
||||
|
||||
/*
|
@@ -0,0 +1,29 @@
|
||||
From 53abd849fe02d16ae158b4f5f7264c761871089f Mon Sep 17 00:00:00 2001
|
||||
From: Evgeniy Harchenko <evgeniyharchenko.dev@gmail.com>
|
||||
Date: Fri, 15 Aug 2025 12:58:14 +0300
|
||||
Subject: ALSA: hda/realtek: Add support for HP EliteBook x360 830 G6 and
|
||||
EliteBook 830 G6
|
||||
|
||||
The HP EliteBook x360 830 G6 and HP EliteBook 830 G6 have
|
||||
Realtek HDA codec ALC215. It needs the ALC285_FIXUP_HP_GPIO_LED
|
||||
quirk to enable the mute LED.
|
||||
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Signed-off-by: Evgeniy Harchenko <evgeniyharchenko.dev@gmail.com>
|
||||
Link: https://patch.msgid.link/20250815095814.75845-1-evgeniyharchenko.dev@gmail.com
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
sound/pci/hda/patch_realtek.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- a/sound/pci/hda/patch_realtek.c
|
||||
+++ b/sound/pci/hda/patch_realtek.c
|
||||
@@ -10662,6 +10662,8 @@ static const struct hda_quirk alc269_fix
|
||||
SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
|
||||
SND_PCI_QUIRK(0x103c, 0x8519, "HP Spectre x360 15-df0xxx", ALC285_FIXUP_HP_SPECTRE_X360),
|
||||
SND_PCI_QUIRK(0x103c, 0x8537, "HP ProBook 440 G6", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
|
||||
+ SND_PCI_QUIRK(0x103c, 0x8548, "HP EliteBook x360 830 G6", ALC285_FIXUP_HP_GPIO_LED),
|
||||
+ SND_PCI_QUIRK(0x103c, 0x854a, "HP EliteBook 830 G6", ALC285_FIXUP_HP_GPIO_LED),
|
||||
SND_PCI_QUIRK(0x103c, 0x85c6, "HP Pavilion x360 Convertible 14-dy1xxx", ALC295_FIXUP_HP_MUTE_LED_COEFBIT11),
|
||||
SND_PCI_QUIRK(0x103c, 0x85de, "HP Envy x360 13-ar0xxx", ALC285_FIXUP_HP_ENVY_X360),
|
||||
SND_PCI_QUIRK(0x103c, 0x860f, "HP ZBook 15 G6", ALC285_FIXUP_HP_GPIO_AMP_INIT),
|
@@ -0,0 +1,76 @@
|
||||
From 23b7b20948f48844f17030dab3b1e556f37c803a Mon Sep 17 00:00:00 2001
|
||||
From: Zenm Chen <zenmchen@gmail.com>
|
||||
Date: Thu, 14 Aug 2025 00:24:15 +0800
|
||||
Subject: USB: storage: Ignore driver CD mode for Realtek multi-mode Wi-Fi
|
||||
dongles
|
||||
|
||||
Many Realtek USB Wi-Fi dongles released in recent years have two modes:
|
||||
one is driver CD mode which has Windows driver onboard, another one is
|
||||
Wi-Fi mode. Add the US_FL_IGNORE_DEVICE quirk for these multi-mode devices.
|
||||
Otherwise, usb_modeswitch may fail to switch them to Wi-Fi mode.
|
||||
|
||||
Currently there are only two USB IDs known to be used by these multi-mode
|
||||
Wi-Fi dongles: 0bda:1a2b and 0bda:a192.
|
||||
|
||||
Information about Mercury MW310UH in /sys/kernel/debug/usb/devices.
|
||||
T: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 12 Spd=480 MxCh= 0
|
||||
D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1
|
||||
P: Vendor=0bda ProdID=a192 Rev= 2.00
|
||||
S: Manufacturer=Realtek
|
||||
S: Product=DISK
|
||||
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=500mA
|
||||
I:* If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=(none)
|
||||
E: Ad=8a(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
|
||||
E: Ad=0b(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
|
||||
|
||||
Information about D-Link AX9U rev. A1 in /sys/kernel/debug/usb/devices.
|
||||
T: Bus=03 Lev=01 Prnt=01 Port=02 Cnt=01 Dev#= 55 Spd=480 MxCh= 0
|
||||
D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1
|
||||
P: Vendor=0bda ProdID=1a2b Rev= 0.00
|
||||
S: Manufacturer=Realtek
|
||||
S: Product=DISK
|
||||
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=500mA
|
||||
I:* If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=(none)
|
||||
E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
|
||||
E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
|
||||
|
||||
Cc: stable <stable@kernel.org>
|
||||
Signed-off-by: Zenm Chen <zenmchen@gmail.com>
|
||||
Acked-by: Alan Stern <stern@rowland.harvard.edu>
|
||||
Link: https://lore.kernel.org/r/20250813162415.2630-1-zenmchen@gmail.com
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/usb/storage/unusual_devs.h | 22 ++++++++++++++++++++++
|
||||
1 file changed, 22 insertions(+)
|
||||
|
||||
--- a/drivers/usb/storage/unusual_devs.h
|
||||
+++ b/drivers/usb/storage/unusual_devs.h
|
||||
@@ -1501,6 +1501,28 @@ UNUSUAL_DEV( 0x0bc2, 0x3332, 0x0000, 0x9
|
||||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
US_FL_NO_WP_DETECT ),
|
||||
|
||||
+/*
|
||||
+ * Reported by Zenm Chen <zenmchen@gmail.com>
|
||||
+ * Ignore driver CD mode, otherwise usb_modeswitch may fail to switch
|
||||
+ * the device into Wi-Fi mode.
|
||||
+ */
|
||||
+UNUSUAL_DEV( 0x0bda, 0x1a2b, 0x0000, 0xffff,
|
||||
+ "Realtek",
|
||||
+ "DISK",
|
||||
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
+ US_FL_IGNORE_DEVICE ),
|
||||
+
|
||||
+/*
|
||||
+ * Reported by Zenm Chen <zenmchen@gmail.com>
|
||||
+ * Ignore driver CD mode, otherwise usb_modeswitch may fail to switch
|
||||
+ * the device into Wi-Fi mode.
|
||||
+ */
|
||||
+UNUSUAL_DEV( 0x0bda, 0xa192, 0x0000, 0xffff,
|
||||
+ "Realtek",
|
||||
+ "DISK",
|
||||
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
+ US_FL_IGNORE_DEVICE ),
|
||||
+
|
||||
UNUSUAL_DEV( 0x0d49, 0x7310, 0x0000, 0x9999,
|
||||
"Maxtor",
|
||||
"USB to SATA",
|
129
debian/patches/patchset-pf/steady/0056-usb-dwc3-Remove-WARN_ON-for-device-endpoint-command-.patch
vendored
Normal file
129
debian/patches/patchset-pf/steady/0056-usb-dwc3-Remove-WARN_ON-for-device-endpoint-command-.patch
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
From fc0576dcffc4ec82e728efe8bb3e3e753151fde0 Mon Sep 17 00:00:00 2001
|
||||
From: Selvarasu Ganesan <selvarasu.g@samsung.com>
|
||||
Date: Fri, 8 Aug 2025 18:23:05 +0530
|
||||
Subject: usb: dwc3: Remove WARN_ON for device endpoint command timeouts
|
||||
|
||||
This commit addresses a rarely observed endpoint command timeout
|
||||
which causes kernel panic due to warn when 'panic_on_warn' is enabled
|
||||
and unnecessary call trace prints when 'panic_on_warn' is disabled.
|
||||
It is seen during fast software-controlled connect/disconnect testcases.
|
||||
The following is one such endpoint command timeout that we observed:
|
||||
|
||||
1. Connect
|
||||
=======
|
||||
->dwc3_thread_interrupt
|
||||
->dwc3_ep0_interrupt
|
||||
->configfs_composite_setup
|
||||
->composite_setup
|
||||
->usb_ep_queue
|
||||
->dwc3_gadget_ep0_queue
|
||||
->__dwc3_gadget_ep0_queue
|
||||
->__dwc3_ep0_do_control_data
|
||||
->dwc3_send_gadget_ep_cmd
|
||||
|
||||
2. Disconnect
|
||||
==========
|
||||
->dwc3_thread_interrupt
|
||||
->dwc3_gadget_disconnect_interrupt
|
||||
->dwc3_ep0_reset_state
|
||||
->dwc3_ep0_end_control_data
|
||||
->dwc3_send_gadget_ep_cmd
|
||||
|
||||
In the issue scenario, in Exynos platforms, we observed that control
|
||||
transfers for the previous connect have not yet been completed and end
|
||||
transfer command sent as a part of the disconnect sequence and
|
||||
processing of USB_ENDPOINT_HALT feature request from the host timeout.
|
||||
This maybe an expected scenario since the controller is processing EP
|
||||
commands sent as a part of the previous connect. It maybe better to
|
||||
remove WARN_ON in all places where device endpoint commands are sent to
|
||||
avoid unnecessary kernel panic due to warn.
|
||||
|
||||
Cc: stable <stable@kernel.org>
|
||||
Co-developed-by: Akash M <akash.m5@samsung.com>
|
||||
Signed-off-by: Akash M <akash.m5@samsung.com>
|
||||
Signed-off-by: Selvarasu Ganesan <selvarasu.g@samsung.com>
|
||||
Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
|
||||
Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
||||
Link: https://lore.kernel.org/r/20250808125315.1607-1-selvarasu.g@samsung.com
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/usb/dwc3/ep0.c | 20 ++++++++++++++++----
|
||||
drivers/usb/dwc3/gadget.c | 10 ++++++++--
|
||||
2 files changed, 24 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/usb/dwc3/ep0.c
|
||||
+++ b/drivers/usb/dwc3/ep0.c
|
||||
@@ -288,7 +288,9 @@ void dwc3_ep0_out_start(struct dwc3 *dwc
|
||||
dwc3_ep0_prepare_one_trb(dep, dwc->ep0_trb_addr, 8,
|
||||
DWC3_TRBCTL_CONTROL_SETUP, false);
|
||||
ret = dwc3_ep0_start_trans(dep);
|
||||
- WARN_ON(ret < 0);
|
||||
+ if (ret < 0)
|
||||
+ dev_err(dwc->dev, "ep0 out start transfer failed: %d\n", ret);
|
||||
+
|
||||
for (i = 2; i < DWC3_ENDPOINTS_NUM; i++) {
|
||||
struct dwc3_ep *dwc3_ep;
|
||||
|
||||
@@ -1061,7 +1063,9 @@ static void __dwc3_ep0_do_control_data(s
|
||||
ret = dwc3_ep0_start_trans(dep);
|
||||
}
|
||||
|
||||
- WARN_ON(ret < 0);
|
||||
+ if (ret < 0)
|
||||
+ dev_err(dwc->dev,
|
||||
+ "ep0 data phase start transfer failed: %d\n", ret);
|
||||
}
|
||||
|
||||
static int dwc3_ep0_start_control_status(struct dwc3_ep *dep)
|
||||
@@ -1078,7 +1082,12 @@ static int dwc3_ep0_start_control_status
|
||||
|
||||
static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep)
|
||||
{
|
||||
- WARN_ON(dwc3_ep0_start_control_status(dep));
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = dwc3_ep0_start_control_status(dep);
|
||||
+ if (ret)
|
||||
+ dev_err(dwc->dev,
|
||||
+ "ep0 status phase start transfer failed: %d\n", ret);
|
||||
}
|
||||
|
||||
static void dwc3_ep0_do_control_status(struct dwc3 *dwc,
|
||||
@@ -1121,7 +1130,10 @@ void dwc3_ep0_end_control_data(struct dw
|
||||
cmd |= DWC3_DEPCMD_PARAM(dep->resource_index);
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms);
|
||||
- WARN_ON_ONCE(ret);
|
||||
+ if (ret)
|
||||
+ dev_err_ratelimited(dwc->dev,
|
||||
+ "ep0 data phase end transfer failed: %d\n", ret);
|
||||
+
|
||||
dep->resource_index = 0;
|
||||
}
|
||||
|
||||
--- a/drivers/usb/dwc3/gadget.c
|
||||
+++ b/drivers/usb/dwc3/gadget.c
|
||||
@@ -1774,7 +1774,11 @@ static int __dwc3_stop_active_transfer(s
|
||||
dep->flags |= DWC3_EP_DELAY_STOP;
|
||||
return 0;
|
||||
}
|
||||
- WARN_ON_ONCE(ret);
|
||||
+
|
||||
+ if (ret)
|
||||
+ dev_err_ratelimited(dep->dwc->dev,
|
||||
+ "end transfer failed: %d\n", ret);
|
||||
+
|
||||
dep->resource_index = 0;
|
||||
|
||||
if (!interrupt)
|
||||
@@ -4050,7 +4054,9 @@ static void dwc3_clear_stall_all_ep(stru
|
||||
dep->flags &= ~DWC3_EP_STALL;
|
||||
|
||||
ret = dwc3_send_clear_stall_ep_cmd(dep);
|
||||
- WARN_ON_ONCE(ret);
|
||||
+ if (ret)
|
||||
+ dev_err_ratelimited(dwc->dev,
|
||||
+ "failed to clear STALL on %s\n", dep->name);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,51 @@
|
||||
From ce921c8404b2574fe419d3c0efee185b4a951d70 Mon Sep 17 00:00:00 2001
|
||||
From: Amit Sunil Dhamne <amitsd@google.com>
|
||||
Date: Fri, 15 Aug 2025 11:31:51 -0700
|
||||
Subject: usb: typec: maxim_contaminant: disable low power mode when reading
|
||||
comparator values
|
||||
|
||||
Low power mode is enabled when reading CC resistance as part of
|
||||
`max_contaminant_read_resistance_kohm()` and left in that state.
|
||||
However, it's supposed to work with 1uA current source. To read CC
|
||||
comparator values current source is changed to 80uA. This causes a storm
|
||||
of CC interrupts as it (falsely) detects a potential contaminant. To
|
||||
prevent this, disable low power mode current sourcing before reading
|
||||
comparator values.
|
||||
|
||||
Fixes: 02b332a06397 ("usb: typec: maxim_contaminant: Implement check_contaminant callback")
|
||||
Cc: stable <stable@kernel.org>
|
||||
Signed-off-by: Amit Sunil Dhamne <amitsd@google.com>
|
||||
Reviewed-by: Badhri Jagan Sridharan <badhri@google.com>
|
||||
Rule: add
|
||||
Link: https://lore.kernel.org/stable/20250814-fix-upstream-contaminant-v1-1-801ce8089031%40google.com
|
||||
Link: https://lore.kernel.org/r/20250815-fix-upstream-contaminant-v2-1-6c8d6c3adafb@google.com
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/usb/typec/tcpm/maxim_contaminant.c | 5 +++++
|
||||
drivers/usb/typec/tcpm/tcpci_maxim.h | 1 +
|
||||
2 files changed, 6 insertions(+)
|
||||
|
||||
--- a/drivers/usb/typec/tcpm/maxim_contaminant.c
|
||||
+++ b/drivers/usb/typec/tcpm/maxim_contaminant.c
|
||||
@@ -188,6 +188,11 @@ static int max_contaminant_read_comparat
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
+ /* Disable low power mode */
|
||||
+ ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL2, CCLPMODESEL,
|
||||
+ FIELD_PREP(CCLPMODESEL,
|
||||
+ LOW_POWER_MODE_DISABLE));
|
||||
+
|
||||
/* Sleep to allow comparators settle */
|
||||
usleep_range(5000, 6000);
|
||||
ret = regmap_update_bits(regmap, TCPC_TCPC_CTRL, TCPC_TCPC_CTRL_ORIENTATION, PLUG_ORNT_CC1);
|
||||
--- a/drivers/usb/typec/tcpm/tcpci_maxim.h
|
||||
+++ b/drivers/usb/typec/tcpm/tcpci_maxim.h
|
||||
@@ -21,6 +21,7 @@
|
||||
#define CCOVPDIS BIT(6)
|
||||
#define SBURPCTRL BIT(5)
|
||||
#define CCLPMODESEL GENMASK(4, 3)
|
||||
+#define LOW_POWER_MODE_DISABLE 0
|
||||
#define ULTRA_LOW_POWER_MODE 1
|
||||
#define CCRPCTRL GENMASK(2, 0)
|
||||
#define UA_1_SRC 1
|
114
debian/patches/patchset-pf/steady/0058-usb-typec-maxim_contaminant-re-enable-cc-toggle-if-c.patch
vendored
Normal file
114
debian/patches/patchset-pf/steady/0058-usb-typec-maxim_contaminant-re-enable-cc-toggle-if-c.patch
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
From 9a6bb08b2f28ebc163784da8c61a1ed1d086dc7b Mon Sep 17 00:00:00 2001
|
||||
From: Amit Sunil Dhamne <amitsd@google.com>
|
||||
Date: Fri, 15 Aug 2025 11:31:52 -0700
|
||||
Subject: usb: typec: maxim_contaminant: re-enable cc toggle if cc is open and
|
||||
port is clean
|
||||
|
||||
Presently in `max_contaminant_is_contaminant()` if there's no
|
||||
contaminant detected previously, CC is open & stopped toggling and no
|
||||
contaminant is currently present, TCPC.RC would be programmed to do DRP
|
||||
toggling. However, it didn't actively look for a connection. This would
|
||||
lead to Type-C not detect *any* new connections. Hence, in the above
|
||||
situation, re-enable toggling & program TCPC to look for a new
|
||||
connection.
|
||||
|
||||
Also, return early if TCPC was looking for connection as this indicates
|
||||
TCPC has neither detected a potential connection nor a change in
|
||||
contaminant state.
|
||||
|
||||
In addition, once dry detection is complete (port is dry), restart
|
||||
toggling.
|
||||
|
||||
Fixes: 02b332a06397e ("usb: typec: maxim_contaminant: Implement check_contaminant callback")
|
||||
Cc: stable <stable@kernel.org>
|
||||
Signed-off-by: Amit Sunil Dhamne <amitsd@google.com>
|
||||
Reviewed-by: Badhri Jagan Sridharan <badhri@google.com>
|
||||
Link: https://lore.kernel.org/r/20250815-fix-upstream-contaminant-v2-2-6c8d6c3adafb@google.com
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/usb/typec/tcpm/maxim_contaminant.c | 53 ++++++++++++++++++++++
|
||||
1 file changed, 53 insertions(+)
|
||||
|
||||
--- a/drivers/usb/typec/tcpm/maxim_contaminant.c
|
||||
+++ b/drivers/usb/typec/tcpm/maxim_contaminant.c
|
||||
@@ -329,6 +329,39 @@ static int max_contaminant_enable_dry_de
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int max_contaminant_enable_toggling(struct max_tcpci_chip *chip)
|
||||
+{
|
||||
+ struct regmap *regmap = chip->data.regmap;
|
||||
+ int ret;
|
||||
+
|
||||
+ /* Disable dry detection if enabled. */
|
||||
+ ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL2, CCLPMODESEL,
|
||||
+ FIELD_PREP(CCLPMODESEL,
|
||||
+ LOW_POWER_MODE_DISABLE));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL1, CCCONNDRY, 0);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = max_tcpci_write8(chip, TCPC_ROLE_CTRL, TCPC_ROLE_CTRL_DRP |
|
||||
+ FIELD_PREP(TCPC_ROLE_CTRL_CC1,
|
||||
+ TCPC_ROLE_CTRL_CC_RD) |
|
||||
+ FIELD_PREP(TCPC_ROLE_CTRL_CC2,
|
||||
+ TCPC_ROLE_CTRL_CC_RD));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = regmap_update_bits(regmap, TCPC_TCPC_CTRL,
|
||||
+ TCPC_TCPC_CTRL_EN_LK4CONN_ALRT,
|
||||
+ TCPC_TCPC_CTRL_EN_LK4CONN_ALRT);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return max_tcpci_write8(chip, TCPC_COMMAND, TCPC_CMD_LOOK4CONNECTION);
|
||||
+}
|
||||
+
|
||||
bool max_contaminant_is_contaminant(struct max_tcpci_chip *chip, bool disconnect_while_debounce,
|
||||
bool *cc_handled)
|
||||
{
|
||||
@@ -345,6 +378,12 @@ bool max_contaminant_is_contaminant(stru
|
||||
if (ret < 0)
|
||||
return false;
|
||||
|
||||
+ if (cc_status & TCPC_CC_STATUS_TOGGLING) {
|
||||
+ if (chip->contaminant_state == DETECTED)
|
||||
+ return true;
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
if (chip->contaminant_state == NOT_DETECTED || chip->contaminant_state == SINK) {
|
||||
if (!disconnect_while_debounce)
|
||||
msleep(100);
|
||||
@@ -377,6 +416,12 @@ bool max_contaminant_is_contaminant(stru
|
||||
max_contaminant_enable_dry_detection(chip);
|
||||
return true;
|
||||
}
|
||||
+
|
||||
+ ret = max_contaminant_enable_toggling(chip);
|
||||
+ if (ret)
|
||||
+ dev_err(chip->dev,
|
||||
+ "Failed to enable toggling, ret=%d",
|
||||
+ ret);
|
||||
}
|
||||
} else if (chip->contaminant_state == DETECTED) {
|
||||
if (!(cc_status & TCPC_CC_STATUS_TOGGLING)) {
|
||||
@@ -384,6 +429,14 @@ bool max_contaminant_is_contaminant(stru
|
||||
if (chip->contaminant_state == DETECTED) {
|
||||
max_contaminant_enable_dry_detection(chip);
|
||||
return true;
|
||||
+ } else {
|
||||
+ ret = max_contaminant_enable_toggling(chip);
|
||||
+ if (ret) {
|
||||
+ dev_err(chip->dev,
|
||||
+ "Failed to enable toggling, ret=%d",
|
||||
+ ret);
|
||||
+ return true;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
}
|
75
debian/patches/patchset-pf/steady/0059-debugfs-fix-mount-options-not-being-applied.patch
vendored
Normal file
75
debian/patches/patchset-pf/steady/0059-debugfs-fix-mount-options-not-being-applied.patch
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
From 576b70e92168f38ab3167768acb6b65cd5bf8aa7 Mon Sep 17 00:00:00 2001
|
||||
From: Charalampos Mitrodimas <charmitro@posteo.net>
|
||||
Date: Sat, 16 Aug 2025 14:14:37 +0000
|
||||
Subject: debugfs: fix mount options not being applied
|
||||
|
||||
Mount options (uid, gid, mode) are silently ignored when debugfs is
|
||||
mounted. This is a regression introduced during the conversion to the
|
||||
new mount API.
|
||||
|
||||
When the mount API conversion was done, the parsed options were never
|
||||
applied to the superblock when it was reused. As a result, the mount
|
||||
options were ignored when debugfs was mounted.
|
||||
|
||||
Fix this by following the same pattern as the tracefs fix in commit
|
||||
e4d32142d1de ("tracing: Fix tracefs mount options"). Call
|
||||
debugfs_reconfigure() in debugfs_get_tree() to apply the mount options
|
||||
to the superblock after it has been created or reused.
|
||||
|
||||
As an example, with the bug the "mode" mount option is ignored:
|
||||
|
||||
$ mount -o mode=0666 -t debugfs debugfs /tmp/debugfs_test
|
||||
$ mount | grep debugfs_test
|
||||
debugfs on /tmp/debugfs_test type debugfs (rw,relatime)
|
||||
$ ls -ld /tmp/debugfs_test
|
||||
drwx------ 25 root root 0 Aug 4 14:16 /tmp/debugfs_test
|
||||
|
||||
With the fix applied, it works as expected:
|
||||
|
||||
$ mount -o mode=0666 -t debugfs debugfs /tmp/debugfs_test
|
||||
$ mount | grep debugfs_test
|
||||
debugfs on /tmp/debugfs_test type debugfs (rw,relatime,mode=666)
|
||||
$ ls -ld /tmp/debugfs_test
|
||||
drw-rw-rw- 37 root root 0 Aug 2 17:28 /tmp/debugfs_test
|
||||
|
||||
Fixes: a20971c18752 ("vfs: Convert debugfs to use the new mount API")
|
||||
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220406
|
||||
Cc: stable <stable@kernel.org>
|
||||
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
|
||||
Signed-off-by: Charalampos Mitrodimas <charmitro@posteo.net>
|
||||
Link: https://lore.kernel.org/r/20250816-debugfs-mount-opts-v3-1-d271dad57b5b@posteo.net
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
fs/debugfs/inode.c | 11 ++++++++++-
|
||||
1 file changed, 10 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/fs/debugfs/inode.c
|
||||
+++ b/fs/debugfs/inode.c
|
||||
@@ -183,6 +183,9 @@ static int debugfs_reconfigure(struct fs
|
||||
struct debugfs_fs_info *sb_opts = sb->s_fs_info;
|
||||
struct debugfs_fs_info *new_opts = fc->s_fs_info;
|
||||
|
||||
+ if (!new_opts)
|
||||
+ return 0;
|
||||
+
|
||||
sync_filesystem(sb);
|
||||
|
||||
/* structure copy of new mount options to sb */
|
||||
@@ -282,10 +285,16 @@ static int debugfs_fill_super(struct sup
|
||||
|
||||
static int debugfs_get_tree(struct fs_context *fc)
|
||||
{
|
||||
+ int err;
|
||||
+
|
||||
if (!(debugfs_allow & DEBUGFS_ALLOW_API))
|
||||
return -EPERM;
|
||||
|
||||
- return get_tree_single(fc, debugfs_fill_super);
|
||||
+ err = get_tree_single(fc, debugfs_fill_super);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ return debugfs_reconfigure(fc);
|
||||
}
|
||||
|
||||
static void debugfs_free_fc(struct fs_context *fc)
|
@@ -0,0 +1,88 @@
|
||||
From 80250ddfb13b64a0fef53806669893094a731956 Mon Sep 17 00:00:00 2001
|
||||
From: Namjae Jeon <linkinjeon@kernel.org>
|
||||
Date: Sun, 17 Aug 2025 09:48:40 +0900
|
||||
Subject: ksmbd: extend the connection limiting mechanism to support IPv6
|
||||
|
||||
Update the connection tracking logic to handle both IPv4 and IPv6
|
||||
address families.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Fixes: e6bb91939740 ("ksmbd: limit repeated connections from clients with the same IP")
|
||||
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
|
||||
Signed-off-by: Steve French <stfrench@microsoft.com>
|
||||
---
|
||||
fs/smb/server/connection.h | 7 ++++++-
|
||||
fs/smb/server/transport_tcp.c | 26 +++++++++++++++++++++++---
|
||||
2 files changed, 29 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/fs/smb/server/connection.h
|
||||
+++ b/fs/smb/server/connection.h
|
||||
@@ -46,7 +46,12 @@ struct ksmbd_conn {
|
||||
struct mutex srv_mutex;
|
||||
int status;
|
||||
unsigned int cli_cap;
|
||||
- __be32 inet_addr;
|
||||
+ union {
|
||||
+ __be32 inet_addr;
|
||||
+#if IS_ENABLED(CONFIG_IPV6)
|
||||
+ u8 inet6_addr[16];
|
||||
+#endif
|
||||
+ };
|
||||
char *request_buf;
|
||||
struct ksmbd_transport *transport;
|
||||
struct nls_table *local_nls;
|
||||
--- a/fs/smb/server/transport_tcp.c
|
||||
+++ b/fs/smb/server/transport_tcp.c
|
||||
@@ -87,7 +87,14 @@ static struct tcp_transport *alloc_trans
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+#if IS_ENABLED(CONFIG_IPV6)
|
||||
+ if (client_sk->sk->sk_family == AF_INET6)
|
||||
+ memcpy(&conn->inet6_addr, &client_sk->sk->sk_v6_daddr, 16);
|
||||
+ else
|
||||
+ conn->inet_addr = inet_sk(client_sk->sk)->inet_daddr;
|
||||
+#else
|
||||
conn->inet_addr = inet_sk(client_sk->sk)->inet_daddr;
|
||||
+#endif
|
||||
conn->transport = KSMBD_TRANS(t);
|
||||
KSMBD_TRANS(t)->conn = conn;
|
||||
KSMBD_TRANS(t)->ops = &ksmbd_tcp_transport_ops;
|
||||
@@ -231,7 +238,6 @@ static int ksmbd_kthread_fn(void *p)
|
||||
{
|
||||
struct socket *client_sk = NULL;
|
||||
struct interface *iface = (struct interface *)p;
|
||||
- struct inet_sock *csk_inet;
|
||||
struct ksmbd_conn *conn;
|
||||
int ret;
|
||||
|
||||
@@ -254,13 +260,27 @@ static int ksmbd_kthread_fn(void *p)
|
||||
/*
|
||||
* Limits repeated connections from clients with the same IP.
|
||||
*/
|
||||
- csk_inet = inet_sk(client_sk->sk);
|
||||
down_read(&conn_list_lock);
|
||||
list_for_each_entry(conn, &conn_list, conns_list)
|
||||
- if (csk_inet->inet_daddr == conn->inet_addr) {
|
||||
+#if IS_ENABLED(CONFIG_IPV6)
|
||||
+ if (client_sk->sk->sk_family == AF_INET6) {
|
||||
+ if (memcmp(&client_sk->sk->sk_v6_daddr,
|
||||
+ &conn->inet6_addr, 16) == 0) {
|
||||
+ ret = -EAGAIN;
|
||||
+ break;
|
||||
+ }
|
||||
+ } else if (inet_sk(client_sk->sk)->inet_daddr ==
|
||||
+ conn->inet_addr) {
|
||||
ret = -EAGAIN;
|
||||
break;
|
||||
}
|
||||
+#else
|
||||
+ if (inet_sk(client_sk->sk)->inet_daddr ==
|
||||
+ conn->inet_addr) {
|
||||
+ ret = -EAGAIN;
|
||||
+ break;
|
||||
+ }
|
||||
+#endif
|
||||
up_read(&conn_list_lock);
|
||||
if (ret == -EAGAIN)
|
||||
continue;
|
@@ -0,0 +1,56 @@
|
||||
From 053ed640e99b096f155a404b3d919b3475bd4275 Mon Sep 17 00:00:00 2001
|
||||
From: Ziyan Xu <ziyan@securitygossip.com>
|
||||
Date: Sat, 16 Aug 2025 10:20:05 +0900
|
||||
Subject: ksmbd: fix refcount leak causing resource not released
|
||||
|
||||
When ksmbd_conn_releasing(opinfo->conn) returns true,the refcount was not
|
||||
decremented properly, causing a refcount leak that prevents the count from
|
||||
reaching zero and the memory from being released.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Ziyan Xu <ziyan@securitygossip.com>
|
||||
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
|
||||
Signed-off-by: Steve French <stfrench@microsoft.com>
|
||||
---
|
||||
fs/smb/server/oplock.c | 13 ++++++++++---
|
||||
1 file changed, 10 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/fs/smb/server/oplock.c
|
||||
+++ b/fs/smb/server/oplock.c
|
||||
@@ -1102,8 +1102,10 @@ void smb_send_parent_lease_break_noti(st
|
||||
if (!atomic_inc_not_zero(&opinfo->refcount))
|
||||
continue;
|
||||
|
||||
- if (ksmbd_conn_releasing(opinfo->conn))
|
||||
+ if (ksmbd_conn_releasing(opinfo->conn)) {
|
||||
+ opinfo_put(opinfo);
|
||||
continue;
|
||||
+ }
|
||||
|
||||
oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE, NULL);
|
||||
opinfo_put(opinfo);
|
||||
@@ -1139,8 +1141,11 @@ void smb_lazy_parent_lease_break_close(s
|
||||
if (!atomic_inc_not_zero(&opinfo->refcount))
|
||||
continue;
|
||||
|
||||
- if (ksmbd_conn_releasing(opinfo->conn))
|
||||
+ if (ksmbd_conn_releasing(opinfo->conn)) {
|
||||
+ opinfo_put(opinfo);
|
||||
continue;
|
||||
+ }
|
||||
+
|
||||
oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE, NULL);
|
||||
opinfo_put(opinfo);
|
||||
}
|
||||
@@ -1343,8 +1348,10 @@ void smb_break_all_levII_oplock(struct k
|
||||
if (!atomic_inc_not_zero(&brk_op->refcount))
|
||||
continue;
|
||||
|
||||
- if (ksmbd_conn_releasing(brk_op->conn))
|
||||
+ if (ksmbd_conn_releasing(brk_op->conn)) {
|
||||
+ opinfo_put(brk_op);
|
||||
continue;
|
||||
+ }
|
||||
|
||||
if (brk_op->is_lease && (brk_op->o_lease->state &
|
||||
(~(SMB2_LEASE_READ_CACHING_LE |
|
@@ -0,0 +1,86 @@
|
||||
From 4d73be13721834ee79ae45bd66102501f17a779d Mon Sep 17 00:00:00 2001
|
||||
From: Victor Shih <victor.shih@genesyslogic.com.tw>
|
||||
Date: Thu, 31 Jul 2025 14:57:50 +0800
|
||||
Subject: mmc: sdhci-pci-gli: Add a new function to simplify the code
|
||||
|
||||
In preparation to fix replay timer timeout, add
|
||||
sdhci_gli_mask_replay_timer_timeout() function
|
||||
to simplify some of the code, allowing it to be re-used.
|
||||
|
||||
Signed-off-by: Victor Shih <victor.shih@genesyslogic.com.tw>
|
||||
Fixes: 1ae1d2d6e555 ("mmc: sdhci-pci-gli: Add Genesys Logic GL9763E support")
|
||||
Cc: stable@vger.kernel.org
|
||||
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
|
||||
Link: https://lore.kernel.org/r/20250731065752.450231-2-victorshihgli@gmail.com
|
||||
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
|
||||
---
|
||||
drivers/mmc/host/sdhci-pci-gli.c | 30 ++++++++++++++++--------------
|
||||
1 file changed, 16 insertions(+), 14 deletions(-)
|
||||
|
||||
--- a/drivers/mmc/host/sdhci-pci-gli.c
|
||||
+++ b/drivers/mmc/host/sdhci-pci-gli.c
|
||||
@@ -287,6 +287,20 @@
|
||||
#define GLI_MAX_TUNING_LOOP 40
|
||||
|
||||
/* Genesys Logic chipset */
|
||||
+static void sdhci_gli_mask_replay_timer_timeout(struct pci_dev *pdev)
|
||||
+{
|
||||
+ int aer;
|
||||
+ u32 value;
|
||||
+
|
||||
+ /* mask the replay timer timeout of AER */
|
||||
+ aer = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
|
||||
+ if (aer) {
|
||||
+ pci_read_config_dword(pdev, aer + PCI_ERR_COR_MASK, &value);
|
||||
+ value |= PCI_ERR_COR_REP_TIMER;
|
||||
+ pci_write_config_dword(pdev, aer + PCI_ERR_COR_MASK, value);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static inline void gl9750_wt_on(struct sdhci_host *host)
|
||||
{
|
||||
u32 wt_value;
|
||||
@@ -607,7 +621,6 @@ static void gl9750_hw_setting(struct sdh
|
||||
{
|
||||
struct sdhci_pci_slot *slot = sdhci_priv(host);
|
||||
struct pci_dev *pdev;
|
||||
- int aer;
|
||||
u32 value;
|
||||
|
||||
pdev = slot->chip->pdev;
|
||||
@@ -626,12 +639,7 @@ static void gl9750_hw_setting(struct sdh
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
|
||||
/* mask the replay timer timeout of AER */
|
||||
- aer = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
|
||||
- if (aer) {
|
||||
- pci_read_config_dword(pdev, aer + PCI_ERR_COR_MASK, &value);
|
||||
- value |= PCI_ERR_COR_REP_TIMER;
|
||||
- pci_write_config_dword(pdev, aer + PCI_ERR_COR_MASK, value);
|
||||
- }
|
||||
+ sdhci_gli_mask_replay_timer_timeout(pdev);
|
||||
|
||||
gl9750_wt_off(host);
|
||||
}
|
||||
@@ -806,7 +814,6 @@ static void sdhci_gl9755_set_clock(struc
|
||||
static void gl9755_hw_setting(struct sdhci_pci_slot *slot)
|
||||
{
|
||||
struct pci_dev *pdev = slot->chip->pdev;
|
||||
- int aer;
|
||||
u32 value;
|
||||
|
||||
gl9755_wt_on(pdev);
|
||||
@@ -841,12 +848,7 @@ static void gl9755_hw_setting(struct sdh
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
|
||||
/* mask the replay timer timeout of AER */
|
||||
- aer = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
|
||||
- if (aer) {
|
||||
- pci_read_config_dword(pdev, aer + PCI_ERR_COR_MASK, &value);
|
||||
- value |= PCI_ERR_COR_REP_TIMER;
|
||||
- pci_write_config_dword(pdev, aer + PCI_ERR_COR_MASK, value);
|
||||
- }
|
||||
+ sdhci_gli_mask_replay_timer_timeout(pdev);
|
||||
|
||||
gl9755_wt_off(pdev);
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
From dfc8d4137cf986bac6a07e4b202423b0e3d32f9e Mon Sep 17 00:00:00 2001
|
||||
From: Victor Shih <victor.shih@genesyslogic.com.tw>
|
||||
Date: Thu, 31 Jul 2025 14:57:51 +0800
|
||||
Subject: mmc: sdhci-pci-gli: GL9763e: Rename the gli_set_gl9763e() for
|
||||
consistency
|
||||
|
||||
In preparation to fix replay timer timeout, rename the
|
||||
gli_set_gl9763e() to gl9763e_hw_setting() for consistency.
|
||||
|
||||
Signed-off-by: Victor Shih <victor.shih@genesyslogic.com.tw>
|
||||
Fixes: 1ae1d2d6e555 ("mmc: sdhci-pci-gli: Add Genesys Logic GL9763E support")
|
||||
Cc: stable@vger.kernel.org
|
||||
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
|
||||
Link: https://lore.kernel.org/r/20250731065752.450231-3-victorshihgli@gmail.com
|
||||
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
|
||||
---
|
||||
drivers/mmc/host/sdhci-pci-gli.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/mmc/host/sdhci-pci-gli.c
|
||||
+++ b/drivers/mmc/host/sdhci-pci-gli.c
|
||||
@@ -1753,7 +1753,7 @@ cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static void gli_set_gl9763e(struct sdhci_pci_slot *slot)
|
||||
+static void gl9763e_hw_setting(struct sdhci_pci_slot *slot)
|
||||
{
|
||||
struct pci_dev *pdev = slot->chip->pdev;
|
||||
u32 value;
|
||||
@@ -1925,7 +1925,7 @@ static int gli_probe_slot_gl9763e(struct
|
||||
gli_pcie_enable_msi(slot);
|
||||
host->mmc_host_ops.hs400_enhanced_strobe =
|
||||
gl9763e_hs400_enhanced_strobe;
|
||||
- gli_set_gl9763e(slot);
|
||||
+ gl9763e_hw_setting(slot);
|
||||
sdhci_enable_v4_mode(host);
|
||||
|
||||
return 0;
|
@@ -0,0 +1,32 @@
|
||||
From d36b9a791450aec781a3276dd3544bdfb147e539 Mon Sep 17 00:00:00 2001
|
||||
From: Victor Shih <victor.shih@genesyslogic.com.tw>
|
||||
Date: Thu, 31 Jul 2025 14:57:52 +0800
|
||||
Subject: mmc: sdhci-pci-gli: GL9763e: Mask the replay timer timeout of AER
|
||||
|
||||
Due to a flaw in the hardware design, the GL9763e replay timer frequently
|
||||
times out when ASPM is enabled. As a result, the warning messages will
|
||||
often appear in the system log when the system accesses the GL9763e
|
||||
PCI config. Therefore, the replay timer timeout must be masked.
|
||||
|
||||
Signed-off-by: Victor Shih <victor.shih@genesyslogic.com.tw>
|
||||
Fixes: 1ae1d2d6e555 ("mmc: sdhci-pci-gli: Add Genesys Logic GL9763E support")
|
||||
Cc: stable@vger.kernel.org
|
||||
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
|
||||
Link: https://lore.kernel.org/r/20250731065752.450231-4-victorshihgli@gmail.com
|
||||
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
|
||||
---
|
||||
drivers/mmc/host/sdhci-pci-gli.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
--- a/drivers/mmc/host/sdhci-pci-gli.c
|
||||
+++ b/drivers/mmc/host/sdhci-pci-gli.c
|
||||
@@ -1782,6 +1782,9 @@ static void gl9763e_hw_setting(struct sd
|
||||
value |= FIELD_PREP(GLI_9763E_HS400_RXDLY, GLI_9763E_HS400_RXDLY_5);
|
||||
pci_write_config_dword(pdev, PCIE_GLI_9763E_CLKRXDLY, value);
|
||||
|
||||
+ /* mask the replay timer timeout of AER */
|
||||
+ sdhci_gli_mask_replay_timer_timeout(pdev);
|
||||
+
|
||||
pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value);
|
||||
value &= ~GLI_9763E_VHS_REV;
|
||||
value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_R);
|
128
debian/patches/patchset-pf/steady/0065-mmc-sdhci-of-arasan-Ensure-CD-logic-stabilization-be.patch
vendored
Normal file
128
debian/patches/patchset-pf/steady/0065-mmc-sdhci-of-arasan-Ensure-CD-logic-stabilization-be.patch
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
From 848beabc268b0e12a5bc0dbe71c45c5db7a12b43 Mon Sep 17 00:00:00 2001
|
||||
From: Sai Krishna Potthuri <sai.krishna.potthuri@amd.com>
|
||||
Date: Wed, 30 Jul 2025 11:35:43 +0530
|
||||
Subject: mmc: sdhci-of-arasan: Ensure CD logic stabilization before power-up
|
||||
|
||||
During SD suspend/resume without a full card rescan (when using
|
||||
non-removable SD cards for rootfs), the SD card initialization may fail
|
||||
after resume. This occurs because, after a host controller reset, the
|
||||
card detect logic may take time to stabilize due to debounce logic.
|
||||
Without waiting for stabilization, the host may attempt powering up the
|
||||
card prematurely, leading to command timeouts during resume flow.
|
||||
Add sdhci_arasan_set_power_and_bus_voltage() to wait for the card detect
|
||||
stable bit before power up the card. Since the stabilization time
|
||||
is not fixed, a maximum timeout of one second is used to ensure
|
||||
sufficient wait time for the card detect signal to stabilize.
|
||||
|
||||
Signed-off-by: Sai Krishna Potthuri <sai.krishna.potthuri@amd.com>
|
||||
Cc: stable@vger.kernel.org
|
||||
Link: https://lore.kernel.org/r/20250730060543.1735971-1-sai.krishna.potthuri@amd.com
|
||||
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
|
||||
---
|
||||
drivers/mmc/host/sdhci-of-arasan.c | 33 ++++++++++++++++++++++++++++--
|
||||
1 file changed, 31 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/mmc/host/sdhci-of-arasan.c
|
||||
+++ b/drivers/mmc/host/sdhci-of-arasan.c
|
||||
@@ -99,6 +99,9 @@
|
||||
#define HIWORD_UPDATE(val, mask, shift) \
|
||||
((val) << (shift) | (mask) << ((shift) + 16))
|
||||
|
||||
+#define CD_STABLE_TIMEOUT_US 1000000
|
||||
+#define CD_STABLE_MAX_SLEEP_US 10
|
||||
+
|
||||
/**
|
||||
* struct sdhci_arasan_soc_ctl_field - Field used in sdhci_arasan_soc_ctl_map
|
||||
*
|
||||
@@ -206,12 +209,15 @@ struct sdhci_arasan_data {
|
||||
* 19MHz instead
|
||||
*/
|
||||
#define SDHCI_ARASAN_QUIRK_CLOCK_25_BROKEN BIT(2)
|
||||
+/* Enable CD stable check before power-up */
|
||||
+#define SDHCI_ARASAN_QUIRK_ENSURE_CD_STABLE BIT(3)
|
||||
};
|
||||
|
||||
struct sdhci_arasan_of_data {
|
||||
const struct sdhci_arasan_soc_ctl_map *soc_ctl_map;
|
||||
const struct sdhci_pltfm_data *pdata;
|
||||
const struct sdhci_arasan_clk_ops *clk_ops;
|
||||
+ u32 quirks;
|
||||
};
|
||||
|
||||
static const struct sdhci_arasan_soc_ctl_map rk3399_soc_ctl_map = {
|
||||
@@ -514,6 +520,24 @@ static int sdhci_arasan_voltage_switch(s
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+static void sdhci_arasan_set_power_and_bus_voltage(struct sdhci_host *host, unsigned char mode,
|
||||
+ unsigned short vdd)
|
||||
+{
|
||||
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
+ struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
|
||||
+ u32 reg;
|
||||
+
|
||||
+ /*
|
||||
+ * Ensure that the card detect logic has stabilized before powering up, this is
|
||||
+ * necessary after a host controller reset.
|
||||
+ */
|
||||
+ if (mode == MMC_POWER_UP && sdhci_arasan->quirks & SDHCI_ARASAN_QUIRK_ENSURE_CD_STABLE)
|
||||
+ read_poll_timeout(sdhci_readl, reg, reg & SDHCI_CD_STABLE, CD_STABLE_MAX_SLEEP_US,
|
||||
+ CD_STABLE_TIMEOUT_US, false, host, SDHCI_PRESENT_STATE);
|
||||
+
|
||||
+ sdhci_set_power_and_bus_voltage(host, mode, vdd);
|
||||
+}
|
||||
+
|
||||
static const struct sdhci_ops sdhci_arasan_ops = {
|
||||
.set_clock = sdhci_arasan_set_clock,
|
||||
.get_max_clock = sdhci_pltfm_clk_get_max_clock,
|
||||
@@ -521,7 +545,7 @@ static const struct sdhci_ops sdhci_aras
|
||||
.set_bus_width = sdhci_set_bus_width,
|
||||
.reset = sdhci_arasan_reset,
|
||||
.set_uhs_signaling = sdhci_set_uhs_signaling,
|
||||
- .set_power = sdhci_set_power_and_bus_voltage,
|
||||
+ .set_power = sdhci_arasan_set_power_and_bus_voltage,
|
||||
.hw_reset = sdhci_arasan_hw_reset,
|
||||
};
|
||||
|
||||
@@ -570,7 +594,7 @@ static const struct sdhci_ops sdhci_aras
|
||||
.set_bus_width = sdhci_set_bus_width,
|
||||
.reset = sdhci_arasan_reset,
|
||||
.set_uhs_signaling = sdhci_set_uhs_signaling,
|
||||
- .set_power = sdhci_set_power_and_bus_voltage,
|
||||
+ .set_power = sdhci_arasan_set_power_and_bus_voltage,
|
||||
.irq = sdhci_arasan_cqhci_irq,
|
||||
};
|
||||
|
||||
@@ -1447,6 +1471,7 @@ static const struct sdhci_arasan_clk_ops
|
||||
static struct sdhci_arasan_of_data sdhci_arasan_zynqmp_data = {
|
||||
.pdata = &sdhci_arasan_zynqmp_pdata,
|
||||
.clk_ops = &zynqmp_clk_ops,
|
||||
+ .quirks = SDHCI_ARASAN_QUIRK_ENSURE_CD_STABLE,
|
||||
};
|
||||
|
||||
static const struct sdhci_arasan_clk_ops versal_clk_ops = {
|
||||
@@ -1457,6 +1482,7 @@ static const struct sdhci_arasan_clk_ops
|
||||
static struct sdhci_arasan_of_data sdhci_arasan_versal_data = {
|
||||
.pdata = &sdhci_arasan_zynqmp_pdata,
|
||||
.clk_ops = &versal_clk_ops,
|
||||
+ .quirks = SDHCI_ARASAN_QUIRK_ENSURE_CD_STABLE,
|
||||
};
|
||||
|
||||
static const struct sdhci_arasan_clk_ops versal_net_clk_ops = {
|
||||
@@ -1467,6 +1493,7 @@ static const struct sdhci_arasan_clk_ops
|
||||
static struct sdhci_arasan_of_data sdhci_arasan_versal_net_data = {
|
||||
.pdata = &sdhci_arasan_versal_net_pdata,
|
||||
.clk_ops = &versal_net_clk_ops,
|
||||
+ .quirks = SDHCI_ARASAN_QUIRK_ENSURE_CD_STABLE,
|
||||
};
|
||||
|
||||
static struct sdhci_arasan_of_data intel_keembay_emmc_data = {
|
||||
@@ -1945,6 +1972,8 @@ static int sdhci_arasan_probe(struct pla
|
||||
if (of_device_is_compatible(np, "rockchip,rk3399-sdhci-5.1"))
|
||||
sdhci_arasan_update_clockmultiplier(host, 0x0);
|
||||
|
||||
+ sdhci_arasan->quirks |= data->quirks;
|
||||
+
|
||||
if (of_device_is_compatible(np, "intel,keembay-sdhci-5.1-emmc") ||
|
||||
of_device_is_compatible(np, "intel,keembay-sdhci-5.1-sd") ||
|
||||
of_device_is_compatible(np, "intel,keembay-sdhci-5.1-sdio")) {
|
@@ -0,0 +1,75 @@
|
||||
From 6b13747a602e6e119a0cfd03d967e0726d12ba26 Mon Sep 17 00:00:00 2001
|
||||
From: Jiayi Li <lijiayi@kylinos.cn>
|
||||
Date: Mon, 4 Aug 2025 09:36:04 +0800
|
||||
Subject: memstick: Fix deadlock by moving removing flag earlier
|
||||
|
||||
The existing memstick core patch: commit 62c59a8786e6 ("memstick: Skip
|
||||
allocating card when removing host") sets host->removing in
|
||||
memstick_remove_host(),but still exists a critical time window where
|
||||
memstick_check can run after host->eject is set but before removing is set.
|
||||
|
||||
In the rtsx_usb_ms driver, the problematic sequence is:
|
||||
|
||||
rtsx_usb_ms_drv_remove: memstick_check:
|
||||
host->eject = true
|
||||
cancel_work_sync(handle_req) if(!host->removing)
|
||||
... memstick_alloc_card()
|
||||
memstick_set_rw_addr()
|
||||
memstick_new_req()
|
||||
rtsx_usb_ms_request()
|
||||
if(!host->eject)
|
||||
skip schedule_work
|
||||
wait_for_completion()
|
||||
memstick_remove_host: [blocks indefinitely]
|
||||
host->removing = true
|
||||
flush_workqueue()
|
||||
[block]
|
||||
|
||||
1. rtsx_usb_ms_drv_remove sets host->eject = true
|
||||
2. cancel_work_sync(&host->handle_req) runs
|
||||
3. memstick_check work may be executed here <-- danger window
|
||||
4. memstick_remove_host sets removing = 1
|
||||
|
||||
During this window (step 3), memstick_check calls memstick_alloc_card,
|
||||
which may indefinitely waiting for mrq_complete completion that will
|
||||
never occur because rtsx_usb_ms_request sees eject=true and skips
|
||||
scheduling work, memstick_set_rw_addr waits forever for completion.
|
||||
|
||||
This causes a deadlock when memstick_remove_host tries to flush_workqueue,
|
||||
waiting for memstick_check to complete, while memstick_check is blocked
|
||||
waiting for mrq_complete completion.
|
||||
|
||||
Fix this by setting removing=true at the start of rtsx_usb_ms_drv_remove,
|
||||
before any work cancellation. This ensures memstick_check will see the
|
||||
removing flag immediately and exit early, avoiding the deadlock.
|
||||
|
||||
Fixes: 62c59a8786e6 ("memstick: Skip allocating card when removing host")
|
||||
Signed-off-by: Jiayi Li <lijiayi@kylinos.cn>
|
||||
Cc: stable@vger.kernel.org
|
||||
Link: https://lore.kernel.org/r/20250804013604.1311218-1-lijiayi@kylinos.cn
|
||||
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
|
||||
---
|
||||
drivers/memstick/core/memstick.c | 1 -
|
||||
drivers/memstick/host/rtsx_usb_ms.c | 1 +
|
||||
2 files changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/memstick/core/memstick.c
|
||||
+++ b/drivers/memstick/core/memstick.c
|
||||
@@ -555,7 +555,6 @@ EXPORT_SYMBOL(memstick_add_host);
|
||||
*/
|
||||
void memstick_remove_host(struct memstick_host *host)
|
||||
{
|
||||
- host->removing = 1;
|
||||
flush_workqueue(workqueue);
|
||||
mutex_lock(&host->lock);
|
||||
if (host->card)
|
||||
--- a/drivers/memstick/host/rtsx_usb_ms.c
|
||||
+++ b/drivers/memstick/host/rtsx_usb_ms.c
|
||||
@@ -812,6 +812,7 @@ static void rtsx_usb_ms_drv_remove(struc
|
||||
int err;
|
||||
|
||||
host->eject = true;
|
||||
+ msh->removing = true;
|
||||
cancel_work_sync(&host->handle_req);
|
||||
cancel_delayed_work_sync(&host->poll_card);
|
||||
|
63
debian/patches/patchset-pf/steady/0067-compiler-remove-__ADDRESSABLE_ASM-_STR-again.patch
vendored
Normal file
63
debian/patches/patchset-pf/steady/0067-compiler-remove-__ADDRESSABLE_ASM-_STR-again.patch
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
From c09f6cef1d27da9baec950c8949926c9fc42a3e7 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Beulich <jbeulich@suse.com>
|
||||
Date: Mon, 14 Apr 2025 16:41:07 +0200
|
||||
Subject: compiler: remove __ADDRESSABLE_ASM{_STR,}() again
|
||||
|
||||
__ADDRESSABLE_ASM_STR() is where the necessary stringification happens.
|
||||
As long as "sym" doesn't contain any odd characters, no quoting is
|
||||
required for its use with .quad / .long. In fact the quotation gets in
|
||||
the way with gas 2.25; it's only from 2.26 onwards that quoted symbols
|
||||
are half-way properly supported.
|
||||
|
||||
However, assembly being different from C anyway, drop
|
||||
__ADDRESSABLE_ASM_STR() and its helper macro altogether. A simple
|
||||
.global directive will suffice to get the symbol "declared", i.e. into
|
||||
the symbol table. While there also stop open-coding STATIC_CALL_TRAMP()
|
||||
and STATIC_CALL_KEY().
|
||||
|
||||
Fixes: 0ef8047b737d ("x86/static-call: provide a way to do very early static-call updates")
|
||||
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
||||
Acked-by: Josh Poimboeuf <jpoimboe@kernel.org>
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Juergen Gross <jgross@suse.com>
|
||||
Message-ID: <609d2c74-de13-4fae-ab1a-1ec44afb948d@suse.com>
|
||||
---
|
||||
arch/x86/include/asm/xen/hypercall.h | 5 +++--
|
||||
include/linux/compiler.h | 8 --------
|
||||
2 files changed, 3 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/arch/x86/include/asm/xen/hypercall.h
|
||||
+++ b/arch/x86/include/asm/xen/hypercall.h
|
||||
@@ -94,12 +94,13 @@ DECLARE_STATIC_CALL(xen_hypercall, xen_h
|
||||
#ifdef MODULE
|
||||
#define __ADDRESSABLE_xen_hypercall
|
||||
#else
|
||||
-#define __ADDRESSABLE_xen_hypercall __ADDRESSABLE_ASM_STR(__SCK__xen_hypercall)
|
||||
+#define __ADDRESSABLE_xen_hypercall \
|
||||
+ __stringify(.global STATIC_CALL_KEY(xen_hypercall);)
|
||||
#endif
|
||||
|
||||
#define __HYPERCALL \
|
||||
__ADDRESSABLE_xen_hypercall \
|
||||
- "call __SCT__xen_hypercall"
|
||||
+ __stringify(call STATIC_CALL_TRAMP(xen_hypercall))
|
||||
|
||||
#define __HYPERCALL_ENTRY(x) "a" (x)
|
||||
|
||||
--- a/include/linux/compiler.h
|
||||
+++ b/include/linux/compiler.h
|
||||
@@ -288,14 +288,6 @@ static inline void *offset_to_ptr(const
|
||||
#define __ADDRESSABLE(sym) \
|
||||
___ADDRESSABLE(sym, __section(".discard.addressable"))
|
||||
|
||||
-#define __ADDRESSABLE_ASM(sym) \
|
||||
- .pushsection .discard.addressable,"aw"; \
|
||||
- .align ARCH_SEL(8,4); \
|
||||
- ARCH_SEL(.quad, .long) __stringify(sym); \
|
||||
- .popsection;
|
||||
-
|
||||
-#define __ADDRESSABLE_ASM_STR(sym) __stringify(__ADDRESSABLE_ASM(sym))
|
||||
-
|
||||
/*
|
||||
* This returns a constant expression while determining if an argument is
|
||||
* a constant expression, most importantly without evaluating the argument.
|
@@ -0,0 +1,55 @@
|
||||
From 3ba50a386db1ab9c1bdabbdcea6e7063bd7f875d Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@baylibre.com>
|
||||
Date: Thu, 14 Aug 2025 07:11:57 +0200
|
||||
Subject: ACPI: APEI: EINJ: Fix resource leak by remove callback in .exit.text
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The .remove() callback is also used during error handling in
|
||||
faux_probe(). As einj_remove() was marked with __exit it's not linked
|
||||
into the kernel if the driver is built-in, potentially resulting in
|
||||
resource leaks.
|
||||
|
||||
Also remove the comment justifying the __exit annotation which doesn't
|
||||
apply any more since the driver was converted to the faux device
|
||||
interface.
|
||||
|
||||
Fixes: 6cb9441bfe8d ("ACPI: APEI: EINJ: Transition to the faux device interface")
|
||||
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
|
||||
Cc: 6.16+ <stable@vger.kernel.org> # 6.16+
|
||||
Link: https://patch.msgid.link/20250814051157.35867-2-u.kleine-koenig@baylibre.com
|
||||
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
||||
---
|
||||
drivers/acpi/apei/einj-core.c | 12 +++---------
|
||||
1 file changed, 3 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/drivers/acpi/apei/einj-core.c
|
||||
+++ b/drivers/acpi/apei/einj-core.c
|
||||
@@ -842,7 +842,7 @@ err_put_table:
|
||||
return rc;
|
||||
}
|
||||
|
||||
-static void __exit einj_remove(struct faux_device *fdev)
|
||||
+static void einj_remove(struct faux_device *fdev)
|
||||
{
|
||||
struct apei_exec_context ctx;
|
||||
|
||||
@@ -864,15 +864,9 @@ static void __exit einj_remove(struct fa
|
||||
}
|
||||
|
||||
static struct faux_device *einj_dev;
|
||||
-/*
|
||||
- * einj_remove() lives in .exit.text. For drivers registered via
|
||||
- * platform_driver_probe() this is ok because they cannot get unbound at
|
||||
- * runtime. So mark the driver struct with __refdata to prevent modpost
|
||||
- * triggering a section mismatch warning.
|
||||
- */
|
||||
-static struct faux_device_ops einj_device_ops __refdata = {
|
||||
+static struct faux_device_ops einj_device_ops = {
|
||||
.probe = einj_probe,
|
||||
- .remove = __exit_p(einj_remove),
|
||||
+ .remove = einj_remove,
|
||||
};
|
||||
|
||||
static int __init einj_init(void)
|
118
debian/patches/patchset-pf/steady/0069-cpuidle-governors-menu-Avoid-selecting-states-with-t.patch
vendored
Normal file
118
debian/patches/patchset-pf/steady/0069-cpuidle-governors-menu-Avoid-selecting-states-with-t.patch
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
From 2d8daa84e1cb9681d49a29cf829eb5678850210e Mon Sep 17 00:00:00 2001
|
||||
From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
|
||||
Date: Wed, 13 Aug 2025 12:25:58 +0200
|
||||
Subject: cpuidle: governors: menu: Avoid selecting states with too much
|
||||
latency
|
||||
|
||||
Occasionally, the exit latency of the idle state selected by the menu
|
||||
governor may exceed the PM QoS CPU wakeup latency limit. Namely, if the
|
||||
scheduler tick has been stopped already and predicted_ns is greater than
|
||||
the tick period length, the governor may return an idle state whose exit
|
||||
latency exceeds latency_req because that decision is made before
|
||||
checking the current idle state's exit latency.
|
||||
|
||||
For instance, say that there are 3 idle states, 0, 1, and 2. For idle
|
||||
states 0 and 1, the exit latency is equal to the target residency and
|
||||
the values are 0 and 5 us, respectively. State 2 is deeper and has the
|
||||
exit latency and target residency of 200 us and 2 ms (which is greater
|
||||
than the tick period length), respectively.
|
||||
|
||||
Say that predicted_ns is equal to TICK_NSEC and the PM QoS latency
|
||||
limit is 20 us. After the first two iterations of the main loop in
|
||||
menu_select(), idx becomes 1 and in the third iteration of it the target
|
||||
residency of the current state (state 2) is greater than predicted_ns.
|
||||
State 2 is not a polling one and predicted_ns is not less than TICK_NSEC,
|
||||
so the check on whether or not the tick has been stopped is done. Say
|
||||
that the tick has been stopped already and there are no imminent timers
|
||||
(that is, delta_tick is greater than the target residency of state 2).
|
||||
In that case, idx becomes 2 and it is returned immediately, but the exit
|
||||
latency of state 2 exceeds the latency limit.
|
||||
|
||||
Address this issue by modifying the code to compare the exit latency of
|
||||
the current idle state (idle state i) with the latency limit before
|
||||
comparing its target residency with predicted_ns, which allows one
|
||||
more exit_latency_ns check that becomes redundant to be dropped.
|
||||
|
||||
However, after the above change, latency_req cannot take the predicted_ns
|
||||
value any more, which takes place after commit 38f83090f515 ("cpuidle:
|
||||
menu: Remove iowait influence"), because it may cause a polling state
|
||||
to be returned prematurely.
|
||||
|
||||
In the context of the previous example say that predicted_ns is 3000 and
|
||||
the PM QoS latency limit is still 20 us. Additionally, say that idle
|
||||
state 0 is a polling one. Moving the exit_latency_ns check before the
|
||||
target_residency_ns one causes the loop to terminate in the second
|
||||
iteration, before the target_residency_ns check, so idle state 0 will be
|
||||
returned even though previously state 1 would be returned if there were
|
||||
no imminent timers.
|
||||
|
||||
For this reason, remove the assignment of the predicted_ns value to
|
||||
latency_req from the code.
|
||||
|
||||
Fixes: 5ef499cd571c ("cpuidle: menu: Handle stopped tick more aggressively")
|
||||
Cc: 4.17+ <stable@vger.kernel.org> # 4.17+
|
||||
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
||||
Reviewed-by: Christian Loehle <christian.loehle@arm.com>
|
||||
Link: https://patch.msgid.link/5043159.31r3eYUQgx@rafael.j.wysocki
|
||||
---
|
||||
drivers/cpuidle/governors/menu.c | 29 ++++++++++++-----------------
|
||||
1 file changed, 12 insertions(+), 17 deletions(-)
|
||||
|
||||
--- a/drivers/cpuidle/governors/menu.c
|
||||
+++ b/drivers/cpuidle/governors/menu.c
|
||||
@@ -287,20 +287,15 @@ static int menu_select(struct cpuidle_dr
|
||||
return 0;
|
||||
}
|
||||
|
||||
- if (tick_nohz_tick_stopped()) {
|
||||
- /*
|
||||
- * If the tick is already stopped, the cost of possible short
|
||||
- * idle duration misprediction is much higher, because the CPU
|
||||
- * may be stuck in a shallow idle state for a long time as a
|
||||
- * result of it. In that case say we might mispredict and use
|
||||
- * the known time till the closest timer event for the idle
|
||||
- * state selection.
|
||||
- */
|
||||
- if (predicted_ns < TICK_NSEC)
|
||||
- predicted_ns = data->next_timer_ns;
|
||||
- } else if (latency_req > predicted_ns) {
|
||||
- latency_req = predicted_ns;
|
||||
- }
|
||||
+ /*
|
||||
+ * If the tick is already stopped, the cost of possible short idle
|
||||
+ * duration misprediction is much higher, because the CPU may be stuck
|
||||
+ * in a shallow idle state for a long time as a result of it. In that
|
||||
+ * case, say we might mispredict and use the known time till the closest
|
||||
+ * timer event for the idle state selection.
|
||||
+ */
|
||||
+ if (tick_nohz_tick_stopped() && predicted_ns < TICK_NSEC)
|
||||
+ predicted_ns = data->next_timer_ns;
|
||||
|
||||
/*
|
||||
* Find the idle state with the lowest power while satisfying
|
||||
@@ -316,13 +311,15 @@ static int menu_select(struct cpuidle_dr
|
||||
if (idx == -1)
|
||||
idx = i; /* first enabled state */
|
||||
|
||||
+ if (s->exit_latency_ns > latency_req)
|
||||
+ break;
|
||||
+
|
||||
if (s->target_residency_ns > predicted_ns) {
|
||||
/*
|
||||
* Use a physical idle state, not busy polling, unless
|
||||
* a timer is going to trigger soon enough.
|
||||
*/
|
||||
if ((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) &&
|
||||
- s->exit_latency_ns <= latency_req &&
|
||||
s->target_residency_ns <= data->next_timer_ns) {
|
||||
predicted_ns = s->target_residency_ns;
|
||||
idx = i;
|
||||
@@ -354,8 +351,6 @@ static int menu_select(struct cpuidle_dr
|
||||
|
||||
return idx;
|
||||
}
|
||||
- if (s->exit_latency_ns > latency_req)
|
||||
- break;
|
||||
|
||||
idx = i;
|
||||
}
|
@@ -0,0 +1,57 @@
|
||||
From 28803c739ac24f0b71167c2735fb35d04b19384a Mon Sep 17 00:00:00 2001
|
||||
From: Christoph Paasch <cpaasch@openai.com>
|
||||
Date: Fri, 15 Aug 2025 19:28:19 +0200
|
||||
Subject: mptcp: drop skb if MPTCP skb extension allocation fails
|
||||
|
||||
When skb_ext_add(skb, SKB_EXT_MPTCP) fails in mptcp_incoming_options(),
|
||||
we used to return true, letting the segment proceed through the TCP
|
||||
receive path without a DSS mapping. Such segments can leave inconsistent
|
||||
mapping state and trigger a mid-stream fallback to TCP, which in testing
|
||||
collapsed (by artificially forcing failures in skb_ext_add) throughput
|
||||
to zero.
|
||||
|
||||
Return false instead so the TCP input path drops the skb (see
|
||||
tcp_data_queue() and step-7 processing). This is the safer choice
|
||||
under memory pressure: it preserves MPTCP correctness and provides
|
||||
backpressure to the sender.
|
||||
|
||||
Control packets remain unaffected: ACK updates and DATA_FIN handling
|
||||
happen before attempting the extension allocation, and tcp_reset()
|
||||
continues to ignore the return value.
|
||||
|
||||
With this change, MPTCP continues to work at high throughput if we
|
||||
artificially inject failures into skb_ext_add.
|
||||
|
||||
Fixes: 6787b7e350d3 ("mptcp: avoid processing packet if a subflow reset")
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Christoph Paasch <cpaasch@openai.com>
|
||||
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
|
||||
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
|
||||
Link: https://patch.msgid.link/20250815-net-mptcp-misc-fixes-6-17-rc2-v1-1-521fe9957892@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
net/mptcp/options.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/net/mptcp/options.c
|
||||
+++ b/net/mptcp/options.c
|
||||
@@ -1117,7 +1117,9 @@ static bool add_addr_hmac_valid(struct m
|
||||
return hmac == mp_opt->ahmac;
|
||||
}
|
||||
|
||||
-/* Return false if a subflow has been reset, else return true */
|
||||
+/* Return false in case of error (or subflow has been reset),
|
||||
+ * else return true.
|
||||
+ */
|
||||
bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
||||
@@ -1221,7 +1223,7 @@ bool mptcp_incoming_options(struct sock
|
||||
|
||||
mpext = skb_ext_add(skb, SKB_EXT_MPTCP);
|
||||
if (!mpext)
|
||||
- return true;
|
||||
+ return false;
|
||||
|
||||
memset(mpext, 0, sizeof(*mpext));
|
||||
|
35
debian/patches/patchset-pf/steady/0071-mptcp-pm-kernel-flush-do-not-reset-ADD_ADDR-limit.patch
vendored
Normal file
35
debian/patches/patchset-pf/steady/0071-mptcp-pm-kernel-flush-do-not-reset-ADD_ADDR-limit.patch
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
From c4efb64dbe77b1db336896b9fd151d4f306cf521 Mon Sep 17 00:00:00 2001
|
||||
From: "Matthieu Baerts (NGI0)" <matttbe@kernel.org>
|
||||
Date: Fri, 15 Aug 2025 19:28:20 +0200
|
||||
Subject: mptcp: pm: kernel: flush: do not reset ADD_ADDR limit
|
||||
|
||||
A flush of the MPTCP endpoints should not affect the MPTCP limits. In
|
||||
other words, 'ip mptcp endpoint flush' should not change 'ip mptcp
|
||||
limits'.
|
||||
|
||||
But it was the case: the MPTCP_PM_ATTR_RCV_ADD_ADDRS (add_addr_accepted)
|
||||
limit was reset by accident. Removing the reset of this counter during a
|
||||
flush fixes this issue.
|
||||
|
||||
Fixes: 01cacb00b35c ("mptcp: add netlink-based PM")
|
||||
Cc: stable@vger.kernel.org
|
||||
Reported-by: Thomas Dreibholz <dreibh@simula.no>
|
||||
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/579
|
||||
Reviewed-by: Mat Martineau <martineau@kernel.org>
|
||||
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
|
||||
Link: https://patch.msgid.link/20250815-net-mptcp-misc-fixes-6-17-rc2-v1-2-521fe9957892@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
net/mptcp/pm_kernel.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
--- a/net/mptcp/pm_kernel.c
|
||||
+++ b/net/mptcp/pm_kernel.c
|
||||
@@ -1085,7 +1085,6 @@ static void __flush_addrs(struct list_he
|
||||
static void __reset_counters(struct pm_nl_pernet *pernet)
|
||||
{
|
||||
WRITE_ONCE(pernet->add_addr_signal_max, 0);
|
||||
- WRITE_ONCE(pernet->add_addr_accept_max, 0);
|
||||
WRITE_ONCE(pernet->local_addr_max, 0);
|
||||
pernet->addrs = 0;
|
||||
}
|
45
debian/patches/patchset-pf/steady/0072-mptcp-remove-duplicate-sk_reset_timer-call.patch
vendored
Normal file
45
debian/patches/patchset-pf/steady/0072-mptcp-remove-duplicate-sk_reset_timer-call.patch
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
From 135074416baed33c7e855827cf2d93d7fcb6d057 Mon Sep 17 00:00:00 2001
|
||||
From: Geliang Tang <tanggeliang@kylinos.cn>
|
||||
Date: Fri, 15 Aug 2025 19:28:22 +0200
|
||||
Subject: mptcp: remove duplicate sk_reset_timer call
|
||||
|
||||
sk_reset_timer() was called twice in mptcp_pm_alloc_anno_list.
|
||||
|
||||
Simplify the code by using a 'goto' statement to eliminate the
|
||||
duplication.
|
||||
|
||||
Note that this is not a fix, but it will help backporting the following
|
||||
patch. The same "Fixes" tag has been added for this reason.
|
||||
|
||||
Fixes: 93f323b9cccc ("mptcp: add a new sysctl add_addr_timeout")
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
|
||||
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
|
||||
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
|
||||
Link: https://patch.msgid.link/20250815-net-mptcp-misc-fixes-6-17-rc2-v1-4-521fe9957892@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
net/mptcp/pm.c | 5 ++---
|
||||
1 file changed, 2 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/net/mptcp/pm.c
|
||||
+++ b/net/mptcp/pm.c
|
||||
@@ -353,9 +353,7 @@ bool mptcp_pm_alloc_anno_list(struct mpt
|
||||
if (WARN_ON_ONCE(mptcp_pm_is_kernel(msk)))
|
||||
return false;
|
||||
|
||||
- sk_reset_timer(sk, &add_entry->add_timer,
|
||||
- jiffies + mptcp_get_add_addr_timeout(net));
|
||||
- return true;
|
||||
+ goto reset_timer;
|
||||
}
|
||||
|
||||
add_entry = kmalloc(sizeof(*add_entry), GFP_ATOMIC);
|
||||
@@ -369,6 +367,7 @@ bool mptcp_pm_alloc_anno_list(struct mpt
|
||||
add_entry->retrans_times = 0;
|
||||
|
||||
timer_setup(&add_entry->add_timer, mptcp_pm_add_timer, 0);
|
||||
+reset_timer:
|
||||
sk_reset_timer(sk, &add_entry->add_timer,
|
||||
jiffies + mptcp_get_add_addr_timeout(net));
|
||||
|
@@ -0,0 +1,86 @@
|
||||
From dda31fb26f0ac5d06db5d59daade7e9ced49667a Mon Sep 17 00:00:00 2001
|
||||
From: Geliang Tang <tanggeliang@kylinos.cn>
|
||||
Date: Fri, 15 Aug 2025 19:28:23 +0200
|
||||
Subject: mptcp: disable add_addr retransmission when timeout is 0
|
||||
|
||||
When add_addr_timeout was set to 0, this caused the ADD_ADDR to be
|
||||
retransmitted immediately, which looks like a buggy behaviour. Instead,
|
||||
interpret 0 as "no retransmissions needed".
|
||||
|
||||
The documentation is updated to explicitly state that setting the timeout
|
||||
to 0 disables retransmission.
|
||||
|
||||
Fixes: 93f323b9cccc ("mptcp: add a new sysctl add_addr_timeout")
|
||||
Cc: stable@vger.kernel.org
|
||||
Suggested-by: Matthieu Baerts <matttbe@kernel.org>
|
||||
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
|
||||
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
|
||||
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
|
||||
Link: https://patch.msgid.link/20250815-net-mptcp-misc-fixes-6-17-rc2-v1-5-521fe9957892@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
Documentation/networking/mptcp-sysctl.rst | 2 ++
|
||||
net/mptcp/pm.c | 13 ++++++++++---
|
||||
2 files changed, 12 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/Documentation/networking/mptcp-sysctl.rst
|
||||
+++ b/Documentation/networking/mptcp-sysctl.rst
|
||||
@@ -12,6 +12,8 @@ add_addr_timeout - INTEGER (seconds)
|
||||
resent to an MPTCP peer that has not acknowledged a previous
|
||||
ADD_ADDR message.
|
||||
|
||||
+ Do not retransmit if set to 0.
|
||||
+
|
||||
The default value matches TCP_RTO_MAX. This is a per-namespace
|
||||
sysctl.
|
||||
|
||||
--- a/net/mptcp/pm.c
|
||||
+++ b/net/mptcp/pm.c
|
||||
@@ -274,6 +274,7 @@ static void mptcp_pm_add_timer(struct ti
|
||||
add_timer);
|
||||
struct mptcp_sock *msk = entry->sock;
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
+ unsigned int timeout;
|
||||
|
||||
pr_debug("msk=%p\n", msk);
|
||||
|
||||
@@ -291,6 +292,10 @@ static void mptcp_pm_add_timer(struct ti
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ timeout = mptcp_get_add_addr_timeout(sock_net(sk));
|
||||
+ if (!timeout)
|
||||
+ goto out;
|
||||
+
|
||||
spin_lock_bh(&msk->pm.lock);
|
||||
|
||||
if (!mptcp_pm_should_add_signal_addr(msk)) {
|
||||
@@ -302,7 +307,7 @@ static void mptcp_pm_add_timer(struct ti
|
||||
|
||||
if (entry->retrans_times < ADD_ADDR_RETRANS_MAX)
|
||||
sk_reset_timer(sk, timer,
|
||||
- jiffies + mptcp_get_add_addr_timeout(sock_net(sk)));
|
||||
+ jiffies + timeout);
|
||||
|
||||
spin_unlock_bh(&msk->pm.lock);
|
||||
|
||||
@@ -344,6 +349,7 @@ bool mptcp_pm_alloc_anno_list(struct mpt
|
||||
struct mptcp_pm_add_entry *add_entry = NULL;
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
struct net *net = sock_net(sk);
|
||||
+ unsigned int timeout;
|
||||
|
||||
lockdep_assert_held(&msk->pm.lock);
|
||||
|
||||
@@ -368,8 +374,9 @@ bool mptcp_pm_alloc_anno_list(struct mpt
|
||||
|
||||
timer_setup(&add_entry->add_timer, mptcp_pm_add_timer, 0);
|
||||
reset_timer:
|
||||
- sk_reset_timer(sk, &add_entry->add_timer,
|
||||
- jiffies + mptcp_get_add_addr_timeout(net));
|
||||
+ timeout = mptcp_get_add_addr_timeout(net);
|
||||
+ if (timeout)
|
||||
+ sk_reset_timer(sk, &add_entry->add_timer, jiffies + timeout);
|
||||
|
||||
return true;
|
||||
}
|
217
debian/patches/patchset-pf/steady/0074-usb-xhci-Fix-slot_id-resource-race-conflict.patch
vendored
Normal file
217
debian/patches/patchset-pf/steady/0074-usb-xhci-Fix-slot_id-resource-race-conflict.patch
vendored
Normal file
@@ -0,0 +1,217 @@
|
||||
From 593c5009d3316e756dc882364ac67a78b39332ae Mon Sep 17 00:00:00 2001
|
||||
From: Weitao Wang <WeitaoWang-oc@zhaoxin.com>
|
||||
Date: Tue, 19 Aug 2025 15:58:43 +0300
|
||||
Subject: usb: xhci: Fix slot_id resource race conflict
|
||||
|
||||
xHC controller may immediately reuse a slot_id after it's disabled,
|
||||
giving it to a new enumerating device before the xhci driver freed
|
||||
all resources related to the disabled device.
|
||||
|
||||
In such a scenario, device-A with slot_id equal to 1 is disconnecting
|
||||
while device-B is enumerating, device-B will fail to enumerate in the
|
||||
follow sequence.
|
||||
|
||||
1.[device-A] send disable slot command
|
||||
2.[device-B] send enable slot command
|
||||
3.[device-A] disable slot command completed and wakeup waiting thread
|
||||
4.[device-B] enable slot command completed with slot_id equal to 1 and
|
||||
wakeup waiting thread
|
||||
5.[device-B] driver checks that slot_id is still in use (by device-A) in
|
||||
xhci_alloc_virt_device, and fail to enumerate due to this
|
||||
conflict
|
||||
6.[device-A] xhci->devs[slot_id] set to NULL in xhci_free_virt_device
|
||||
|
||||
To fix driver's slot_id resources conflict, clear xhci->devs[slot_id] and
|
||||
xhci->dcbba->dev_context_ptrs[slot_id] pointers in the interrupt context
|
||||
when disable slot command completes successfully. Simultaneously, adjust
|
||||
function xhci_free_virt_device to accurately handle device release.
|
||||
|
||||
[minor smatch warning and commit message fix -Mathias]
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Fixes: 7faac1953ed1 ("xhci: avoid race between disable slot command and host runtime suspend")
|
||||
Signed-off-by: Weitao Wang <WeitaoWang-oc@zhaoxin.com>
|
||||
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
|
||||
Link: https://lore.kernel.org/r/20250819125844.2042452-2-mathias.nyman@linux.intel.com
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/usb/host/xhci-hub.c | 3 +--
|
||||
drivers/usb/host/xhci-mem.c | 22 +++++++++++-----------
|
||||
drivers/usb/host/xhci-ring.c | 9 +++++++--
|
||||
drivers/usb/host/xhci.c | 21 ++++++++++++++-------
|
||||
drivers/usb/host/xhci.h | 3 ++-
|
||||
5 files changed, 35 insertions(+), 23 deletions(-)
|
||||
|
||||
--- a/drivers/usb/host/xhci-hub.c
|
||||
+++ b/drivers/usb/host/xhci-hub.c
|
||||
@@ -704,8 +704,7 @@ static int xhci_enter_test_mode(struct x
|
||||
if (!xhci->devs[i])
|
||||
continue;
|
||||
|
||||
- retval = xhci_disable_slot(xhci, i);
|
||||
- xhci_free_virt_device(xhci, i);
|
||||
+ retval = xhci_disable_and_free_slot(xhci, i);
|
||||
if (retval)
|
||||
xhci_err(xhci, "Failed to disable slot %d, %d. Enter test mode anyway\n",
|
||||
i, retval);
|
||||
--- a/drivers/usb/host/xhci-mem.c
|
||||
+++ b/drivers/usb/host/xhci-mem.c
|
||||
@@ -865,21 +865,20 @@ free_tts:
|
||||
* will be manipulated by the configure endpoint, allocate device, or update
|
||||
* hub functions while this function is removing the TT entries from the list.
|
||||
*/
|
||||
-void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
|
||||
+void xhci_free_virt_device(struct xhci_hcd *xhci, struct xhci_virt_device *dev,
|
||||
+ int slot_id)
|
||||
{
|
||||
- struct xhci_virt_device *dev;
|
||||
int i;
|
||||
int old_active_eps = 0;
|
||||
|
||||
/* Slot ID 0 is reserved */
|
||||
- if (slot_id == 0 || !xhci->devs[slot_id])
|
||||
+ if (slot_id == 0 || !dev)
|
||||
return;
|
||||
|
||||
- dev = xhci->devs[slot_id];
|
||||
-
|
||||
- xhci->dcbaa->dev_context_ptrs[slot_id] = 0;
|
||||
- if (!dev)
|
||||
- return;
|
||||
+ /* If device ctx array still points to _this_ device, clear it */
|
||||
+ if (dev->out_ctx &&
|
||||
+ xhci->dcbaa->dev_context_ptrs[slot_id] == cpu_to_le64(dev->out_ctx->dma))
|
||||
+ xhci->dcbaa->dev_context_ptrs[slot_id] = 0;
|
||||
|
||||
trace_xhci_free_virt_device(dev);
|
||||
|
||||
@@ -920,8 +919,9 @@ void xhci_free_virt_device(struct xhci_h
|
||||
dev->udev->slot_id = 0;
|
||||
if (dev->rhub_port && dev->rhub_port->slot_id == slot_id)
|
||||
dev->rhub_port->slot_id = 0;
|
||||
- kfree(xhci->devs[slot_id]);
|
||||
- xhci->devs[slot_id] = NULL;
|
||||
+ if (xhci->devs[slot_id] == dev)
|
||||
+ xhci->devs[slot_id] = NULL;
|
||||
+ kfree(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -962,7 +962,7 @@ static void xhci_free_virt_devices_depth
|
||||
out:
|
||||
/* we are now at a leaf device */
|
||||
xhci_debugfs_remove_slot(xhci, slot_id);
|
||||
- xhci_free_virt_device(xhci, slot_id);
|
||||
+ xhci_free_virt_device(xhci, vdev, slot_id);
|
||||
}
|
||||
|
||||
int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
|
||||
--- a/drivers/usb/host/xhci-ring.c
|
||||
+++ b/drivers/usb/host/xhci-ring.c
|
||||
@@ -1592,7 +1592,8 @@ static void xhci_handle_cmd_enable_slot(
|
||||
command->slot_id = 0;
|
||||
}
|
||||
|
||||
-static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id)
|
||||
+static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id,
|
||||
+ u32 cmd_comp_code)
|
||||
{
|
||||
struct xhci_virt_device *virt_dev;
|
||||
struct xhci_slot_ctx *slot_ctx;
|
||||
@@ -1607,6 +1608,10 @@ static void xhci_handle_cmd_disable_slot
|
||||
if (xhci->quirks & XHCI_EP_LIMIT_QUIRK)
|
||||
/* Delete default control endpoint resources */
|
||||
xhci_free_device_endpoint_resources(xhci, virt_dev, true);
|
||||
+ if (cmd_comp_code == COMP_SUCCESS) {
|
||||
+ xhci->dcbaa->dev_context_ptrs[slot_id] = 0;
|
||||
+ xhci->devs[slot_id] = NULL;
|
||||
+ }
|
||||
}
|
||||
|
||||
static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id)
|
||||
@@ -1856,7 +1861,7 @@ static void handle_cmd_completion(struct
|
||||
xhci_handle_cmd_enable_slot(slot_id, cmd, cmd_comp_code);
|
||||
break;
|
||||
case TRB_DISABLE_SLOT:
|
||||
- xhci_handle_cmd_disable_slot(xhci, slot_id);
|
||||
+ xhci_handle_cmd_disable_slot(xhci, slot_id, cmd_comp_code);
|
||||
break;
|
||||
case TRB_CONFIG_EP:
|
||||
if (!cmd->completion)
|
||||
--- a/drivers/usb/host/xhci.c
|
||||
+++ b/drivers/usb/host/xhci.c
|
||||
@@ -3932,8 +3932,7 @@ static int xhci_discover_or_reset_device
|
||||
* Obtaining a new device slot to inform the xHCI host that
|
||||
* the USB device has been reset.
|
||||
*/
|
||||
- ret = xhci_disable_slot(xhci, udev->slot_id);
|
||||
- xhci_free_virt_device(xhci, udev->slot_id);
|
||||
+ ret = xhci_disable_and_free_slot(xhci, udev->slot_id);
|
||||
if (!ret) {
|
||||
ret = xhci_alloc_dev(hcd, udev);
|
||||
if (ret == 1)
|
||||
@@ -4090,7 +4089,7 @@ static void xhci_free_dev(struct usb_hcd
|
||||
xhci_disable_slot(xhci, udev->slot_id);
|
||||
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
- xhci_free_virt_device(xhci, udev->slot_id);
|
||||
+ xhci_free_virt_device(xhci, virt_dev, udev->slot_id);
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
|
||||
}
|
||||
@@ -4139,6 +4138,16 @@ int xhci_disable_slot(struct xhci_hcd *x
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int xhci_disable_and_free_slot(struct xhci_hcd *xhci, u32 slot_id)
|
||||
+{
|
||||
+ struct xhci_virt_device *vdev = xhci->devs[slot_id];
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = xhci_disable_slot(xhci, slot_id);
|
||||
+ xhci_free_virt_device(xhci, vdev, slot_id);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Checks if we have enough host controller resources for the default control
|
||||
* endpoint.
|
||||
@@ -4245,8 +4254,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd,
|
||||
return 1;
|
||||
|
||||
disable_slot:
|
||||
- xhci_disable_slot(xhci, udev->slot_id);
|
||||
- xhci_free_virt_device(xhci, udev->slot_id);
|
||||
+ xhci_disable_and_free_slot(xhci, udev->slot_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -4382,8 +4390,7 @@ static int xhci_setup_device(struct usb_
|
||||
dev_warn(&udev->dev, "Device not responding to setup %s.\n", act);
|
||||
|
||||
mutex_unlock(&xhci->mutex);
|
||||
- ret = xhci_disable_slot(xhci, udev->slot_id);
|
||||
- xhci_free_virt_device(xhci, udev->slot_id);
|
||||
+ ret = xhci_disable_and_free_slot(xhci, udev->slot_id);
|
||||
if (!ret) {
|
||||
if (xhci_alloc_dev(hcd, udev) == 1)
|
||||
xhci_setup_addressable_virt_dev(xhci, udev);
|
||||
--- a/drivers/usb/host/xhci.h
|
||||
+++ b/drivers/usb/host/xhci.h
|
||||
@@ -1791,7 +1791,7 @@ void xhci_dbg_trace(struct xhci_hcd *xhc
|
||||
/* xHCI memory management */
|
||||
void xhci_mem_cleanup(struct xhci_hcd *xhci);
|
||||
int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags);
|
||||
-void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id);
|
||||
+void xhci_free_virt_device(struct xhci_hcd *xhci, struct xhci_virt_device *dev, int slot_id);
|
||||
int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, struct usb_device *udev, gfp_t flags);
|
||||
int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udev);
|
||||
void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci,
|
||||
@@ -1888,6 +1888,7 @@ void xhci_reset_bandwidth(struct usb_hcd
|
||||
int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
|
||||
struct usb_tt *tt, gfp_t mem_flags);
|
||||
int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id);
|
||||
+int xhci_disable_and_free_slot(struct xhci_hcd *xhci, u32 slot_id);
|
||||
int xhci_ext_cap_init(struct xhci_hcd *xhci);
|
||||
|
||||
int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup);
|
@@ -0,0 +1,48 @@
|
||||
From af9d38028438d5893403b1bea8bd493186f8d2b7 Mon Sep 17 00:00:00 2001
|
||||
From: Niklas Neronin <niklas.neronin@linux.intel.com>
|
||||
Date: Tue, 19 Aug 2025 15:58:44 +0300
|
||||
Subject: usb: xhci: fix host not responding after suspend and resume
|
||||
|
||||
Partially revert commit e1db856bd288 ("usb: xhci: remove '0' write to
|
||||
write-1-to-clear register") because the patch cleared the Interrupt Pending
|
||||
bit during interrupt enabling and disabling. The Interrupt Pending bit
|
||||
should only be cleared when the driver has handled the interrupt.
|
||||
|
||||
Ideally, all interrupts should be handled before disabling the interrupt;
|
||||
consequently, no interrupt should be pending when enabling the interrupt.
|
||||
For this reason, keep the debug message informing if an interrupt is still
|
||||
pending when an interrupt is disabled.
|
||||
|
||||
Because the Interrupt Pending bit is write-1-to-clear, writing '0' to it
|
||||
ensures that the state does not change.
|
||||
|
||||
Link: https://lore.kernel.org/linux-usb/20250818231103.672ec7ed@foxbook
|
||||
Fixes: e1db856bd288 ("usb: xhci: remove '0' write to write-1-to-clear register")
|
||||
Closes: https://bbs.archlinux.org/viewtopic.php?id=307641
|
||||
cc: stable@vger.kernel.org # 6.16+
|
||||
Signed-off-by: Niklas Neronin <niklas.neronin@linux.intel.com>
|
||||
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
|
||||
Link: https://lore.kernel.org/r/20250819125844.2042452-3-mathias.nyman@linux.intel.com
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/usb/host/xhci.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- a/drivers/usb/host/xhci.c
|
||||
+++ b/drivers/usb/host/xhci.c
|
||||
@@ -309,6 +309,7 @@ int xhci_enable_interrupter(struct xhci_
|
||||
return -EINVAL;
|
||||
|
||||
iman = readl(&ir->ir_set->iman);
|
||||
+ iman &= ~IMAN_IP;
|
||||
iman |= IMAN_IE;
|
||||
writel(iman, &ir->ir_set->iman);
|
||||
|
||||
@@ -325,6 +326,7 @@ int xhci_disable_interrupter(struct xhci
|
||||
return -EINVAL;
|
||||
|
||||
iman = readl(&ir->ir_set->iman);
|
||||
+ iman &= ~IMAN_IP;
|
||||
iman &= ~IMAN_IE;
|
||||
writel(iman, &ir->ir_set->iman);
|
||||
|
128
debian/patches/patchset-pf/steady/0076-NFS-Fix-a-race-when-updating-an-existing-write.patch
vendored
Normal file
128
debian/patches/patchset-pf/steady/0076-NFS-Fix-a-race-when-updating-an-existing-write.patch
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
From 89a721716c46752ff3a1e6b4005130aeb22c107e Mon Sep 17 00:00:00 2001
|
||||
From: Trond Myklebust <trond.myklebust@hammerspace.com>
|
||||
Date: Sat, 16 Aug 2025 07:25:20 -0700
|
||||
Subject: NFS: Fix a race when updating an existing write
|
||||
|
||||
After nfs_lock_and_join_requests() tests for whether the request is
|
||||
still attached to the mapping, nothing prevents a call to
|
||||
nfs_inode_remove_request() from succeeding until we actually lock the
|
||||
page group.
|
||||
The reason is that whoever called nfs_inode_remove_request() doesn't
|
||||
necessarily have a lock on the page group head.
|
||||
|
||||
So in order to avoid races, let's take the page group lock earlier in
|
||||
nfs_lock_and_join_requests(), and hold it across the removal of the
|
||||
request in nfs_inode_remove_request().
|
||||
|
||||
Reported-by: Jeff Layton <jlayton@kernel.org>
|
||||
Tested-by: Joe Quanaim <jdq@meta.com>
|
||||
Tested-by: Andrew Steffen <aksteffen@meta.com>
|
||||
Reviewed-by: Jeff Layton <jlayton@kernel.org>
|
||||
Fixes: bd37d6fce184 ("NFSv4: Convert nfs_lock_and_join_requests() to use nfs_page_find_head_request()")
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
|
||||
---
|
||||
fs/nfs/pagelist.c | 9 +++++----
|
||||
fs/nfs/write.c | 29 ++++++++++-------------------
|
||||
include/linux/nfs_page.h | 1 +
|
||||
3 files changed, 16 insertions(+), 23 deletions(-)
|
||||
|
||||
--- a/fs/nfs/pagelist.c
|
||||
+++ b/fs/nfs/pagelist.c
|
||||
@@ -253,13 +253,14 @@ nfs_page_group_unlock(struct nfs_page *r
|
||||
nfs_page_clear_headlock(req);
|
||||
}
|
||||
|
||||
-/*
|
||||
- * nfs_page_group_sync_on_bit_locked
|
||||
+/**
|
||||
+ * nfs_page_group_sync_on_bit_locked - Test if all requests have @bit set
|
||||
+ * @req: request in page group
|
||||
+ * @bit: PG_* bit that is used to sync page group
|
||||
*
|
||||
* must be called with page group lock held
|
||||
*/
|
||||
-static bool
|
||||
-nfs_page_group_sync_on_bit_locked(struct nfs_page *req, unsigned int bit)
|
||||
+bool nfs_page_group_sync_on_bit_locked(struct nfs_page *req, unsigned int bit)
|
||||
{
|
||||
struct nfs_page *head = req->wb_head;
|
||||
struct nfs_page *tmp;
|
||||
--- a/fs/nfs/write.c
|
||||
+++ b/fs/nfs/write.c
|
||||
@@ -153,20 +153,10 @@ nfs_page_set_inode_ref(struct nfs_page *
|
||||
}
|
||||
}
|
||||
|
||||
-static int
|
||||
-nfs_cancel_remove_inode(struct nfs_page *req, struct inode *inode)
|
||||
+static void nfs_cancel_remove_inode(struct nfs_page *req, struct inode *inode)
|
||||
{
|
||||
- int ret;
|
||||
-
|
||||
- if (!test_bit(PG_REMOVE, &req->wb_flags))
|
||||
- return 0;
|
||||
- ret = nfs_page_group_lock(req);
|
||||
- if (ret)
|
||||
- return ret;
|
||||
if (test_and_clear_bit(PG_REMOVE, &req->wb_flags))
|
||||
nfs_page_set_inode_ref(req, inode);
|
||||
- nfs_page_group_unlock(req);
|
||||
- return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -585,19 +575,18 @@ retry:
|
||||
}
|
||||
}
|
||||
|
||||
+ ret = nfs_page_group_lock(head);
|
||||
+ if (ret < 0)
|
||||
+ goto out_unlock;
|
||||
+
|
||||
/* Ensure that nobody removed the request before we locked it */
|
||||
if (head != folio->private) {
|
||||
+ nfs_page_group_unlock(head);
|
||||
nfs_unlock_and_release_request(head);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
- ret = nfs_cancel_remove_inode(head, inode);
|
||||
- if (ret < 0)
|
||||
- goto out_unlock;
|
||||
-
|
||||
- ret = nfs_page_group_lock(head);
|
||||
- if (ret < 0)
|
||||
- goto out_unlock;
|
||||
+ nfs_cancel_remove_inode(head, inode);
|
||||
|
||||
/* lock each request in the page group */
|
||||
for (subreq = head->wb_this_page;
|
||||
@@ -786,7 +775,8 @@ static void nfs_inode_remove_request(str
|
||||
{
|
||||
struct nfs_inode *nfsi = NFS_I(nfs_page_to_inode(req));
|
||||
|
||||
- if (nfs_page_group_sync_on_bit(req, PG_REMOVE)) {
|
||||
+ nfs_page_group_lock(req);
|
||||
+ if (nfs_page_group_sync_on_bit_locked(req, PG_REMOVE)) {
|
||||
struct folio *folio = nfs_page_to_folio(req->wb_head);
|
||||
struct address_space *mapping = folio->mapping;
|
||||
|
||||
@@ -798,6 +788,7 @@ static void nfs_inode_remove_request(str
|
||||
}
|
||||
spin_unlock(&mapping->i_private_lock);
|
||||
}
|
||||
+ nfs_page_group_unlock(req);
|
||||
|
||||
if (test_and_clear_bit(PG_INODE_REF, &req->wb_flags)) {
|
||||
atomic_long_dec(&nfsi->nrequests);
|
||||
--- a/include/linux/nfs_page.h
|
||||
+++ b/include/linux/nfs_page.h
|
||||
@@ -160,6 +160,7 @@ extern void nfs_join_page_group(struct n
|
||||
extern int nfs_page_group_lock(struct nfs_page *);
|
||||
extern void nfs_page_group_unlock(struct nfs_page *);
|
||||
extern bool nfs_page_group_sync_on_bit(struct nfs_page *, unsigned int);
|
||||
+extern bool nfs_page_group_sync_on_bit_locked(struct nfs_page *, unsigned int);
|
||||
extern int nfs_page_set_headlock(struct nfs_page *req);
|
||||
extern void nfs_page_clear_headlock(struct nfs_page *req);
|
||||
extern bool nfs_async_iocounter_wait(struct rpc_task *, struct nfs_lock_context *);
|
102
debian/patches/patchset-pf/steady/0077-kho-init-new_physxa-phys_bits-to-fix-lockdep.patch
vendored
Normal file
102
debian/patches/patchset-pf/steady/0077-kho-init-new_physxa-phys_bits-to-fix-lockdep.patch
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
From cb937c419cee16eb53a09e3c8cc16b675db0214f Mon Sep 17 00:00:00 2001
|
||||
From: Pasha Tatashin <pasha.tatashin@soleen.com>
|
||||
Date: Fri, 8 Aug 2025 20:18:02 +0000
|
||||
Subject: kho: init new_physxa->phys_bits to fix lockdep
|
||||
|
||||
Patch series "Several KHO Hotfixes".
|
||||
|
||||
Three unrelated fixes for Kexec Handover.
|
||||
|
||||
|
||||
This patch (of 3):
|
||||
|
||||
Lockdep shows the following warning:
|
||||
|
||||
INFO: trying to register non-static key. The code is fine but needs
|
||||
lockdep annotation, or maybe you didn't initialize this object before use?
|
||||
turning off the locking correctness validator.
|
||||
|
||||
[<ffffffff810133a6>] dump_stack_lvl+0x66/0xa0
|
||||
[<ffffffff8136012c>] assign_lock_key+0x10c/0x120
|
||||
[<ffffffff81358bb4>] register_lock_class+0xf4/0x2f0
|
||||
[<ffffffff813597ff>] __lock_acquire+0x7f/0x2c40
|
||||
[<ffffffff81360cb0>] ? __pfx_hlock_conflict+0x10/0x10
|
||||
[<ffffffff811707be>] ? native_flush_tlb_global+0x8e/0xa0
|
||||
[<ffffffff8117096e>] ? __flush_tlb_all+0x4e/0xa0
|
||||
[<ffffffff81172fc2>] ? __kernel_map_pages+0x112/0x140
|
||||
[<ffffffff813ec327>] ? xa_load_or_alloc+0x67/0xe0
|
||||
[<ffffffff81359556>] lock_acquire+0xe6/0x280
|
||||
[<ffffffff813ec327>] ? xa_load_or_alloc+0x67/0xe0
|
||||
[<ffffffff8100b9e0>] _raw_spin_lock+0x30/0x40
|
||||
[<ffffffff813ec327>] ? xa_load_or_alloc+0x67/0xe0
|
||||
[<ffffffff813ec327>] xa_load_or_alloc+0x67/0xe0
|
||||
[<ffffffff813eb4c0>] kho_preserve_folio+0x90/0x100
|
||||
[<ffffffff813ebb7f>] __kho_finalize+0xcf/0x400
|
||||
[<ffffffff813ebef4>] kho_finalize+0x34/0x70
|
||||
|
||||
This is becase xa has its own lock, that is not initialized in
|
||||
xa_load_or_alloc.
|
||||
|
||||
Modifiy __kho_preserve_order(), to properly call
|
||||
xa_init(&new_physxa->phys_bits);
|
||||
|
||||
Link: https://lkml.kernel.org/r/20250808201804.772010-2-pasha.tatashin@soleen.com
|
||||
Fixes: fc33e4b44b27 ("kexec: enable KHO support for memory preservation")
|
||||
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
|
||||
Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
|
||||
Cc: Alexander Graf <graf@amazon.com>
|
||||
Cc: Arnd Bergmann <arnd@arndb.de>
|
||||
Cc: Baoquan He <bhe@redhat.com>
|
||||
Cc: Changyuan Lyu <changyuanl@google.com>
|
||||
Cc: Coiby Xu <coxu@redhat.com>
|
||||
Cc: Dave Vasilevsky <dave@vasilevsky.ca>
|
||||
Cc: Eric Biggers <ebiggers@google.com>
|
||||
Cc: Kees Cook <kees@kernel.org>
|
||||
Cc: Pratyush Yadav <pratyush@kernel.org>
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
---
|
||||
kernel/kexec_handover.c | 28 ++++++++++++++++++++++++----
|
||||
1 file changed, 24 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/kernel/kexec_handover.c
|
||||
+++ b/kernel/kexec_handover.c
|
||||
@@ -144,14 +144,34 @@ static int __kho_preserve_order(struct k
|
||||
unsigned int order)
|
||||
{
|
||||
struct kho_mem_phys_bits *bits;
|
||||
- struct kho_mem_phys *physxa;
|
||||
+ struct kho_mem_phys *physxa, *new_physxa;
|
||||
const unsigned long pfn_high = pfn >> order;
|
||||
|
||||
might_sleep();
|
||||
|
||||
- physxa = xa_load_or_alloc(&track->orders, order, sizeof(*physxa));
|
||||
- if (IS_ERR(physxa))
|
||||
- return PTR_ERR(physxa);
|
||||
+ physxa = xa_load(&track->orders, order);
|
||||
+ if (!physxa) {
|
||||
+ int err;
|
||||
+
|
||||
+ new_physxa = kzalloc(sizeof(*physxa), GFP_KERNEL);
|
||||
+ if (!new_physxa)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ xa_init(&new_physxa->phys_bits);
|
||||
+ physxa = xa_cmpxchg(&track->orders, order, NULL, new_physxa,
|
||||
+ GFP_KERNEL);
|
||||
+
|
||||
+ err = xa_err(physxa);
|
||||
+ if (err || physxa) {
|
||||
+ xa_destroy(&new_physxa->phys_bits);
|
||||
+ kfree(new_physxa);
|
||||
+
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+ } else {
|
||||
+ physxa = new_physxa;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
bits = xa_load_or_alloc(&physxa->phys_bits, pfn_high / PRESERVE_BITS,
|
||||
sizeof(*bits));
|
44
debian/patches/patchset-pf/steady/0078-kho-mm-don-t-allow-deferred-struct-page-with-KHO.patch
vendored
Normal file
44
debian/patches/patchset-pf/steady/0078-kho-mm-don-t-allow-deferred-struct-page-with-KHO.patch
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
From 8f64c65c577701d4f11d4aa6b487126d52a471c5 Mon Sep 17 00:00:00 2001
|
||||
From: Pasha Tatashin <pasha.tatashin@soleen.com>
|
||||
Date: Fri, 8 Aug 2025 20:18:03 +0000
|
||||
Subject: kho: mm: don't allow deferred struct page with KHO
|
||||
|
||||
KHO uses struct pages for the preserved memory early in boot, however,
|
||||
with deferred struct page initialization, only a small portion of memory
|
||||
has properly initialized struct pages.
|
||||
|
||||
This problem was detected where vmemmap is poisoned, and illegal flag
|
||||
combinations are detected.
|
||||
|
||||
Don't allow them to be enabled together, and later we will have to teach
|
||||
KHO to work properly with deferred struct page init kernel feature.
|
||||
|
||||
Link: https://lkml.kernel.org/r/20250808201804.772010-3-pasha.tatashin@soleen.com
|
||||
Fixes: 4e1d010e3bda ("kexec: add config option for KHO")
|
||||
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
|
||||
Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
|
||||
Acked-by: Pratyush Yadav <pratyush@kernel.org>
|
||||
Cc: Alexander Graf <graf@amazon.com>
|
||||
Cc: Arnd Bergmann <arnd@arndb.de>
|
||||
Cc: Baoquan He <bhe@redhat.com>
|
||||
Cc: Changyuan Lyu <changyuanl@google.com>
|
||||
Cc: Coiby Xu <coxu@redhat.com>
|
||||
Cc: Dave Vasilevsky <dave@vasilevsky.ca>
|
||||
Cc: Eric Biggers <ebiggers@google.com>
|
||||
Cc: Kees Cook <kees@kernel.org>
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
---
|
||||
kernel/Kconfig.kexec | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/kernel/Kconfig.kexec
|
||||
+++ b/kernel/Kconfig.kexec
|
||||
@@ -97,6 +97,7 @@ config KEXEC_JUMP
|
||||
config KEXEC_HANDOVER
|
||||
bool "kexec handover"
|
||||
depends on ARCH_SUPPORTS_KEXEC_HANDOVER && ARCH_SUPPORTS_KEXEC_FILE
|
||||
+ depends on !DEFERRED_STRUCT_PAGE_INIT
|
||||
select MEMBLOCK_KHO_SCRATCH
|
||||
select KEXEC_FILE
|
||||
select DEBUG_FS
|
39
debian/patches/patchset-pf/steady/0079-kho-warn-if-KHO-is-disabled-due-to-an-error.patch
vendored
Normal file
39
debian/patches/patchset-pf/steady/0079-kho-warn-if-KHO-is-disabled-due-to-an-error.patch
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
From b784ab2867996b84098abc798052aa503d981745 Mon Sep 17 00:00:00 2001
|
||||
From: Pasha Tatashin <pasha.tatashin@soleen.com>
|
||||
Date: Fri, 8 Aug 2025 20:18:04 +0000
|
||||
Subject: kho: warn if KHO is disabled due to an error
|
||||
|
||||
During boot scratch area is allocated based on command line parameters or
|
||||
auto calculated. However, scratch area may fail to allocate, and in that
|
||||
case KHO is disabled. Currently, no warning is printed that KHO is
|
||||
disabled, which makes it confusing for the end user to figure out why KHO
|
||||
is not available. Add the missing warning message.
|
||||
|
||||
Link: https://lkml.kernel.org/r/20250808201804.772010-4-pasha.tatashin@soleen.com
|
||||
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
|
||||
Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
|
||||
Acked-by: Pratyush Yadav <pratyush@kernel.org>
|
||||
Cc: Alexander Graf <graf@amazon.com>
|
||||
Cc: Arnd Bergmann <arnd@arndb.de>
|
||||
Cc: Baoquan He <bhe@redhat.com>
|
||||
Cc: Changyuan Lyu <changyuanl@google.com>
|
||||
Cc: Coiby Xu <coxu@redhat.com>
|
||||
Cc: Dave Vasilevsky <dave@vasilevsky.ca>
|
||||
Cc: Eric Biggers <ebiggers@google.com>
|
||||
Cc: Kees Cook <kees@kernel.org>
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
---
|
||||
kernel/kexec_handover.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/kernel/kexec_handover.c
|
||||
+++ b/kernel/kexec_handover.c
|
||||
@@ -564,6 +564,7 @@ err_free_scratch_areas:
|
||||
err_free_scratch_desc:
|
||||
memblock_free(kho_scratch, kho_scratch_cnt * sizeof(*kho_scratch));
|
||||
err_disable_kho:
|
||||
+ pr_warn("Failed to reserve scratch area, disabling kexec handover\n");
|
||||
kho_enable = false;
|
||||
}
|
||||
|
55
debian/patches/patchset-pf/steady/0080-squashfs-fix-memory-leak-in-squashfs_fill_super.patch
vendored
Normal file
55
debian/patches/patchset-pf/steady/0080-squashfs-fix-memory-leak-in-squashfs_fill_super.patch
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
From ef787512b2a3a79de6aac63c9b715cd8791594e5 Mon Sep 17 00:00:00 2001
|
||||
From: Phillip Lougher <phillip@squashfs.org.uk>
|
||||
Date: Mon, 11 Aug 2025 23:37:40 +0100
|
||||
Subject: squashfs: fix memory leak in squashfs_fill_super
|
||||
|
||||
If sb_min_blocksize returns 0, squashfs_fill_super exits without freeing
|
||||
allocated memory (sb->s_fs_info).
|
||||
|
||||
Fix this by moving the call to sb_min_blocksize to before memory is
|
||||
allocated.
|
||||
|
||||
Link: https://lkml.kernel.org/r/20250811223740.110392-1-phillip@squashfs.org.uk
|
||||
Fixes: 734aa85390ea ("Squashfs: check return result of sb_min_blocksize")
|
||||
Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
|
||||
Reported-by: Scott GUO <scottzhguo@tencent.com>
|
||||
Closes: https://lore.kernel.org/all/20250811061921.3807353-1-scott_gzh@163.com
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
---
|
||||
fs/squashfs/super.c | 14 +++++++-------
|
||||
1 file changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/fs/squashfs/super.c
|
||||
+++ b/fs/squashfs/super.c
|
||||
@@ -187,10 +187,15 @@ static int squashfs_fill_super(struct su
|
||||
unsigned short flags;
|
||||
unsigned int fragments;
|
||||
u64 lookup_table_start, xattr_id_table_start, next_table;
|
||||
- int err;
|
||||
+ int err, devblksize = sb_min_blocksize(sb, SQUASHFS_DEVBLK_SIZE);
|
||||
|
||||
TRACE("Entered squashfs_fill_superblock\n");
|
||||
|
||||
+ if (!devblksize) {
|
||||
+ errorf(fc, "squashfs: unable to set blocksize\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
sb->s_fs_info = kzalloc(sizeof(*msblk), GFP_KERNEL);
|
||||
if (sb->s_fs_info == NULL) {
|
||||
ERROR("Failed to allocate squashfs_sb_info\n");
|
||||
@@ -201,12 +206,7 @@ static int squashfs_fill_super(struct su
|
||||
|
||||
msblk->panic_on_errors = (opts->errors == Opt_errors_panic);
|
||||
|
||||
- msblk->devblksize = sb_min_blocksize(sb, SQUASHFS_DEVBLK_SIZE);
|
||||
- if (!msblk->devblksize) {
|
||||
- errorf(fc, "squashfs: unable to set blocksize\n");
|
||||
- return -EINVAL;
|
||||
- }
|
||||
-
|
||||
+ msblk->devblksize = devblksize;
|
||||
msblk->devblksize_log2 = ffz(~msblk->devblksize);
|
||||
|
||||
mutex_init(&msblk->meta_index_mutex);
|
140
debian/patches/patchset-pf/steady/0081-mm-debug_vm_pgtable-clear-page-table-entries-at-dest.patch
vendored
Normal file
140
debian/patches/patchset-pf/steady/0081-mm-debug_vm_pgtable-clear-page-table-entries-at-dest.patch
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
From 94ccad3e78c9f1a90526b8ca4301d5e5c2df0f88 Mon Sep 17 00:00:00 2001
|
||||
From: "Herton R. Krzesinski" <herton@redhat.com>
|
||||
Date: Thu, 31 Jul 2025 18:40:51 -0300
|
||||
Subject: mm/debug_vm_pgtable: clear page table entries at destroy_args()
|
||||
|
||||
The mm/debug_vm_pagetable test allocates manually page table entries for
|
||||
the tests it runs, using also its manually allocated mm_struct. That in
|
||||
itself is ok, but when it exits, at destroy_args() it fails to clear those
|
||||
entries with the *_clear functions.
|
||||
|
||||
The problem is that leaves stale entries. If another process allocates an
|
||||
mm_struct with a pgd at the same address, it may end up running into the
|
||||
stale entry. This is happening in practice on a debug kernel with
|
||||
CONFIG_DEBUG_VM_PGTABLE=y, for example this is the output with some extra
|
||||
debugging I added (it prints a warning trace if pgtables_bytes goes
|
||||
negative, in addition to the warning at check_mm() function):
|
||||
|
||||
[ 2.539353] debug_vm_pgtable: [get_random_vaddr ]: random_vaddr is 0x7ea247140000
|
||||
[ 2.539366] kmem_cache info
|
||||
[ 2.539374] kmem_cachep 0x000000002ce82385 - freelist 0x0000000000000000 - offset 0x508
|
||||
[ 2.539447] debug_vm_pgtable: [init_args ]: args->mm is 0x000000002267cc9e
|
||||
(...)
|
||||
[ 2.552800] WARNING: CPU: 5 PID: 116 at include/linux/mm.h:2841 free_pud_range+0x8bc/0x8d0
|
||||
[ 2.552816] Modules linked in:
|
||||
[ 2.552843] CPU: 5 UID: 0 PID: 116 Comm: modprobe Not tainted 6.12.0-105.debug_vm2.el10.ppc64le+debug #1 VOLUNTARY
|
||||
[ 2.552859] Hardware name: IBM,9009-41A POWER9 (architected) 0x4e0202 0xf000005 of:IBM,FW910.00 (VL910_062) hv:phyp pSeries
|
||||
[ 2.552872] NIP: c0000000007eef3c LR: c0000000007eef30 CTR: c0000000003d8c90
|
||||
[ 2.552885] REGS: c0000000622e73b0 TRAP: 0700 Not tainted (6.12.0-105.debug_vm2.el10.ppc64le+debug)
|
||||
[ 2.552899] MSR: 800000000282b033 <SF,VEC,VSX,EE,FP,ME,IR,DR,RI,LE> CR: 24002822 XER: 0000000a
|
||||
[ 2.552954] CFAR: c0000000008f03f0 IRQMASK: 0
|
||||
[ 2.552954] GPR00: c0000000007eef30 c0000000622e7650 c000000002b1ac00 0000000000000001
|
||||
[ 2.552954] GPR04: 0000000000000008 0000000000000000 c0000000007eef30 ffffffffffffffff
|
||||
[ 2.552954] GPR08: 00000000ffff00f5 0000000000000001 0000000000000048 0000000000004000
|
||||
[ 2.552954] GPR12: 00000003fa440000 c000000017ffa300 c0000000051d9f80 ffffffffffffffdb
|
||||
[ 2.552954] GPR16: 0000000000000000 0000000000000008 000000000000000a 60000000000000e0
|
||||
[ 2.552954] GPR20: 4080000000000000 c0000000113af038 00007fffcf130000 0000700000000000
|
||||
[ 2.552954] GPR24: c000000062a6a000 0000000000000001 8000000062a68000 0000000000000001
|
||||
[ 2.552954] GPR28: 000000000000000a c000000062ebc600 0000000000002000 c000000062ebc760
|
||||
[ 2.553170] NIP [c0000000007eef3c] free_pud_range+0x8bc/0x8d0
|
||||
[ 2.553185] LR [c0000000007eef30] free_pud_range+0x8b0/0x8d0
|
||||
[ 2.553199] Call Trace:
|
||||
[ 2.553207] [c0000000622e7650] [c0000000007eef30] free_pud_range+0x8b0/0x8d0 (unreliable)
|
||||
[ 2.553229] [c0000000622e7750] [c0000000007f40b4] free_pgd_range+0x284/0x3b0
|
||||
[ 2.553248] [c0000000622e7800] [c0000000007f4630] free_pgtables+0x450/0x570
|
||||
[ 2.553274] [c0000000622e78e0] [c0000000008161c0] exit_mmap+0x250/0x650
|
||||
[ 2.553292] [c0000000622e7a30] [c0000000001b95b8] __mmput+0x98/0x290
|
||||
[ 2.558344] [c0000000622e7a80] [c0000000001d1018] exit_mm+0x118/0x1b0
|
||||
[ 2.558361] [c0000000622e7ac0] [c0000000001d141c] do_exit+0x2ec/0x870
|
||||
[ 2.558376] [c0000000622e7b60] [c0000000001d1ca8] do_group_exit+0x88/0x150
|
||||
[ 2.558391] [c0000000622e7bb0] [c0000000001d1db8] sys_exit_group+0x48/0x50
|
||||
[ 2.558407] [c0000000622e7be0] [c00000000003d810] system_call_exception+0x1e0/0x4c0
|
||||
[ 2.558423] [c0000000622e7e50] [c00000000000d05c] system_call_vectored_common+0x15c/0x2ec
|
||||
(...)
|
||||
[ 2.558892] ---[ end trace 0000000000000000 ]---
|
||||
[ 2.559022] BUG: Bad rss-counter state mm:000000002267cc9e type:MM_ANONPAGES val:1
|
||||
[ 2.559037] BUG: non-zero pgtables_bytes on freeing mm: -6144
|
||||
|
||||
Here the modprobe process ended up with an allocated mm_struct from the
|
||||
mm_struct slab that was used before by the debug_vm_pgtable test. That is
|
||||
not a problem, since the mm_struct is initialized again etc., however, if
|
||||
it ends up using the same pgd table, it bumps into the old stale entry
|
||||
when clearing/freeing the page table entries, so it tries to free an entry
|
||||
already gone (that one which was allocated by the debug_vm_pgtable test),
|
||||
which also explains the negative pgtables_bytes since it's accounting for
|
||||
not allocated entries in the current process.
|
||||
|
||||
As far as I looked pgd_{alloc,free} etc. does not clear entries, and
|
||||
clearing of the entries is explicitly done in the free_pgtables->
|
||||
free_pgd_range->free_p4d_range->free_pud_range->free_pmd_range->
|
||||
free_pte_range path. However, the debug_vm_pgtable test does not call
|
||||
free_pgtables, since it allocates mm_struct and entries manually for its
|
||||
test and eg. not goes through page faults. So it also should clear
|
||||
manually the entries before exit at destroy_args().
|
||||
|
||||
This problem was noticed on a reboot X number of times test being done on
|
||||
a powerpc host, with a debug kernel with CONFIG_DEBUG_VM_PGTABLE enabled.
|
||||
Depends on the system, but on a 100 times reboot loop the problem could
|
||||
manifest once or twice, if a process ends up getting the right mm->pgd
|
||||
entry with the stale entries used by mm/debug_vm_pagetable. After using
|
||||
this patch, I couldn't reproduce/experience the problems anymore. I was
|
||||
able to reproduce the problem as well on latest upstream kernel (6.16).
|
||||
|
||||
I also modified destroy_args() to use mmput() instead of mmdrop(), there
|
||||
is no reason to hold mm_users reference and not release the mm_struct
|
||||
entirely, and in the output above with my debugging prints I already had
|
||||
patched it to use mmput, it did not fix the problem, but helped in the
|
||||
debugging as well.
|
||||
|
||||
Link: https://lkml.kernel.org/r/20250731214051.4115182-1-herton@redhat.com
|
||||
Fixes: 3c9b84f044a9 ("mm/debug_vm_pgtable: introduce struct pgtable_debug_args")
|
||||
Signed-off-by: Herton R. Krzesinski <herton@redhat.com>
|
||||
Cc: Anshuman Khandual <anshuman.khandual@arm.com>
|
||||
Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
|
||||
Cc: Gavin Shan <gshan@redhat.com>
|
||||
Cc: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
---
|
||||
mm/debug_vm_pgtable.c | 9 +++++++--
|
||||
1 file changed, 7 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/mm/debug_vm_pgtable.c
|
||||
+++ b/mm/debug_vm_pgtable.c
|
||||
@@ -1041,29 +1041,34 @@ static void __init destroy_args(struct p
|
||||
|
||||
/* Free page table entries */
|
||||
if (args->start_ptep) {
|
||||
+ pmd_clear(args->pmdp);
|
||||
pte_free(args->mm, args->start_ptep);
|
||||
mm_dec_nr_ptes(args->mm);
|
||||
}
|
||||
|
||||
if (args->start_pmdp) {
|
||||
+ pud_clear(args->pudp);
|
||||
pmd_free(args->mm, args->start_pmdp);
|
||||
mm_dec_nr_pmds(args->mm);
|
||||
}
|
||||
|
||||
if (args->start_pudp) {
|
||||
+ p4d_clear(args->p4dp);
|
||||
pud_free(args->mm, args->start_pudp);
|
||||
mm_dec_nr_puds(args->mm);
|
||||
}
|
||||
|
||||
- if (args->start_p4dp)
|
||||
+ if (args->start_p4dp) {
|
||||
+ pgd_clear(args->pgdp);
|
||||
p4d_free(args->mm, args->start_p4dp);
|
||||
+ }
|
||||
|
||||
/* Free vma and mm struct */
|
||||
if (args->vma)
|
||||
vm_area_free(args->vma);
|
||||
|
||||
if (args->mm)
|
||||
- mmdrop(args->mm);
|
||||
+ mmput(args->mm);
|
||||
}
|
||||
|
||||
static struct page * __init
|
@@ -0,0 +1,52 @@
|
||||
From 8e0fc5bd3c988e47827d000f51ffa73512a4a5b6 Mon Sep 17 00:00:00 2001
|
||||
From: Sang-Heon Jeon <ekffu200098@gmail.com>
|
||||
Date: Sun, 10 Aug 2025 21:42:01 +0900
|
||||
Subject: mm/damon/core: fix commit_ops_filters by using correct nth function
|
||||
|
||||
damos_commit_ops_filters() incorrectly uses damos_nth_filter() which
|
||||
iterates core_filters. As a result, performing a commit unintentionally
|
||||
corrupts ops_filters.
|
||||
|
||||
Add damos_nth_ops_filter() which iterates ops_filters. Use this function
|
||||
to fix issues caused by wrong iteration.
|
||||
|
||||
Link: https://lkml.kernel.org/r/20250810124201.15743-1-ekffu200098@gmail.com
|
||||
Fixes: 3607cc590f18 ("mm/damon/core: support committing ops_filters") # 6.15.x
|
||||
Signed-off-by: Sang-Heon Jeon <ekffu200098@gmail.com>
|
||||
Reviewed-by: SeongJae Park <sj@kernel.org>
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
---
|
||||
mm/damon/core.c | 14 +++++++++++++-
|
||||
1 file changed, 13 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/mm/damon/core.c
|
||||
+++ b/mm/damon/core.c
|
||||
@@ -843,6 +843,18 @@ static struct damos_filter *damos_nth_fi
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+static struct damos_filter *damos_nth_ops_filter(int n, struct damos *s)
|
||||
+{
|
||||
+ struct damos_filter *filter;
|
||||
+ int i = 0;
|
||||
+
|
||||
+ damos_for_each_ops_filter(filter, s) {
|
||||
+ if (i++ == n)
|
||||
+ return filter;
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
static void damos_commit_filter_arg(
|
||||
struct damos_filter *dst, struct damos_filter *src)
|
||||
{
|
||||
@@ -906,7 +918,7 @@ static int damos_commit_ops_filters(stru
|
||||
int i = 0, j = 0;
|
||||
|
||||
damos_for_each_ops_filter_safe(dst_filter, next, dst) {
|
||||
- src_filter = damos_nth_filter(i++, src);
|
||||
+ src_filter = damos_nth_ops_filter(i++, src);
|
||||
if (src_filter)
|
||||
damos_commit_filter(dst_filter, src_filter);
|
||||
else
|
@@ -0,0 +1,77 @@
|
||||
From 0623d1f6690209880885deae614e8368488598c2 Mon Sep 17 00:00:00 2001
|
||||
From: Dominique Martinet <asmadeus@codewreck.org>
|
||||
Date: Wed, 13 Aug 2025 15:04:55 +0900
|
||||
Subject: iov_iter: iterate_folioq: fix handling of offset >= folio size
|
||||
|
||||
It's apparently possible to get an iov advanced all the way up to the end
|
||||
of the current page we're looking at, e.g.
|
||||
|
||||
(gdb) p *iter
|
||||
$24 = {iter_type = 4 '\004', nofault = false, data_source = false, iov_offset = 4096, {__ubuf_iovec = {
|
||||
iov_base = 0xffff88800f5bc000, iov_len = 655}, {{__iov = 0xffff88800f5bc000, kvec = 0xffff88800f5bc000,
|
||||
bvec = 0xffff88800f5bc000, folioq = 0xffff88800f5bc000, xarray = 0xffff88800f5bc000,
|
||||
ubuf = 0xffff88800f5bc000}, count = 655}}, {nr_segs = 2, folioq_slot = 2 '\002', xarray_start = 2}}
|
||||
|
||||
Where iov_offset is 4k with 4k-sized folios
|
||||
|
||||
This should have been fine because we're only in the 2nd slot and there's
|
||||
another one after this, but iterate_folioq should not try to map a folio
|
||||
that skips the whole size, and more importantly part here does not end up
|
||||
zero (because 'PAGE_SIZE - skip % PAGE_SIZE' ends up PAGE_SIZE and not
|
||||
zero..), so skip forward to the "advance to next folio" code
|
||||
|
||||
Link: https://lkml.kernel.org/r/20250813-iot_iter_folio-v3-0-a0ffad2b665a@codewreck.org
|
||||
Link: https://lkml.kernel.org/r/20250813-iot_iter_folio-v3-1-a0ffad2b665a@codewreck.org
|
||||
Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
|
||||
Fixes: db0aa2e9566f ("mm: Define struct folio_queue and ITER_FOLIOQ to handle a sequence of folios")
|
||||
Reported-by: Maximilian Bosch <maximilian@mbosch.me>
|
||||
Reported-by: Ryan Lahfa <ryan@lahfa.xyz>
|
||||
Reported-by: Christian Theune <ct@flyingcircus.io>
|
||||
Reported-by: Arnout Engelen <arnout@bzzt.net>
|
||||
Link: https://lkml.kernel.org/r/D4LHHUNLG79Y.12PI0X6BEHRHW@mbosch.me/
|
||||
Acked-by: David Howells <dhowells@redhat.com>
|
||||
Cc: Al Viro <viro@zeniv.linux.org.uk>
|
||||
Cc: Christian Brauner <brauner@kernel.org>
|
||||
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
|
||||
Cc: <stable@vger.kernel.org> [6.12+]
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
---
|
||||
include/linux/iov_iter.h | 20 +++++++++++---------
|
||||
1 file changed, 11 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/include/linux/iov_iter.h
|
||||
+++ b/include/linux/iov_iter.h
|
||||
@@ -160,7 +160,7 @@ size_t iterate_folioq(struct iov_iter *i
|
||||
|
||||
do {
|
||||
struct folio *folio = folioq_folio(folioq, slot);
|
||||
- size_t part, remain, consumed;
|
||||
+ size_t part, remain = 0, consumed;
|
||||
size_t fsize;
|
||||
void *base;
|
||||
|
||||
@@ -168,14 +168,16 @@ size_t iterate_folioq(struct iov_iter *i
|
||||
break;
|
||||
|
||||
fsize = folioq_folio_size(folioq, slot);
|
||||
- base = kmap_local_folio(folio, skip);
|
||||
- part = umin(len, PAGE_SIZE - skip % PAGE_SIZE);
|
||||
- remain = step(base, progress, part, priv, priv2);
|
||||
- kunmap_local(base);
|
||||
- consumed = part - remain;
|
||||
- len -= consumed;
|
||||
- progress += consumed;
|
||||
- skip += consumed;
|
||||
+ if (skip < fsize) {
|
||||
+ base = kmap_local_folio(folio, skip);
|
||||
+ part = umin(len, PAGE_SIZE - skip % PAGE_SIZE);
|
||||
+ remain = step(base, progress, part, priv, priv2);
|
||||
+ kunmap_local(base);
|
||||
+ consumed = part - remain;
|
||||
+ len -= consumed;
|
||||
+ progress += consumed;
|
||||
+ skip += consumed;
|
||||
+ }
|
||||
if (skip >= fsize) {
|
||||
skip = 0;
|
||||
slot++;
|
@@ -0,0 +1,57 @@
|
||||
From 786e39b5e75b7d766b7930519d504a90eaf887da Mon Sep 17 00:00:00 2001
|
||||
From: Jinjiang Tu <tujinjiang@huawei.com>
|
||||
Date: Fri, 15 Aug 2025 15:32:09 +0800
|
||||
Subject: mm/memory-failure: fix infinite UCE for VM_PFNMAP pfn
|
||||
|
||||
When memory_failure() is called for a already hwpoisoned pfn,
|
||||
kill_accessing_process() will be called to kill current task. However, if
|
||||
the vma of the accessing vaddr is VM_PFNMAP, walk_page_range() will skip
|
||||
the vma in walk_page_test() and return 0.
|
||||
|
||||
Before commit aaf99ac2ceb7 ("mm/hwpoison: do not send SIGBUS to processes
|
||||
with recovered clean pages"), kill_accessing_process() will return EFAULT.
|
||||
For x86, the current task will be killed in kill_me_maybe().
|
||||
|
||||
However, after this commit, kill_accessing_process() simplies return 0,
|
||||
that means UCE is handled properly, but it doesn't actually. In such
|
||||
case, the user task will trigger UCE infinitely.
|
||||
|
||||
To fix it, add .test_walk callback for hwpoison_walk_ops to scan all vmas.
|
||||
|
||||
Link: https://lkml.kernel.org/r/20250815073209.1984582-1-tujinjiang@huawei.com
|
||||
Fixes: aaf99ac2ceb7 ("mm/hwpoison: do not send SIGBUS to processes with recovered clean pages")
|
||||
Signed-off-by: Jinjiang Tu <tujinjiang@huawei.com>
|
||||
Acked-by: David Hildenbrand <david@redhat.com>
|
||||
Acked-by: Miaohe Lin <linmiaohe@huawei.com>
|
||||
Reviewed-by: Jane Chu <jane.chu@oracle.com>
|
||||
Cc: Kefeng Wang <wangkefeng.wang@huawei.com>
|
||||
Cc: Naoya Horiguchi <nao.horiguchi@gmail.com>
|
||||
Cc: Oscar Salvador <osalvador@suse.de>
|
||||
Cc: Shuai Xue <xueshuai@linux.alibaba.com>
|
||||
Cc: Zi Yan <ziy@nvidia.com>
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
---
|
||||
mm/memory-failure.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
--- a/mm/memory-failure.c
|
||||
+++ b/mm/memory-failure.c
|
||||
@@ -847,9 +847,17 @@ static int hwpoison_hugetlb_range(pte_t
|
||||
#define hwpoison_hugetlb_range NULL
|
||||
#endif
|
||||
|
||||
+static int hwpoison_test_walk(unsigned long start, unsigned long end,
|
||||
+ struct mm_walk *walk)
|
||||
+{
|
||||
+ /* We also want to consider pages mapped into VM_PFNMAP. */
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static const struct mm_walk_ops hwpoison_walk_ops = {
|
||||
.pmd_entry = hwpoison_pte_range,
|
||||
.hugetlb_entry = hwpoison_hugetlb_range,
|
||||
+ .test_walk = hwpoison_test_walk,
|
||||
.walk_lock = PGWALK_RDLOCK,
|
||||
};
|
||||
|
@@ -0,0 +1,32 @@
|
||||
From 40faa11c480476ef29d74f44c0126026b37d988d Mon Sep 17 00:00:00 2001
|
||||
From: Sang-Heon Jeon <ekffu200098@gmail.com>
|
||||
Date: Sat, 16 Aug 2025 10:51:16 +0900
|
||||
Subject: mm/damon/core: fix damos_commit_filter not changing allow
|
||||
|
||||
Current damos_commit_filter() does not persist the `allow' value of the
|
||||
filter. As a result, changing the `allow' value of a filter and
|
||||
committing doesn't change the `allow' value.
|
||||
|
||||
Add the missing `allow' value update, so committing the filter
|
||||
persistently changes the `allow' value well.
|
||||
|
||||
Link: https://lkml.kernel.org/r/20250816015116.194589-1-ekffu200098@gmail.com
|
||||
Fixes: fe6d7fdd6249 ("mm/damon/core: add damos_filter->allow field")
|
||||
Signed-off-by: Sang-Heon Jeon <ekffu200098@gmail.com>
|
||||
Reviewed-by: SeongJae Park <sj@kernel.org>
|
||||
Cc: <stable@vger.kernel.org> [6.14.x]
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
---
|
||||
mm/damon/core.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/mm/damon/core.c
|
||||
+++ b/mm/damon/core.c
|
||||
@@ -881,6 +881,7 @@ static void damos_commit_filter(
|
||||
{
|
||||
dst->type = src->type;
|
||||
dst->matching = src->matching;
|
||||
+ dst->allow = src->allow;
|
||||
damos_commit_filter_arg(dst, src);
|
||||
}
|
||||
|
157
debian/patches/patchset-pf/steady/0086-mm-mremap-fix-WARN-with-uffd-that-has-remap-events-d.patch
vendored
Normal file
157
debian/patches/patchset-pf/steady/0086-mm-mremap-fix-WARN-with-uffd-that-has-remap-events-d.patch
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
From 148516b367dd591d31a2b98ad913417bc1b9c865 Mon Sep 17 00:00:00 2001
|
||||
From: David Hildenbrand <david@redhat.com>
|
||||
Date: Mon, 18 Aug 2025 19:53:58 +0200
|
||||
Subject: mm/mremap: fix WARN with uffd that has remap events disabled
|
||||
|
||||
Registering userfaultd on a VMA that spans at least one PMD and then
|
||||
mremap()'ing that VMA can trigger a WARN when recovering from a failed
|
||||
page table move due to a page table allocation error.
|
||||
|
||||
The code ends up doing the right thing (recurse, avoiding moving actual
|
||||
page tables), but triggering that WARN is unpleasant:
|
||||
|
||||
WARNING: CPU: 2 PID: 6133 at mm/mremap.c:357 move_normal_pmd mm/mremap.c:357 [inline]
|
||||
WARNING: CPU: 2 PID: 6133 at mm/mremap.c:357 move_pgt_entry mm/mremap.c:595 [inline]
|
||||
WARNING: CPU: 2 PID: 6133 at mm/mremap.c:357 move_page_tables+0x3832/0x44a0 mm/mremap.c:852
|
||||
Modules linked in:
|
||||
CPU: 2 UID: 0 PID: 6133 Comm: syz.0.19 Not tainted 6.17.0-rc1-syzkaller-00004-g53e760d89498 #0 PREEMPT(full)
|
||||
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
|
||||
RIP: 0010:move_normal_pmd mm/mremap.c:357 [inline]
|
||||
RIP: 0010:move_pgt_entry mm/mremap.c:595 [inline]
|
||||
RIP: 0010:move_page_tables+0x3832/0x44a0 mm/mremap.c:852
|
||||
Code: ...
|
||||
RSP: 0018:ffffc900037a76d8 EFLAGS: 00010293
|
||||
RAX: 0000000000000000 RBX: 0000000032930007 RCX: ffffffff820c6645
|
||||
RDX: ffff88802e56a440 RSI: ffffffff820c7201 RDI: 0000000000000007
|
||||
RBP: ffff888037728fc0 R08: 0000000000000007 R09: 0000000000000000
|
||||
R10: 0000000032930007 R11: 0000000000000000 R12: 0000000000000000
|
||||
R13: ffffc900037a79a8 R14: 0000000000000001 R15: dffffc0000000000
|
||||
FS: 000055556316a500(0000) GS:ffff8880d68bc000(0000) knlGS:0000000000000000
|
||||
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
|
||||
CR2: 0000001b30863fff CR3: 0000000050171000 CR4: 0000000000352ef0
|
||||
Call Trace:
|
||||
<TASK>
|
||||
copy_vma_and_data+0x468/0x790 mm/mremap.c:1215
|
||||
move_vma+0x548/0x1780 mm/mremap.c:1282
|
||||
mremap_to+0x1b7/0x450 mm/mremap.c:1406
|
||||
do_mremap+0xfad/0x1f80 mm/mremap.c:1921
|
||||
__do_sys_mremap+0x119/0x170 mm/mremap.c:1977
|
||||
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
|
||||
do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
|
||||
entry_SYSCALL_64_after_hwframe+0x77/0x7f
|
||||
RIP: 0033:0x7f00d0b8ebe9
|
||||
Code: ...
|
||||
RSP: 002b:00007ffe5ea5ee98 EFLAGS: 00000246 ORIG_RAX: 0000000000000019
|
||||
RAX: ffffffffffffffda RBX: 00007f00d0db5fa0 RCX: 00007f00d0b8ebe9
|
||||
RDX: 0000000000400000 RSI: 0000000000c00000 RDI: 0000200000000000
|
||||
RBP: 00007ffe5ea5eef0 R08: 0000200000c00000 R09: 0000000000000000
|
||||
R10: 0000000000000003 R11: 0000000000000246 R12: 0000000000000002
|
||||
R13: 00007f00d0db5fa0 R14: 00007f00d0db5fa0 R15: 0000000000000005
|
||||
</TASK>
|
||||
|
||||
The underlying issue is that we recurse during the original page table
|
||||
move, but not during the recovery move.
|
||||
|
||||
Fix it by checking for both VMAs and performing the check before the
|
||||
pmd_none() sanity check.
|
||||
|
||||
Add a new helper where we perform+document that check for the PMD and PUD
|
||||
level.
|
||||
|
||||
Thanks to Harry for bisecting.
|
||||
|
||||
Link: https://lkml.kernel.org/r/20250818175358.1184757-1-david@redhat.com
|
||||
Fixes: 0cef0bb836e3 ("mm: clear uffd-wp PTE/PMD state on mremap()")
|
||||
Signed-off-by: David Hildenbrand <david@redhat.com>
|
||||
Reported-by: syzbot+4d9a13f0797c46a29e42@syzkaller.appspotmail.com
|
||||
Closes: https://lkml.kernel.org/r/689bb893.050a0220.7f033.013a.GAE@google.com
|
||||
Tested-by: Harry Yoo <harry.yoo@oracle.com>
|
||||
Cc: "Liam R. Howlett" <Liam.Howlett@oracle.com>
|
||||
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
|
||||
Cc: Vlastimil Babka <vbabka@suse.cz>
|
||||
Cc: Jann Horn <jannh@google.com>
|
||||
Cc: Pedro Falcato <pfalcato@suse.de>
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
||||
---
|
||||
mm/mremap.c | 41 +++++++++++++++++++++++------------------
|
||||
1 file changed, 23 insertions(+), 18 deletions(-)
|
||||
|
||||
--- a/mm/mremap.c
|
||||
+++ b/mm/mremap.c
|
||||
@@ -294,6 +294,25 @@ static inline bool arch_supports_page_ta
|
||||
}
|
||||
#endif
|
||||
|
||||
+static inline bool uffd_supports_page_table_move(struct pagetable_move_control *pmc)
|
||||
+{
|
||||
+ /*
|
||||
+ * If we are moving a VMA that has uffd-wp registered but with
|
||||
+ * remap events disabled (new VMA will not be registered with uffd), we
|
||||
+ * need to ensure that the uffd-wp state is cleared from all pgtables.
|
||||
+ * This means recursing into lower page tables in move_page_tables().
|
||||
+ *
|
||||
+ * We might get called with VMAs reversed when recovering from a
|
||||
+ * failed page table move. In that case, the
|
||||
+ * "old"-but-actually-"originally new" VMA during recovery will not have
|
||||
+ * a uffd context. Recursing into lower page tables during the original
|
||||
+ * move but not during the recovery move will cause trouble, because we
|
||||
+ * run into already-existing page tables. So check both VMAs.
|
||||
+ */
|
||||
+ return !vma_has_uffd_without_event_remap(pmc->old) &&
|
||||
+ !vma_has_uffd_without_event_remap(pmc->new);
|
||||
+}
|
||||
+
|
||||
#ifdef CONFIG_HAVE_MOVE_PMD
|
||||
static bool move_normal_pmd(struct pagetable_move_control *pmc,
|
||||
pmd_t *old_pmd, pmd_t *new_pmd)
|
||||
@@ -306,6 +325,8 @@ static bool move_normal_pmd(struct paget
|
||||
|
||||
if (!arch_supports_page_table_move())
|
||||
return false;
|
||||
+ if (!uffd_supports_page_table_move(pmc))
|
||||
+ return false;
|
||||
/*
|
||||
* The destination pmd shouldn't be established, free_pgtables()
|
||||
* should have released it.
|
||||
@@ -332,15 +353,6 @@ static bool move_normal_pmd(struct paget
|
||||
if (WARN_ON_ONCE(!pmd_none(*new_pmd)))
|
||||
return false;
|
||||
|
||||
- /* If this pmd belongs to a uffd vma with remap events disabled, we need
|
||||
- * to ensure that the uffd-wp state is cleared from all pgtables. This
|
||||
- * means recursing into lower page tables in move_page_tables(), and we
|
||||
- * can reuse the existing code if we simply treat the entry as "not
|
||||
- * moved".
|
||||
- */
|
||||
- if (vma_has_uffd_without_event_remap(vma))
|
||||
- return false;
|
||||
-
|
||||
/*
|
||||
* We don't have to worry about the ordering of src and dst
|
||||
* ptlocks because exclusive mmap_lock prevents deadlock.
|
||||
@@ -389,6 +401,8 @@ static bool move_normal_pud(struct paget
|
||||
|
||||
if (!arch_supports_page_table_move())
|
||||
return false;
|
||||
+ if (!uffd_supports_page_table_move(pmc))
|
||||
+ return false;
|
||||
/*
|
||||
* The destination pud shouldn't be established, free_pgtables()
|
||||
* should have released it.
|
||||
@@ -396,15 +410,6 @@ static bool move_normal_pud(struct paget
|
||||
if (WARN_ON_ONCE(!pud_none(*new_pud)))
|
||||
return false;
|
||||
|
||||
- /* If this pud belongs to a uffd vma with remap events disabled, we need
|
||||
- * to ensure that the uffd-wp state is cleared from all pgtables. This
|
||||
- * means recursing into lower page tables in move_page_tables(), and we
|
||||
- * can reuse the existing code if we simply treat the entry as "not
|
||||
- * moved".
|
||||
- */
|
||||
- if (vma_has_uffd_without_event_remap(vma))
|
||||
- return false;
|
||||
-
|
||||
/*
|
||||
* We don't have to worry about the ordering of src and dst
|
||||
* ptlocks because exclusive mmap_lock prevents deadlock.
|
@@ -0,0 +1,31 @@
|
||||
From 33950693dc7b0306b42d8efffbe26bfa5caa478b Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Iwai <tiwai@suse.de>
|
||||
Date: Wed, 20 Aug 2025 07:19:01 +0200
|
||||
Subject: ALSA: hda: tas2781: Fix wrong reference of tasdevice_priv
|
||||
|
||||
During the conversion to unify the calibration data management, the
|
||||
reference to tasdevice_priv was wrongly set to h->hda_priv instead of
|
||||
h->priv. This resulted in memory corruption and crashes eventually.
|
||||
Unfortunately it's a void pointer, hence the compiler couldn't know
|
||||
that it's wrong.
|
||||
|
||||
Fixes: 4fe238513407 ("ALSA: hda/tas2781: Move and unified the calibrated-data getting function for SPI and I2C into the tas2781_hda lib")
|
||||
Link: https://bugzilla.suse.com/show_bug.cgi?id=1248270
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Link: https://patch.msgid.link/20250820051902.4523-1-tiwai@suse.de
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
sound/pci/hda/tas2781_hda_i2c.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/sound/pci/hda/tas2781_hda_i2c.c
|
||||
+++ b/sound/pci/hda/tas2781_hda_i2c.c
|
||||
@@ -287,7 +287,7 @@ static int tas2563_save_calibration(stru
|
||||
efi_char16_t efi_name[TAS2563_CAL_VAR_NAME_MAX];
|
||||
unsigned long max_size = TAS2563_CAL_DATA_SIZE;
|
||||
unsigned char var8[TAS2563_CAL_VAR_NAME_MAX];
|
||||
- struct tasdevice_priv *p = h->hda_priv;
|
||||
+ struct tasdevice_priv *p = h->priv;
|
||||
struct calidata *cd = &p->cali_data;
|
||||
struct cali_reg *r = &cd->cali_reg_array;
|
||||
unsigned int offset = 0;
|
142
debian/patches/patchset-pf/steady/0088-tracing-Remove-unneeded-goto-out-logic.patch
vendored
Normal file
142
debian/patches/patchset-pf/steady/0088-tracing-Remove-unneeded-goto-out-logic.patch
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
From f7a227320aab53c99656f21d40481af89dfb8923 Mon Sep 17 00:00:00 2001
|
||||
From: Steven Rostedt <rostedt@goodmis.org>
|
||||
Date: Fri, 1 Aug 2025 16:37:23 -0400
|
||||
Subject: tracing: Remove unneeded goto out logic
|
||||
|
||||
Several places in the trace.c file there's a goto out where the out is
|
||||
simply a return. There's no reason to jump to the out label if it's not
|
||||
doing any more logic but simply returning from the function.
|
||||
|
||||
Replace the goto outs with a return and remove the out labels.
|
||||
|
||||
Cc: Masami Hiramatsu <mhiramat@kernel.org>
|
||||
Cc: Mark Rutland <mark.rutland@arm.com>
|
||||
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
|
||||
Cc: Andrew Morton <akpm@linux-foundation.org>
|
||||
Link: https://lore.kernel.org/20250801203857.538726745@kernel.org
|
||||
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
|
||||
---
|
||||
kernel/trace/trace.c | 38 +++++++++++++++-----------------------
|
||||
1 file changed, 15 insertions(+), 23 deletions(-)
|
||||
|
||||
--- a/kernel/trace/trace.c
|
||||
+++ b/kernel/trace/trace.c
|
||||
@@ -1846,7 +1846,7 @@ int trace_get_user(struct trace_parser *
|
||||
|
||||
ret = get_user(ch, ubuf++);
|
||||
if (ret)
|
||||
- goto out;
|
||||
+ return ret;
|
||||
|
||||
read++;
|
||||
cnt--;
|
||||
@@ -1860,7 +1860,7 @@ int trace_get_user(struct trace_parser *
|
||||
while (cnt && isspace(ch)) {
|
||||
ret = get_user(ch, ubuf++);
|
||||
if (ret)
|
||||
- goto out;
|
||||
+ return ret;
|
||||
read++;
|
||||
cnt--;
|
||||
}
|
||||
@@ -1870,8 +1870,7 @@ int trace_get_user(struct trace_parser *
|
||||
/* only spaces were written */
|
||||
if (isspace(ch) || !ch) {
|
||||
*ppos += read;
|
||||
- ret = read;
|
||||
- goto out;
|
||||
+ return read;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1879,13 +1878,12 @@ int trace_get_user(struct trace_parser *
|
||||
while (cnt && !isspace(ch) && ch) {
|
||||
if (parser->idx < parser->size - 1)
|
||||
parser->buffer[parser->idx++] = ch;
|
||||
- else {
|
||||
- ret = -EINVAL;
|
||||
- goto out;
|
||||
- }
|
||||
+ else
|
||||
+ return -EINVAL;
|
||||
+
|
||||
ret = get_user(ch, ubuf++);
|
||||
if (ret)
|
||||
- goto out;
|
||||
+ return ret;
|
||||
read++;
|
||||
cnt--;
|
||||
}
|
||||
@@ -1900,15 +1898,11 @@ int trace_get_user(struct trace_parser *
|
||||
/* Make sure the parsed string always terminates with '\0'. */
|
||||
parser->buffer[parser->idx] = 0;
|
||||
} else {
|
||||
- ret = -EINVAL;
|
||||
- goto out;
|
||||
+ return -EINVAL;
|
||||
}
|
||||
|
||||
*ppos += read;
|
||||
- ret = read;
|
||||
-
|
||||
-out:
|
||||
- return ret;
|
||||
+ return read;
|
||||
}
|
||||
|
||||
/* TODO add a seq_buf_to_buffer() */
|
||||
@@ -2410,10 +2404,10 @@ int __init register_tracer(struct tracer
|
||||
mutex_unlock(&trace_types_lock);
|
||||
|
||||
if (ret || !default_bootup_tracer)
|
||||
- goto out_unlock;
|
||||
+ return ret;
|
||||
|
||||
if (strncmp(default_bootup_tracer, type->name, MAX_TRACER_SIZE))
|
||||
- goto out_unlock;
|
||||
+ return 0;
|
||||
|
||||
printk(KERN_INFO "Starting tracer '%s'\n", type->name);
|
||||
/* Do we want this tracer to start on bootup? */
|
||||
@@ -2425,8 +2419,7 @@ int __init register_tracer(struct tracer
|
||||
/* disable other selftests, since this will break it. */
|
||||
disable_tracing_selftest("running a tracer");
|
||||
|
||||
- out_unlock:
|
||||
- return ret;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static void tracing_reset_cpu(struct array_buffer *buf, int cpu)
|
||||
@@ -8954,12 +8947,12 @@ ftrace_trace_snapshot_callback(struct tr
|
||||
out_reg:
|
||||
ret = tracing_arm_snapshot(tr);
|
||||
if (ret < 0)
|
||||
- goto out;
|
||||
+ return ret;
|
||||
|
||||
ret = register_ftrace_function_probe(glob, tr, ops, count);
|
||||
if (ret < 0)
|
||||
tracing_disarm_snapshot(tr);
|
||||
- out:
|
||||
+
|
||||
return ret < 0 ? ret : 0;
|
||||
}
|
||||
|
||||
@@ -11057,7 +11050,7 @@ __init static int tracer_alloc_buffers(v
|
||||
BUILD_BUG_ON(TRACE_ITER_LAST_BIT > TRACE_FLAGS_MAX_SIZE);
|
||||
|
||||
if (!alloc_cpumask_var(&tracing_buffer_mask, GFP_KERNEL))
|
||||
- goto out;
|
||||
+ return -ENOMEM;
|
||||
|
||||
if (!alloc_cpumask_var(&global_trace.tracing_cpumask, GFP_KERNEL))
|
||||
goto out_free_buffer_mask;
|
||||
@@ -11175,7 +11168,6 @@ out_free_cpumask:
|
||||
free_cpumask_var(global_trace.tracing_cpumask);
|
||||
out_free_buffer_mask:
|
||||
free_cpumask_var(tracing_buffer_mask);
|
||||
-out:
|
||||
return ret;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user