6.12.17-rc1 review
Subsystems (2)
Greg Kroah-Hartman
maintainerPATCH 1/154 arm64: mte: Do not allow PROT_MTE on MAP_HUGETLB user mappings
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Catalin Marinas <[email protected]>
PROT_MTE (memory tagging extensions) is not supported on all user mmap() types for various reasons (memory attributes, backing storage, CoW handling). The arm64 arch_validate_flags() function checks whether the VM_MTE_ALLOWED flag has been set for a vma during mmap(), usually by arch_calc_vm_flag_bits().
Linux prior to 6.13 does not support PROT_MTE hugetlb mappings. This was added by commit 25c17c4b55de ("hugetlb: arm64: add mte support"). However, earlier kernels inadvertently set VM_MTE_ALLOWED on (MAP_ANONYMOUS | MAP_HUGETLB) mappings by only checking for MAP_ANONYMOUS.
Explicitly check MAP_HUGETLB in arch_calc_vm_flag_bits() and avoid setting VM_MTE_ALLOWED for such mappings.
--- arch/arm64/include/asm/mman.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
arch/arm64/include/asm/mman.h +6 -3
@@ -41,9 +41,12 @@ static inline unsigned long arch_calc_vm* backed by tags-capable memory. The vm_flags may be overridden by a * filesystem supporting MTE (RAM-based). */ -if (system_supports_mte () && - ((flags &MAP_ANONYMOUS ) ||shmem_file (file))) -return VM_MTE_ALLOWED ; +if (system_supports_mte ()) { +if ((flags &MAP_ANONYMOUS ) && !(flags &MAP_HUGETLB )) +return VM_MTE_ALLOWED ; +if (shmem_file (file)) +return VM_MTE_ALLOWED ; + }return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 10/154 btrfs: unify to use writer locks for subpage locking
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
[ Upstream commit 336e69f3025fb70db9d0dfb7f36ac79887bf5341 ]
Since commit d7172f52e993 ("btrfs: use per-buffer locking for extent_buffer reading"), metadata read no longer relies on the subpage reader locking.
This means we do not need to maintain a different metadata/data split for locking, so we can convert the existing reader lock users by:
- add_ra_bio_pages()
Convert to btrfs_folio_set_writer_lock()
- end_folio_read()
Convert to btrfs_folio_end_writer_lock()
- begin_folio_read()
Convert to btrfs_folio_set_writer_lock()
- folio_range_has_eb()
Remove the subpage->readers checks, since it is always 0.
- Remove btrfs_subpage_start_reader() and btrfs_subpage_end_reader()
Stable-dep-of: 8bf334beb349 ("btrfs: fix double accounting race when extent_writepage_io() failed")
--- fs/btrfs/compression.c | 3 +- fs/btrfs/extent_io.c | 10 ++----- fs/btrfs/subpage.c | 62 ++---------------------------------------- fs/btrfs/subpage.h | 13 --------- 4 files changed, 5 insertions(+), 83 deletions(-)
fs/btrfs/compression.c +1 -2
@@ -545,8 +545,7 @@ static noinline int add_ra_bio_pages(struct inode *inode,* subpage::readers and to unlock the page. */ if (fs_info->sectorsize <PAGE_SIZE ) -btrfs_subpage_start_reader (fs_info, folio, cur, - add_size); +btrfs_folio_set_writer_lock (fs_info, folio, cur, add_size);folio_put (folio); cur += add_size; }
fs/btrfs/extent_io.c +2 -8
@@ -438,7 +438,7 @@ static void end_folio_read(struct folio *folio, bool uptodate, u64 start, u32 leif (!btrfs_is_subpage (fs_info, folio->mapping))folio_unlock (folio);else -btrfs_subpage_end_reader (fs_info, folio, start, len); +btrfs_folio_end_writer_lock (fs_info, folio, start, len); }/*
@@ -495,7 +495,7 @@ static void begin_folio_read(struct btrfs_fs_info *fs_info, struct folio *folio)return ;ASSERT (folio_test_private (folio)); -btrfs_subpage_start_reader (fs_info, folio,folio_pos (folio),PAGE_SIZE ); +btrfs_folio_set_writer_lock (fs_info, folio,folio_pos (folio),PAGE_SIZE ); }/*
@@ -2507,12 +2507,6 @@ static bool folio_range_has_eb(struct btrfs_fs_info *fs_info, struct folio *foli subpage =folio_get_private (folio);if (atomic_read (&subpage->eb_refs))return true; -/* -* Even there is no eb refs here, we may still have -* end_folio_read() call relying on page::private. -*/ -if (atomic_read (&subpage->readers)) -return true; }return false; }
fs/btrfs/subpage.c +2 -60
76 lines not on this page · raw message
fs/btrfs/subpage.h +0 -13
@@ -45,14 +45,6 @@ enum {struct btrfs_subpage {/* Common members for both data and metadata pages */ spinlock_t lock; -/* -* Both data and metadata needs to track how many readers are for the -* page. -* Data relies on @readers to unlock the page when last reader finished. -* While metadata doesn't need page unlock, it needs to prevent -* page::private get cleared before the last end_page_read(). -*/ -atomic_t readers;union {/* * Structures only used by metadata
@@ -95,11 +87,6 @@ void btrfs_free_subpage(struct btrfs_subpage *subpage);void btrfs_folio_inc_eb_refs (const struct btrfs_fs_info *fs_info,struct folio *folio);void btrfs_folio_dec_eb_refs (const struct btrfs_fs_info *fs_info,struct folio *folio); -void btrfs_subpage_start_reader (const struct btrfs_fs_info *fs_info, -struct folio *folio,u64 start,u32 len); -void btrfs_subpage_end_reader (const struct btrfs_fs_info *fs_info, -struct folio *folio,u64 start,u32 len); -void btrfs_folio_end_writer_lock (const struct btrfs_fs_info *fs_info,struct folio *folio,u64 start,u32 len); void btrfs_folio_set_writer_lock(const struct btrfs_fs_info *fs_info,
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 11/154 btrfs: rename btrfs_folio_(set|start|end)_writer_lock()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
[ Upstream commit 0f7120266584490616f031873e7148495d77dd68 ]
Since there is no user of reader locks, rename the writer locks into a more generic name, by removing the "_writer" part from the name.
And also rename btrfs_subpage::writer into btrfs_subpage::locked.
Stable-dep-of: 8bf334beb349 ("btrfs: fix double accounting race when extent_writepage_io() failed")
--- fs/btrfs/compression.c | 2 +- fs/btrfs/extent_io.c | 14 ++++++------- fs/btrfs/subpage.c | 46 +++++++++++++++++++++--------------------- fs/btrfs/subpage.h | 20 ++++++++++-------- 4 files changed, 43 insertions(+), 39 deletions(-)
fs/btrfs/compression.c +1 -1
@@ -545,7 +545,7 @@ static noinline int add_ra_bio_pages(struct inode *inode,* subpage::readers and to unlock the page. */ if (fs_info->sectorsize <PAGE_SIZE ) -btrfs_folio_set_writer_lock (fs_info, folio, cur, add_size); +btrfs_folio_set_lock (fs_info, folio, cur, add_size);folio_put (folio); cur += add_size; }
fs/btrfs/extent_io.c +7 -7
@@ -190,7 +190,7 @@ static void process_one_folio(struct btrfs_fs_info *fs_info,btrfs_folio_clamp_clear_writeback (fs_info, folio, start, len);if (folio != locked_folio && (page_ops &PAGE_UNLOCK )) -btrfs_folio_end_writer_lock (fs_info, folio, start, len); +btrfs_folio_end_lock (fs_info, folio, start, len); } static void __process_folios_contig(struct address_space *mapping,
@@ -276,7 +276,7 @@ static noinline int lock_delalloc_folios(struct inode *inode, range_start =max_t (u64,folio_pos (folio), start); range_len =min_t (u64,folio_pos (folio) +folio_size (folio), end +1 ) - range_start; -btrfs_folio_set_writer_lock (fs_info, folio, range_start, range_len); +btrfs_folio_set_lock (fs_info, folio, range_start, range_len); processed_end = range_start + range_len -1 ; }
@@ -438,7 +438,7 @@ static void end_folio_read(struct folio *folio, bool uptodate, u64 start, u32 leif (!btrfs_is_subpage (fs_info, folio->mapping))folio_unlock (folio);else -btrfs_folio_end_writer_lock (fs_info, folio, start, len); +btrfs_folio_end_lock (fs_info, folio, start, len); }/*
@@ -495,7 +495,7 @@ static void begin_folio_read(struct btrfs_fs_info *fs_info, struct folio *folio)return ;ASSERT (folio_test_private (folio)); -btrfs_folio_set_writer_lock (fs_info, folio,folio_pos (folio),PAGE_SIZE ); +btrfs_folio_set_lock (fs_info, folio,folio_pos (folio),PAGE_SIZE ); }/*
@@ -1187,7 +1187,7 @@ static noinline_for_stack int writepage_delalloc(struct btrfs_inode *inode,for_each_set_bit (bit, &bio_ctrl->submit_bitmap, fs_info->sectors_per_page) {u64 start = page_start + (bit << fs_info->sectorsize_bits); -btrfs_folio_set_writer_lock (fs_info, folio, start, fs_info->sectorsize); +btrfs_folio_set_lock (fs_info, folio, start, fs_info->sectorsize); }/* Lock all (subpage) delalloc ranges inside the folio first. */
@@ -1523,7 +1523,7 @@ static int extent_writepage(struct folio *folio, struct btrfs_bio_ctrl *bio_ctrl* Only unlock ranges that are submitted. As there can be some async * submitted ranges inside the folio. */ -btrfs_folio_end_writer_lock_bitmap (fs_info, folio, bio_ctrl->submit_bitmap); +btrfs_folio_end_lock_bitmap (fs_info, folio, bio_ctrl->submit_bitmap);ASSERT (ret <=0 );return ret; }
@@ -2280,7 +2280,7 @@ void extent_write_locked_range(struct inode *inode, const struct folio *locked_f cur, cur_len, !ret);mapping_set_error (mapping, ret); } -btrfs_folio_end_writer_lock (fs_info, folio, cur, cur_len); +btrfs_folio_end_lock (fs_info, folio, cur, cur_len);if (ret <0 ) found_error = true; next_page:
fs/btrfs/subpage.c +23 -23
118 lines not on this page · raw message
fs/btrfs/subpage.h +12 -8
@@ -54,8 +54,12 @@ struct btrfs_subpage {*/ atomic_t eb_refs; -/* Structures only used by data */ -atomic_t writers; +/* +* Structures only used by data, +* +* How many sectors inside the page is locked. +*/ +atomic_t nr_locked; };unsigned long bitmaps[]; };
@@ -87,12 +91,12 @@ void btrfs_free_subpage(struct btrfs_subpage *subpage);void btrfs_folio_inc_eb_refs (const struct btrfs_fs_info *fs_info,struct folio *folio);void btrfs_folio_dec_eb_refs (const struct btrfs_fs_info *fs_info,struct folio *folio); -void btrfs_folio_end_writer_lock (const struct btrfs_fs_info *fs_info, -struct folio *folio,u64 start,u32 len); -void btrfs_folio_set_writer_lock (const struct btrfs_fs_info *fs_info, -struct folio *folio,u64 start,u32 len); -void btrfs_folio_end_writer_lock_bitmap (const struct btrfs_fs_info *fs_info, -struct folio *folio,unsigned long bitmap); +void btrfs_folio_end_lock (const struct btrfs_fs_info *fs_info, +struct folio *folio,u64 start,u32 len); +void btrfs_folio_set_lock (const struct btrfs_fs_info *fs_info, +struct folio *folio,u64 start,u32 len); +void btrfs_folio_end_lock_bitmap (const struct btrfs_fs_info *fs_info, +struct folio *folio,unsigned long bitmap);/* * Template for subpage related operations. *
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 12/154 btrfs: use btrfs_inode in extent_writepage()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Sterba <[email protected]>
[ Upstream commit 011a9a1f244656cc3cbde47edba2b250f794d440 ]
As extent_writepage() is internal helper we should use our inode type, so change it from struct inode.
Stable-dep-of: 8bf334beb349 ("btrfs: fix double accounting race when extent_writepage_io() failed")
--- fs/btrfs/extent_io.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
fs/btrfs/extent_io.c +7 -7
@@ -1467,15 +1467,15 @@ static noinline_for_stack int extent_writepage_io(struct btrfs_inode *inode,*/ static int extent_writepage (struct folio *folio,struct btrfs_bio_ctrl *bio_ctrl) { -struct inode *inode = folio->mapping->host; -struct btrfs_fs_info *fs_info =inode_to_fs_info (inode); +struct btrfs_inode *inode =BTRFS_I (folio->mapping->host); +struct btrfs_fs_info *fs_info = inode->root->fs_info;const u64 page_start =folio_pos (folio);int ret;size_t pg_offset; -loff_t i_size =i_size_read (inode); +loff_t i_size =i_size_read (&inode->vfs_inode);unsigned long end_index = i_size >>PAGE_SHIFT ; -trace_extent_writepage (folio, inode, bio_ctrl->wbc); +trace_extent_writepage (folio, &inode->vfs_inode, bio_ctrl->wbc);WARN_ON (!folio_test_locked (folio));
@@ -1499,13 +1499,13 @@ static int extent_writepage(struct folio *folio, struct btrfs_bio_ctrl *bio_ctrlif (ret <0 ) goto done; - ret =writepage_delalloc (BTRFS_I (inode), folio, bio_ctrl); + ret =writepage_delalloc (inode, folio, bio_ctrl);if (ret ==1 )return 0 ;if (ret) goto done; - ret =extent_writepage_io (BTRFS_I (inode), folio,folio_pos (folio), + ret =extent_writepage_io (inode, folio,folio_pos (folio),PAGE_SIZE , bio_ctrl, i_size);if (ret ==1 )return 0 ;
@@ -1514,7 +1514,7 @@ static int extent_writepage(struct folio *folio, struct btrfs_bio_ctrl *bio_ctrl done:if (ret) { -btrfs_mark_ordered_io_finished (BTRFS_I (inode), folio, +btrfs_mark_ordered_io_finished (inode, folio, page_start,PAGE_SIZE , !ret);mapping_set_error (folio->mapping, ret); }
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 13/154 btrfs: fix double accounting race when btrfs_run_delalloc_range() failed
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
[ Upstream commit 72dad8e377afa50435940adfb697e070d3556670 ]
[BUG]
When running btrfs with block size (4K) smaller than page size (64K, aarch64), there is a very high chance to crash the kernel at generic/750, with the following messages:
(before the call traces, there are 3 extra debug messages added)
BTRFS warning (device dm-3): read-write for sector size 4096 with page size 65536 is experimental
BTRFS info (device dm-3): checking UUID tree
hrtimer: interrupt took 5451385 ns
BTRFS error (device dm-3): cow_file_range failed, root=4957 inode=257 start=1605632 len=69632: -28
BTRFS error (device dm-3): run_delalloc_nocow failed, root=4957 inode=257 start=1605632 len=69632: -28
BTRFS error (device dm-3): failed to run delalloc range, root=4957 ino=257 folio=1572864 submit_bitmap=8-15 start=1605632 len=69632: -28
------------[ cut here ]------------
WARNING: CPU: 2 PID: 3020984 at ordered-data.c:360 can_finish_ordered_extent+0x370/0x3b8 [btrfs]
CPU: 2 UID: 0 PID: 3020984 Comm: kworker/u24:1 Tainted: G OE 6.13.0-rc1-custom+ #89
Tainted: [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
Hardware name: QEMU KVM Virtual Machine, BIOS unknown 2/2/2022
Workqueue: events_unbound btrfs_async_reclaim_data_space [btrfs]
pc : can_finish_ordered_extent+0x370/0x3b8 [btrfs]
lr : can_finish_ordered_extent+0x1ec/0x3b8 [btrfs]
Call trace:
can_finish_ordered_extent+0x370/0x3b8 [btrfs] (P)
can_finish_ordered_extent+0x1ec/0x3b8 [btrfs] (L)
btrfs_mark_ordered_io_finished+0x130/0x2b8 [btrfs]
extent_writepage+0x10c/0x3b8 [btrfs]
extent_write_cache_pages+0x21c/0x4e8 [btrfs]
btrfs_writepages+0x94/0x160 [btrfs]
do_writepages+0x74/0x190
filemap_fdatawrite_wbc+0x74/0xa0
start_delalloc_inodes+0x17c/0x3b0 [btrfs]
btrfs_start_delalloc_roots+0x17c/0x288 [btrfs]
shrink_delalloc+0x11c/0x280 [btrfs]
flush_space+0x288/0x328 [btrfs]
btrfs_async_reclaim_data_space+0x180/0x228 [btrfs]
process_one_work+0x228/0x680
worker_thread+0x1bc/0x360
kthread+0x100/0x118
ret_from_fork+0x10/0x20
---[ end trace 0000000000000000 ]---
BTRFS critical (device dm-3): bad ordered extent accounting, root=4957 ino=257 OE offset=1605632 OE len=16384 to_dec=16384 left=0
BTRFS critical (device dm-3): bad ordered extent accounting, root=4957 ino=257 OE offset=1622016 OE len=12288 to_dec=12288 left=0
Unable to handle kernel NULL pointer dereference at virtual address 0000000000000008
BTRFS critical (device dm-3): bad ordered extent accounting, root=4957 ino=257 OE offset=1634304 OE len=8192 to_dec=4096 left=0
CPU: 1 UID: 0 PID: 3286940 Comm: kworker/u24:3 Tainted: G W OE 6.13.0-rc1-custom+ #89
Hardware name: QEMU KVM Virtual Machine, BIOS unknown 2/2/2022
Workqueue: btrfs_work_helper [btrfs] (btrfs-endio-write)
pstate: 404000c5 (nZcv daIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
pc : process_one_work+0x110/0x680
lr : worker_thread+0x1bc/0x360
Call trace:
process_one_work+0x110/0x680 (P)
worker_thread+0x1bc/0x360 (L)
worker_thread+0x1bc/0x360
kthread+0x100/0x118
ret_from_fork+0x10/0x20
Code: f84086a1 f9000fe1 53041c21 b9003361 (f9400661)
---[ end trace 0000000000000000 ]---
Kernel panic - not syncing: Oops: Fatal exception
SMP: stopping secondary CPUs
SMP: failed to stop secondary CPUs 2-3
Dumping ftrace buffer:
(ftrace buffer empty)
Kernel Offset: 0x275bb9540000 from 0xffff800080000000
PHYS_OFFSET: 0xffff8fbba0000000
CPU features: 0x100,00000070,00801250,8201720b[CAUSE]
The above warning is triggered immediately after the delalloc range failure, this happens in the following sequence:
- Range [1568K, 1636K) is dirty
1536K 1568K 1600K 1636K 1664K | |/////////|////////| |
Where 1536K, 1600K and 1664K are page boundaries (64K page size)
- Enter extent_writepage() for page 1536K
- Enter run_delalloc_nocow() with locked page 1536K and range [1568K, 1636K)
This is due to the inode having preallocated extents.
- Enter cow_file_range() with locked page 1536K and range [1568K, 1636K)
- btrfs_reserve_extent() only reserved two extents
The main loop of cow_file_range() only reserved two data extents,
Now we have:
1536K 1568K 1600K 1636K 1664K
| |<-->|<--->|/|///////| |
1584K 1596KRange [1568K, 1596K) has an ordered extent reserved.
- btrfs_reserve_extent() failed inside cow_file_range() for file offset 1596K
This is already a bug in our space reservation code, but for now let's focus on the error handling path.
Now cow_file_range() returned -ENOSPC.
- btrfs_run_delalloc_range() do error cleanup <<< ROOT CAUSE Call btrfs_cleanup_ordered_extents() with locked folio 1536K and range [1568K, 1636K)
Function btrfs_cleanup_ordered_extents() normally needs to skip the ranges inside the folio, as it will normally be cleaned up by extent_writepage().
Such split error handling is already problematic in the first place.
What's worse is the folio range skipping itself, which is not taking subpage cases into consideration at all, it will only skip the range if the page start >= the range start.
In our case, the page start < the range start, since for subpage cases we can have delalloc ranges inside the folio but not covering the folio.
So it doesn't skip the page range at all.
This means all the ordered extents, both [1568K, 1584K) and [1584K, 1596K) will be marked as IOERR.
And these two ordered extents have no more pending ios, they are marked finished, and *QUEUED* to be deleted from the io tree.
- extent_writepage() do error cleanup
Call btrfs_mark_ordered_io_finished() for the range [1536K, 1600K).
Although ranges [1568K, 1584K) and [1584K, 1596K) are finished, the deletion from io tree is async, it may or may not happen at this time.
If the ranges have not yet been removed, we will do double cleaning on those ranges, triggering the above ordered extent warnings.
In theory there are other bugs, like the cleanup in extent_writepage() can cause double accounting on ranges that are submitted asynchronously (compression for example).
But that's much harder to trigger because normally we do not mix regular and compression delalloc ranges.
[FIX]
The folio range split is already buggy and not subpage compatible, it was introduced a long time ago where subpage support was not even considered.
So instead of splitting the ordered extents cleanup into the folio range and out of folio range, do all the cleanup inside writepage_delalloc().
- Pass @NULL as locked_folio for btrfs_cleanup_ordered_extents() in btrfs_run_delalloc_range()
- Skip the btrfs_cleanup_ordered_extents() if writepage_delalloc() failed
So all ordered extents are only cleaned up by
btrfs_run_delalloc_range().
- Handle the ranges that already have ordered extents allocated If part of the folio already has ordered extent allocated, and btrfs_run_delalloc_range() failed, we also need to cleanup that range.
Now we have a concentrated error handling for ordered extents during btrfs_run_delalloc_range().
Stable-dep-of: 8bf334beb349 ("btrfs: fix double accounting race when extent_writepage_io() failed")
--- fs/btrfs/extent_io.c | 59 +++++++++++++++++++++++++++++++++++--------- fs/btrfs/inode.c | 3 +-- 2 files changed, 49 insertions(+), 13 deletions(-)
fs/btrfs/extent_io.c +48 -11
@@ -1145,14 +1145,19 @@ static bool find_next_delalloc_bitmap(struct folio *folio, }/* -* helper for extent_writepage(), doing all of the delayed allocation setup. +* Do all of the delayed allocation setup. * -* This returns 1 if btrfs_run_delalloc_range function did all the work required -* to write the page (copy into inline extent). In this case the IO has -* been started and the page is already unlocked. +* Return >0 if all the dirty blocks are submitted async (compression) or inlined. +* The @folio should no longer be touched (treat it as already unlocked). * -* This returns 0 if all went well (page still locked) -* This returns < 0 if there were errors (page still locked) +* Return 0 if there is still dirty block that needs to be submitted through +* extent_writepage_io(). +* bio_ctrl->submit_bitmap will indicate which blocks of the folio should be +* submitted, and @folio is still kept locked. +* +* Return <0 if there is any error hit. +* Any allocated ordered extent range covering this folio will be marked +* finished (IOERR), and @folio is still kept locked. */ static noinline_for_stack int writepage_delalloc(struct btrfs_inode *inode, struct folio *folio,
@@ -1170,6 +1175,16 @@ static noinline_for_stack int writepage_delalloc(struct btrfs_inode *inode,* last delalloc end. */ u64 last_delalloc_end =0 ; +/* +* The range end (exclusive) of the last successfully finished delalloc +* range. +* Any range covered by ordered extent must either be manually marked +* finished (error handling), or has IO submitted (and finish the +* ordered extent normally). +* +* This records the end of ordered extent cleanup if we hit an error. +*/ +u64 last_finished_delalloc_end = page_start;u64 delalloc_start = page_start;u64 delalloc_end = page_end;u64 delalloc_to_write =0 ;
@@ -1238,11 +1253,19 @@ static noinline_for_stack int writepage_delalloc(struct btrfs_inode *inode, found_len = last_delalloc_end +1 - found_start;if (ret >=0 ) { +/* +* Some delalloc range may be created by previous folios. +* Thus we still need to clean up this range during error +* handling. +*/ + last_finished_delalloc_end = found_start;/* No errors hit so far, run the current delalloc range. */ ret =btrfs_run_delalloc_range (inode, folio, found_start, found_start + found_len -1 , wbc); +if (ret >=0 ) + last_finished_delalloc_end = found_start + found_len; }else {/* * We've hit an error during previous delalloc range,
@@ -1277,8 +1300,22 @@ static noinline_for_stack int writepage_delalloc(struct btrfs_inode *inode, delalloc_start = found_start + found_len; } -if (ret <0 ) +/* +* It's possible we had some ordered extents created before we hit +* an error, cleanup non-async successfully created delalloc ranges. +*/ +if (unlikely (ret <0 )) { +unsigned int bitmap_size =min ( + (last_finished_delalloc_end - page_start) >> + fs_info->sectorsize_bits, + fs_info->sectors_per_page); + +for_each_set_bit (bit, &bio_ctrl->submit_bitmap, bitmap_size) +btrfs_mark_ordered_io_finished (inode, folio, + page_start + (bit << fs_info->sectorsize_bits), + fs_info->sectorsize, false);return ret; + } out:if (last_delalloc_end) delalloc_end = last_delalloc_end;
@@ -1512,13 +1549,13 @@ static int extent_writepage(struct folio *folio, struct btrfs_bio_ctrl *bio_ctrl bio_ctrl->wbc->nr_to_write--; -done: -if (ret) { +if (ret)btrfs_mark_ordered_io_finished (inode, folio, page_start,PAGE_SIZE , !ret); -mapping_set_error (folio->mapping, ret); - } +done: +if (ret <0 ) +mapping_set_error (folio->mapping, ret);/* * Only unlock ranges that are submitted. As there can be some async * submitted ranges inside the folio.
fs/btrfs/inode.c +1 -2
@@ -2419,8 +2419,7 @@ int btrfs_run_delalloc_range(struct btrfs_inode *inode, struct folio *locked_fol out:if (ret <0 ) -btrfs_cleanup_ordered_extents (inode, locked_folio, start, - end - start +1 ); +btrfs_cleanup_ordered_extents (inode,NULL , start, end - start +1 );return ret; }
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 14/154 btrfs: fix double accounting race when extent_writepage_io() failed
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
[ Upstream commit 8bf334beb3496da3c3fbf3daf3856f7eec70dacc ]
[BUG]
If submit_one_sector() failed inside extent_writepage_io() for sector size < page size cases (e.g. 4K sector size and 64K page size), then we can hit double ordered extent accounting error.
This should be very rare, as submit_one_sector() only fails when we failed to grab the extent map, and such extent map should exist inside the memory and has been pinned.
[CAUSE]
For example we have the following folio layout:
0 4K 32K 48K 60K 64K
|//| |//////| |///|Where |///| is the dirty range we need to writeback. The 3 different dirty ranges are submitted for regular COW.
Now we hit the following sequence:
- submit_one_sector() returned 0 for [0, 4K)
- submit_one_sector() returned 0 for [32K, 48K)
- submit_one_sector() returned error for [60K, 64K)
- btrfs_mark_ordered_io_finished() called for the whole folio This will mark the following ranges as finished:
* [0, 4K)
* [32K, 48K)
Both ranges have their IO already submitted, this cleanup will lead to double accounting.
* [60K, 64K)
That's the correct cleanup.
The only good news is, this error is only theoretical, as the target extent map is always pinned, thus we should directly grab it from memory, other than reading it from the disk.
[FIX]
Instead of calling btrfs_mark_ordered_io_finished() for the whole folio range, which can touch ranges we should not touch, instead move the error handling inside extent_writepage_io().
So that we can cleanup exact sectors that ought to be submitted but failed.
This provides much more accurate cleanup, avoiding the double accounting.
--- fs/btrfs/extent_io.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-)
fs/btrfs/extent_io.c +24 -13
@@ -1431,6 +1431,7 @@ static noinline_for_stack int extent_writepage_io(struct btrfs_inode *inode,struct btrfs_fs_info *fs_info = inode->root->fs_info;unsigned long range_bitmap =0 ;bool submitted_io = false; +bool error = false;const u64 folio_start =folio_pos (folio);u64 cur;int bit;
@@ -1473,11 +1474,26 @@ static noinline_for_stack int extent_writepage_io(struct btrfs_inode *inode,break ; } ret =submit_one_sector (inode, folio, cur, bio_ctrl, i_size); -if (ret <0 ) - goto out; +if (unlikely (ret <0 )) { +/* +* bio_ctrl may contain a bio crossing several folios. +* Submit it immediately so that the bio has a chance +* to finish normally, other than marked as error. +*/ +submit_one_bio (bio_ctrl); +/* +* Failed to grab the extent map which should be very rare. +* Since there is no bio submitted to finish the ordered +* extent, we have to manually finish this sector. +*/ +btrfs_mark_ordered_io_finished (inode, folio, cur, + fs_info->sectorsize, false); + error = true; +continue ; + } submitted_io = true; } -out: +/* * If we didn't submitted any sector (>= i_size), folio dirty get * cleared but PAGECACHE_TAG_DIRTY is not cleared (only cleared
@@ -1485,8 +1501,11 @@ static noinline_for_stack int extent_writepage_io(struct btrfs_inode *inode,* * Here we set writeback and clear for the range. If the full folio * is no longer dirty then we clear the PAGECACHE_TAG_DIRTY tag. +* +* If we hit any error, the corresponding sector will still be dirty +* thus no need to clear PAGECACHE_TAG_DIRTY. */ -if (!submitted_io) { +if (!submitted_io && !error) {btrfs_folio_set_writeback (fs_info, folio, start, len);btrfs_folio_clear_writeback (fs_info, folio, start, len); }
@@ -1506,7 +1525,6 @@ static int extent_writepage(struct folio *folio, struct btrfs_bio_ctrl *bio_ctrl {struct btrfs_inode *inode =BTRFS_I (folio->mapping->host);struct btrfs_fs_info *fs_info = inode->root->fs_info; -const u64 page_start =folio_pos (folio);int ret;size_t pg_offset;loff_t i_size =i_size_read (&inode->vfs_inode);
@@ -1549,10 +1567,6 @@ static int extent_writepage(struct folio *folio, struct btrfs_bio_ctrl *bio_ctrl bio_ctrl->wbc->nr_to_write--; -if (ret) -btrfs_mark_ordered_io_finished (inode, folio, - page_start,PAGE_SIZE , !ret); - done:if (ret <0 )mapping_set_error (folio->mapping, ret);
@@ -2312,11 +2326,8 @@ void extent_write_locked_range(struct inode *inode, const struct folio *locked_fif (ret ==1 ) goto next_page; -if (ret) { -btrfs_mark_ordered_io_finished (BTRFS_I (inode), folio, - cur, cur_len, !ret); +if (ret)mapping_set_error (mapping, ret); - }btrfs_folio_end_lock (fs_info, folio, cur, cur_len);if (ret <0 ) found_error = true;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 15/154 KVM: x86: Get vcpu->arch.apic_base directly and drop kvm_get_apic_base()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
[ Upstream commit d91060e342a66b52d9bd64f0b123b9c306293b76 ]
Access KVM's emulated APIC base MSR value directly instead of bouncing through a helper, as there is no reason to add a layer of indirection, and there are other MSRs with a "set" but no "get", e.g. EFER.
No functional change intended.
Stable-dep-of: 04bc93cf49d1 ("KVM: nVMX: Defer SVI update to vmcs01 on EOI when L2 is active w/o VID")
--- arch/x86/kvm/lapic.h | 1 - arch/x86/kvm/x86.c | 13 ++++--------- 2 files changed, 4 insertions(+), 10 deletions(-)
arch/x86/kvm/lapic.h +0 -1
@@ -117,7 +117,6 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src, struct kvm_lapic_irq *irq, int *r, struct dest_map *dest_map);void kvm_apic_send_ipi (struct kvm_lapic *apic,u32 icr_low,u32 icr_high); -u64 kvm_get_apic_base (struct kvm_vcpu *vcpu);int kvm_set_apic_base (struct kvm_vcpu *vcpu,struct msr_data *msr_info);int kvm_apic_get_state (struct kvm_vcpu *vcpu,struct kvm_lapic_state *s);int kvm_apic_set_state (struct kvm_vcpu *vcpu,struct kvm_lapic_state *s);
arch/x86/kvm/x86.c +4 -9
@@ -667,14 +667,9 @@ static void drop_user_return_notifiers(void)kvm_on_user_return (&msrs->urn); } -u64 kvm_get_apic_base (struct kvm_vcpu *vcpu) -{ -return vcpu->arch.apic_base; -} -enum lapic_mode kvm_get_apic_mode (struct kvm_vcpu *vcpu) { -return kvm_apic_mode (kvm_get_apic_base (vcpu)); +return kvm_apic_mode (vcpu->arch.apic_base); }EXPORT_SYMBOL_GPL (kvm_get_apic_mode);
@@ -4314,7 +4309,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) msr_info->data =1 <<24 ;break ;case MSR_IA32_APICBASE : - msr_info->data =kvm_get_apic_base (vcpu); + msr_info->data = vcpu->arch.apic_base;break ; case APIC_BASE_MSR ... APIC_BASE_MSR + 0xff:return kvm_x2apic_msr_read (vcpu, msr_info->index, &msr_info->data);
@@ -10159,7 +10154,7 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu) kvm_run->if_flag =kvm_x86_call (get_if_flag)(vcpu); kvm_run->cr8 =kvm_get_cr8 (vcpu); - kvm_run->apic_base =kvm_get_apic_base (vcpu); + kvm_run->apic_base = vcpu->arch.apic_base; kvm_run->ready_for_interrupt_injection = pic_in_kernel(vcpu->kvm) ||
@@ -11718,7 +11713,7 @@ static void __get_sregs_common(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) sregs->cr4 =kvm_read_cr4 (vcpu); sregs->cr8 =kvm_get_cr8 (vcpu); sregs->efer = vcpu->arch.efer; - sregs->apic_base =kvm_get_apic_base (vcpu); + sregs->apic_base = vcpu->arch.apic_base; }static void __get_sregs (struct kvm_vcpu *vcpu,struct kvm_sregs *sregs)
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 16/154 KVM: x86: Inline kvm_get_apic_mode() in lapic.h
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
[ Upstream commit adfec1f4591cf8c69664104eaf41e06b2e7b767e ]
Inline kvm_get_apic_mode() in lapic.h to avoid a CALL+RET as well as an export. The underlying kvm_apic_mode() helper is public information, i.e. there is no state/information that needs to be hidden from vendor modules.
No functional change intended.
Stable-dep-of: 04bc93cf49d1 ("KVM: nVMX: Defer SVI update to vmcs01 on EOI when L2 is active w/o VID")
--- arch/x86/kvm/lapic.h | 6 +++++- arch/x86/kvm/x86.c | 6 ------ 2 files changed, 5 insertions(+), 7 deletions(-)
arch/x86/kvm/lapic.h +5 -1
@@ -120,7 +120,6 @@ void kvm_apic_send_ipi(struct kvm_lapic *apic, u32 icr_low, u32 icr_high);int kvm_set_apic_base (struct kvm_vcpu *vcpu,struct msr_data *msr_info);int kvm_apic_get_state (struct kvm_vcpu *vcpu,struct kvm_lapic_state *s);int kvm_apic_set_state (struct kvm_vcpu *vcpu,struct kvm_lapic_state *s); -enum lapic_mode kvm_get_apic_mode (struct kvm_vcpu *vcpu);int kvm_lapic_find_highest_irr (struct kvm_vcpu *vcpu);u64 kvm_get_lapic_tscdeadline_msr (struct kvm_vcpu *vcpu);
@@ -270,6 +269,11 @@ static inline enum lapic_mode kvm_apic_mode(u64 apic_base)return apic_base & (MSR_IA32_APICBASE_ENABLE |X2APIC_ENABLE ); } +static inline enum lapic_mode kvm_get_apic_mode (struct kvm_vcpu *vcpu) +{ +return kvm_apic_mode (vcpu->arch.apic_base); +} +static inline u8 kvm_xapic_id (struct kvm_lapic *apic) {return kvm_lapic_get_reg (apic,APIC_ID ) >>24 ;
arch/x86/kvm/x86.c +0 -6
@@ -667,12 +667,6 @@ static void drop_user_return_notifiers(void)kvm_on_user_return (&msrs->urn); } -enum lapic_mode kvm_get_apic_mode (struct kvm_vcpu *vcpu) -{ -return kvm_apic_mode (vcpu->arch.apic_base); -} -EXPORT_SYMBOL_GPL (kvm_get_apic_mode); -int kvm_set_apic_base (struct kvm_vcpu *vcpu,struct msr_data *msr_info) {enum lapic_mode old_mode =kvm_get_apic_mode (vcpu);
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 17/154 KVM: nVMX: Defer SVI update to vmcs01 on EOI when L2 is active w/o VID
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chao Gao <[email protected]>
[ Upstream commit 04bc93cf49d16d01753b95ddb5d4f230b809a991 ]
If KVM emulates an EOI for L1's virtual APIC while L2 is active, defer updating GUEST_INTERUPT_STATUS.SVI, i.e. the VMCS's cache of the highest in-service IRQ, until L1 is active, as vmcs01, not vmcs02, needs to track vISR. The missed SVI update for vmcs01 can result in L1 interrupts being incorrectly blocked, e.g. if there is a pending interrupt with lower priority than the interrupt that was EOI'd.
This bug only affects use cases where L1's vAPIC is effectively passed through to L2, e.g. in a pKVM scenario where L2 is L1's depriveleged host, as KVM will only emulate an EOI for L1's vAPIC if Virtual Interrupt Delivery (VID) is disabled in vmc12, and L1 isn't intercepting L2 accesses to its (virtual) APIC page (or if x2APIC is enabled, the EOI MSR).
WARN() if KVM updates L1's ISR while L2 is active with VID enabled, as an EOI from L2 is supposed to affect L2's vAPIC, but still defer the update, to try to keep L1 alive. Specifically, KVM forwards all APICv-related VM-Exits to L1 via nested_vmx_l1_wants_exit():
case EXIT_REASON_APIC_ACCESS: case EXIT_REASON_APIC_WRITE: case EXIT_REASON_EOI_INDUCED: /* * The controls for "virtualize APIC accesses," "APIC- * register virtualization," and "virtual-interrupt * delivery" only come from vmcs12. */ return true;
--- arch/x86/kvm/lapic.c | 11 +++++++++++ arch/x86/kvm/lapic.h | 1 + arch/x86/kvm/vmx/nested.c | 5 +++++ arch/x86/kvm/vmx/vmx.c | 21 +++++++++++++++++++++ arch/x86/kvm/vmx/vmx.h | 1 + 5 files changed, 39 insertions(+)
arch/x86/kvm/lapic.c +11 -0
@@ -816,6 +816,17 @@ static inline void apic_clear_isr(int vec, struct kvm_lapic *apic) } } +void kvm_apic_update_hwapic_isr (struct kvm_vcpu *vcpu) +{ +struct kvm_lapic *apic = vcpu->arch.apic; + +if (WARN_ON_ONCE (!lapic_in_kernel (vcpu)) || !apic->apicv_active) +return ; + +kvm_x86_call (hwapic_isr_update)(vcpu,apic_find_highest_isr (apic)); +} +EXPORT_SYMBOL_GPL (kvm_apic_update_hwapic_isr); +int kvm_lapic_find_highest_irr (struct kvm_vcpu *vcpu) {/* This may race with setting of irr in __apic_accept_irq() and
arch/x86/kvm/lapic.h +1 -0
@@ -120,6 +120,7 @@ void kvm_apic_send_ipi(struct kvm_lapic *apic, u32 icr_low, u32 icr_high);int kvm_set_apic_base (struct kvm_vcpu *vcpu,struct msr_data *msr_info);int kvm_apic_get_state (struct kvm_vcpu *vcpu,struct kvm_lapic_state *s);int kvm_apic_set_state (struct kvm_vcpu *vcpu,struct kvm_lapic_state *s); +void kvm_apic_update_hwapic_isr (struct kvm_vcpu *vcpu);int kvm_lapic_find_highest_irr (struct kvm_vcpu *vcpu);u64 kvm_get_lapic_tscdeadline_msr (struct kvm_vcpu *vcpu);
arch/x86/kvm/vmx/nested.c +5 -0
@@ -5043,6 +5043,11 @@ void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 vm_exit_reason,kvm_make_request (KVM_REQ_APICV_UPDATE , vcpu); } +if (vmx->nested.update_vmcs01_hwapic_isr) { + vmx->nested.update_vmcs01_hwapic_isr = false; +kvm_apic_update_hwapic_isr (vcpu); + } +if ((vm_exit_reason !=-1 ) && (enable_shadow_vmcs ||nested_vmx_is_evmptr12_valid (vmx))) vmx->nested.need_vmcs12_to_shadow_sync = true;
arch/x86/kvm/vmx/vmx.c +21 -0
@@ -6858,6 +6858,27 @@ void vmx_hwapic_isr_update(struct kvm_vcpu *vcpu, int max_isr)u16 status;u8 old; +/* +* If L2 is active, defer the SVI update until vmcs01 is loaded, as SVI +* is only relevant for if and only if Virtual Interrupt Delivery is +* enabled in vmcs12, and if VID is enabled then L2 EOIs affect L2's +* vAPIC, not L1's vAPIC. KVM must update vmcs01 on the next nested +* VM-Exit, otherwise L1 with run with a stale SVI. +*/ +if (is_guest_mode (vcpu)) { +/* +* KVM is supposed to forward intercepted L2 EOIs to L1 if VID +* is enabled in vmcs12; as above, the EOIs affect L2's vAPIC. +* Note, userspace can stuff state while L2 is active; assert +* that VID is disabled if and only if the vCPU is in KVM_RUN +* to avoid false positives if userspace is setting APIC state. +*/ +WARN_ON_ONCE (vcpu->wants_to_run && +nested_cpu_has_vid (get_vmcs12 (vcpu))); +to_vmx (vcpu)->nested.update_vmcs01_hwapic_isr = true; +return ; + } +if (max_isr ==-1 ) max_isr =0 ;
arch/x86/kvm/vmx/vmx.h +1 -0
@@ -176,6 +176,7 @@ struct nested_vmx {bool reload_vmcs01_apic_access_page;bool update_vmcs01_cpu_dirty_logging;bool update_vmcs01_apicv_status; +bool update_vmcs01_hwapic_isr;/* * Enlightened VMCS has been enabled. It does not mean that L1 has to
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 18/154 drm/amd/display: Refactoring if and endif statements to enable DC_LOGGER
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lohita Mudimela <[email protected]>
[ Upstream commit b04200432c4730c9bb730a66be46551c83d60263 ]
[Why]
For Header related changes for core
[How]
Refactoring if and endif statements to enable DC_LOGGER
Stable-dep-of: f88192d2335b ("drm/amd/display: Correct register address in dcn35")
--- .../gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c | 5 +++-- .../gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c | 6 +++--- .../gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 1 + .../drm/amd/display/dc/link/protocols/link_dp_capability.c | 3 ++- 4 files changed, 9 insertions(+), 6 deletions(-)
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c +3 -2
@@ -50,12 +50,13 @@#include "link.h" #include "logger_types.h" + + +#include "yellow_carp_offset.h" #undef DC_LOGGER#define DC_LOGGER \ clk_mgr->base.base.ctx->logger -#include "yellow_carp_offset.h" -#define regCLK1_CLK_PLL_REQ 0x0237#define regCLK1_CLK_PLL_REQ_BASE_IDX 0
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c +3 -3
@@ -53,9 +53,6 @@#include "logger_types.h" -#undef DC_LOGGER -#define DC_LOGGER \ - clk_mgr->base.base.ctx->logger#define MAX_INSTANCE 7
@@ -77,6 +74,9 @@ static const struct IP_BASE CLK_BASE = { { { { 0x00016C00, 0x02401800, 0, 0, 0, { { 0x0001B200, 0x0242DC00, 0, 0, 0, 0, 0, 0 } }, { { 0x0001B400, 0x0242E000, 0, 0, 0, 0, 0, 0 } } } }; +#undef DC_LOGGER +#define DC_LOGGER \ + clk_mgr->base.base.ctx->logger#define regCLK1_CLK_PLL_REQ 0x0237#define regCLK1_CLK_PLL_REQ_BASE_IDX 0
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +1 -0
@@ -55,6 +55,7 @@#define DC_LOGGER \ clk_mgr->base.base.ctx->logger +#define regCLK1_CLK_PLL_REQ 0x0237#define regCLK1_CLK_PLL_REQ_BASE_IDX 0
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +2 -1
@@ -51,9 +51,10 @@#include "dc_dmub_srv.h" #include "gpio_service_interface.h" +#define DC_TRACE_LEVEL_MESSAGE (...)/* do nothing */ +#define DC_LOGGER \ link->ctx->logger -#define DC_TRACE_LEVEL_MESSAGE (...)/* do nothing */ #ifndef MAX #define MAX (X ,Y ) ((X) > (Y) ? (X) : (Y))
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 2/154 drm/xe/oa: Separate batch submission from waiting for completion
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ashutosh Dixit <[email protected]>
[ Upstream commit dddcb19ad4d4bbe943a72a1fb3266c6e8aa8d541 ]
When we introduce xe_syncs, we don't wait for internal OA programming batches to complete. That is, xe_syncs are signaled asynchronously. In anticipation for this, separate out batch submission from waiting for completion of those batches.
v2: Change return type of xe_oa_submit_bb to "struct dma_fence *" (Matt B)
v3: Retain init "int err = 0;" in xe_oa_submit_bb (Jose)
Stable-dep-of: f0ed39830e60 ("xe/oa: Fix query mode of operation for OAR/OAC")
--- drivers/gpu/drm/xe/xe_oa.c | 57 +++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 13 deletions(-)
drivers/gpu/drm/xe/xe_oa.c +44 -13
@@ -567,11 +567,10 @@ static __poll_t xe_oa_poll(struct file *file, poll_table *wait)return ret; } -static int xe_oa_submit_bb (struct xe_oa_stream *stream,struct xe_bb *bb) +static struct dma_fence *xe_oa_submit_bb (struct xe_oa_stream *stream,struct xe_bb *bb) {struct xe_sched_job *job;struct dma_fence *fence; -long timeout;int err =0 ;/* Kernel configuration is issued on stream->k_exec_q, not stream->exec_q */
@@ -585,14 +584,9 @@ static int xe_oa_submit_bb(struct xe_oa_stream *stream, struct xe_bb *bb) fence =dma_fence_get (&job->drm.s_fence->finished);xe_sched_job_push (job); - timeout =dma_fence_wait_timeout (fence, false,HZ ); -dma_fence_put (fence); -if (timeout <0 ) - err = timeout; -else if (!timeout) - err = -ETIME ; +return fence; exit: -return err; +return ERR_PTR (err); }static void write_cs_mi_lri (struct xe_bb *bb,const struct xe_oa_reg *reg_data,u32 n_regs)
@@ -656,6 +650,7 @@ static void xe_oa_store_flex(struct xe_oa_stream *stream, struct xe_lrc *lrc,static int xe_oa_modify_ctx_image (struct xe_oa_stream *stream,struct xe_lrc *lrc,const struct flex *flex,u32 count) { +struct dma_fence *fence;struct xe_bb *bb;int err;
@@ -667,7 +662,16 @@ static int xe_oa_modify_ctx_image(struct xe_oa_stream *stream, struct xe_lrc *lrxe_oa_store_flex (stream, lrc, bb, flex, count); - err =xe_oa_submit_bb (stream, bb); + fence =xe_oa_submit_bb (stream, bb); +if (IS_ERR (fence)) { + err =PTR_ERR (fence); + goto free_bb; + } +xe_bb_free (bb, fence); +dma_fence_put (fence); + +return 0 ; +free_bb:xe_bb_free (bb,NULL ); exit:return err;
@@ -675,6 +679,7 @@ static int xe_oa_modify_ctx_image(struct xe_oa_stream *stream, struct xe_lrc *lrstatic int xe_oa_load_with_lri (struct xe_oa_stream *stream,struct xe_oa_reg *reg_lri) { +struct dma_fence *fence;struct xe_bb *bb;int err;
@@ -686,7 +691,16 @@ static int xe_oa_load_with_lri(struct xe_oa_stream *stream, struct xe_oa_reg *rewrite_cs_mi_lri (bb, reg_lri,1 ); - err =xe_oa_submit_bb (stream, bb); + fence =xe_oa_submit_bb (stream, bb); +if (IS_ERR (fence)) { + err =PTR_ERR (fence); + goto free_bb; + } +xe_bb_free (bb, fence); +dma_fence_put (fence); + +return 0 ; +free_bb:xe_bb_free (bb,NULL ); exit:return err;
@@ -914,15 +928,32 @@ static int xe_oa_emit_oa_config(struct xe_oa_stream *stream, struct xe_oa_config {#define NOA_PROGRAM_ADDITIONAL_DELAY_US 500struct xe_oa_config_bo *oa_bo; -int err, us =NOA_PROGRAM_ADDITIONAL_DELAY_US ; +int err =0 , us =NOA_PROGRAM_ADDITIONAL_DELAY_US ; +struct dma_fence *fence; +long timeout; +/* Emit OA configuration batch */ oa_bo =xe_oa_alloc_config_buffer (stream, config);if (IS_ERR (oa_bo)) { err =PTR_ERR (oa_bo); goto exit; } - err =xe_oa_submit_bb (stream, oa_bo->bb); + fence =xe_oa_submit_bb (stream, oa_bo->bb); +if (IS_ERR (fence)) { + err =PTR_ERR (fence); + goto exit; + } + +/* Wait till all previous batches have executed */ + timeout =dma_fence_wait_timeout (fence, false,5 *HZ ); +dma_fence_put (fence); +if (timeout <0 ) + err = timeout; +else if (!timeout) + err = -ETIME ; +if (err) +drm_dbg (&stream->oa->xe->drm,"dma_fence_wait_timeout err %d\n" , err);/* Additional empirical delay needed for NOA programming after registers are written */ usleep_range (us,2 * us);
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 3/154 drm/xe/oa/uapi: Define and parse OA sync properties
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ashutosh Dixit <[email protected]>
[ Upstream commit c8507a25cebd179db935dd266a33c51bef1b1e80 ]
Now that we have laid the groundwork, introduce OA sync properties in the uapi and parse the input xe_sync array as is done elsewhere in the driver. Also add DRM_XE_OA_CAPS_SYNCS bit in OA capabilities for userspace.
v2: Fix and document DRM_XE_SYNC_TYPE_USER_FENCE for OA (Matt B)
Add DRM_XE_OA_CAPS_SYNCS bit to OA capabilities (Jose)
Stable-dep-of: f0ed39830e60 ("xe/oa: Fix query mode of operation for OAR/OAC")
--- drivers/gpu/drm/xe/xe_oa.c | 83 +++++++++++++++++++++++++++++++- drivers/gpu/drm/xe/xe_oa_types.h | 6 +++ drivers/gpu/drm/xe/xe_query.c | 2 +- include/uapi/drm/xe_drm.h | 17 +++++++ 4 files changed, 106 insertions(+), 2 deletions(-)
drivers/gpu/drm/xe/xe_oa.c +82 -1
@@ -36,6 +36,7 @@#include "xe_pm.h" #include "xe_sched_job.h" #include "xe_sriov.h" +#include "xe_sync.h" #define DEFAULT_POLL_FREQUENCY_HZ 200#define DEFAULT_POLL_PERIOD_NS (NSEC_PER_SEC / DEFAULT_POLL_FREQUENCY_HZ)
@@ -70,6 +71,7 @@ struct flex { };struct xe_oa_open_param { +struct xe_file *xef;u32 oa_unit_id;bool sample;u32 metric_set;
@@ -81,6 +83,9 @@ struct xe_oa_open_param {struct xe_exec_queue *exec_q;struct xe_hw_engine *hwe;bool no_preempt; +struct drm_xe_sync __user *syncs_user; +int num_syncs; +struct xe_sync_entry *syncs; };struct xe_oa_config_bo {
@@ -1393,6 +1398,9 @@ static int xe_oa_stream_init(struct xe_oa_stream *stream, stream->period_exponent = param->period_exponent; stream->no_preempt = param->no_preempt; + stream->num_syncs = param->num_syncs; + stream->syncs = param->syncs; +/* * For Xe2+, when overrun mode is enabled, there are no partial reports at the end * of buffer, making the OA buffer effectively a non-power-of-2 size circular
@@ -1743,6 +1751,20 @@ static int xe_oa_set_no_preempt(struct xe_oa *oa, u64 value,return 0 ; } +static int xe_oa_set_prop_num_syncs (struct xe_oa *oa,u64 value, +struct xe_oa_open_param *param) +{ + param->num_syncs = value; +return 0 ; +} + +static int xe_oa_set_prop_syncs_user (struct xe_oa *oa,u64 value, +struct xe_oa_open_param *param) +{ + param->syncs_user =u64_to_user_ptr (value); +return 0 ; +} +typedef int (*xe_oa_set_property_fn )(struct xe_oa *oa,u64 value,struct xe_oa_open_param *param);static const xe_oa_set_property_fn xe_oa_set_property_funcs[] = {
@@ -1755,6 +1777,8 @@ static const xe_oa_set_property_fn xe_oa_set_property_funcs[] = { [DRM_XE_OA_PROPERTY_EXEC_QUEUE_ID] = xe_oa_set_prop_exec_queue_id, [DRM_XE_OA_PROPERTY_OA_ENGINE_INSTANCE] = xe_oa_set_prop_engine_instance, [DRM_XE_OA_PROPERTY_NO_PREEMPT] = xe_oa_set_no_preempt, + [DRM_XE_OA_PROPERTY_NUM_SYNCS] = xe_oa_set_prop_num_syncs, + [DRM_XE_OA_PROPERTY_SYNCS] = xe_oa_set_prop_syncs_user, }; static int xe_oa_user_ext_set_property(struct xe_oa *oa, u64 extension,
@@ -1814,6 +1838,49 @@ static int xe_oa_user_extensions(struct xe_oa *oa, u64 extension, int ext_numberreturn 0 ; } +static int xe_oa_parse_syncs (struct xe_oa *oa,struct xe_oa_open_param *param) +{ +int ret, num_syncs, num_ufence =0 ; + +if (param->num_syncs && !param->syncs_user) { +drm_dbg (&oa->xe->drm,"num_syncs specified without sync array\n" ); + ret = -EINVAL ; + goto exit; + } + +if (param->num_syncs) { + param->syncs =kcalloc (param->num_syncs,sizeof (*param->syncs),GFP_KERNEL ); +if (!param->syncs) { + ret = -ENOMEM ; + goto exit; + } + } + +for (num_syncs =0 ; num_syncs < param->num_syncs; num_syncs++) { + ret =xe_sync_entry_parse (oa->xe, param->xef, ¶m->syncs[num_syncs], + ¶m->syncs_user[num_syncs],0 ); +if (ret) + goto err_syncs; + +if (xe_sync_is_ufence (¶m->syncs[num_syncs])) + num_ufence++; + } + +if (XE_IOCTL_DBG (oa->xe, num_ufence >1 )) { + ret = -EINVAL ; + goto err_syncs; + } + +return 0 ; + +err_syncs: +while (num_syncs--) +xe_sync_entry_cleanup (¶m->syncs[num_syncs]); +kfree (param->syncs); +exit: +return ret; +} +/** * xe_oa_stream_open_ioctl - Opens an OA stream * @dev: @drm_device
@@ -1839,6 +1906,7 @@ int xe_oa_stream_open_ioctl(struct drm_device *dev, u64 data, struct drm_file *freturn -ENODEV ; } + param.xef = xef; ret =xe_oa_user_extensions (oa, data,0 , ¶m);if (ret)return ret;
@@ -1907,11 +1975,24 @@ int xe_oa_stream_open_ioctl(struct drm_device *dev, u64 data, struct drm_file *fdrm_dbg (&oa->xe->drm,"Using periodic sampling freq %lld Hz\n" , oa_freq_hz); } + ret =xe_oa_parse_syncs (oa, ¶m); +if (ret) + goto err_exec_q; +mutex_lock (¶m.hwe->gt->oa.gt_lock); ret =xe_oa_stream_open_ioctl_locked (oa, ¶m);mutex_unlock (¶m.hwe->gt->oa.gt_lock); +if (ret <0 ) + goto err_sync_cleanup; + +return ret; + +err_sync_cleanup: +while (param.num_syncs--) +xe_sync_entry_cleanup (¶m.syncs[param.num_syncs]); +kfree (param.syncs); err_exec_q: -if (ret <0 && param.exec_q) +if (param.exec_q)xe_exec_queue_put (param.exec_q);return ret; }
drivers/gpu/drm/xe/xe_oa_types.h +6 -0
@@ -238,5 +238,11 @@ struct xe_oa_stream {/** @no_preempt: Whether preemption and timeslicing is disabled for stream exec_q */ u32 no_preempt; + +/** @num_syncs: size of @syncs array */ +u32 num_syncs; + +/** @syncs: syncs to wait on and to signal */ + struct xe_sync_entry *syncs; };#endif
drivers/gpu/drm/xe/xe_query.c +1 -1
@@ -679,7 +679,7 @@ static int query_oa_units(struct xe_device *xe, du->oa_unit_id = u->oa_unit_id; du->oa_unit_type = u->type; du->oa_timestamp_freq =xe_oa_timestamp_frequency (gt); - du->capabilities =DRM_XE_OA_CAPS_BASE ; + du->capabilities =DRM_XE_OA_CAPS_BASE |DRM_XE_OA_CAPS_SYNCS ; j =0 ;for_each_hw_engine (hwe, gt, hwe_id) {
include/uapi/drm/xe_drm.h +17 -0
@@ -1485,6 +1485,7 @@ struct drm_xe_oa_unit {/** @capabilities: OA capabilities bit-mask */ __u64 capabilities;#define DRM_XE_OA_CAPS_BASE (1 << 0) +#define DRM_XE_OA_CAPS_SYNCS (1 << 1)/** @oa_timestamp_freq: OA timestamp freq */ __u64 oa_timestamp_freq;
@@ -1634,6 +1635,22 @@ enum drm_xe_oa_property_id {* to be disabled for the stream exec queue. */ DRM_XE_OA_PROPERTY_NO_PREEMPT , + +/** +* @DRM_XE_OA_PROPERTY_NUM_SYNCS: Number of syncs in the sync array +* specified in @DRM_XE_OA_PROPERTY_SYNCS +*/ +DRM_XE_OA_PROPERTY_NUM_SYNCS , + +/** +* @DRM_XE_OA_PROPERTY_SYNCS: Pointer to struct @drm_xe_sync array +* with array size specified via @DRM_XE_OA_PROPERTY_NUM_SYNCS. OA +* configuration will wait till input fences signal. Output fences +* will signal after the new OA configuration takes effect. For +* @DRM_XE_SYNC_TYPE_USER_FENCE, @addr is a user pointer, similar +* to the VM bind case. +*/ + DRM_XE_OA_PROPERTY_SYNCS, };/**
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 4/154 drm/xe/oa: Add input fence dependencies
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ashutosh Dixit <[email protected]>
[ Upstream commit 2fb4350a283af03a5ee34ba765783a941f942b82 ]
Add input fence dependencies which will make OA configuration wait till these dependencies are met (till input fences signal).
v2: Change add_deps arg to xe_oa_submit_bb from bool to enum (Matt Brost)
Stable-dep-of: f0ed39830e60 ("xe/oa: Fix query mode of operation for OAR/OAC")
--- drivers/gpu/drm/xe/xe_oa.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-)
drivers/gpu/drm/xe/xe_oa.c +21 -4
@@ -42,6 +42,11 @@#define DEFAULT_POLL_PERIOD_NS (NSEC_PER_SEC / DEFAULT_POLL_FREQUENCY_HZ)#define XE_OA_UNIT_INVALID U32_MAX +enum xe_oa_submit_deps { +XE_OA_SUBMIT_NO_DEPS , +XE_OA_SUBMIT_ADD_DEPS , +}; +struct xe_oa_reg {struct xe_reg addr;u32 value;
@@ -572,7 +577,8 @@ static __poll_t xe_oa_poll(struct file *file, poll_table *wait)return ret; } -static struct dma_fence *xe_oa_submit_bb (struct xe_oa_stream *stream,struct xe_bb *bb) +static struct dma_fence *xe_oa_submit_bb (struct xe_oa_stream *stream,enum xe_oa_submit_deps deps, +struct xe_bb *bb) {struct xe_sched_job *job;struct dma_fence *fence;
@@ -585,11 +591,22 @@ static struct dma_fence *xe_oa_submit_bb(struct xe_oa_stream *stream, struct xe_ goto exit; } +if (deps ==XE_OA_SUBMIT_ADD_DEPS ) { +for (int i =0 ; i < stream->num_syncs && !err; i++) + err =xe_sync_entry_add_deps (&stream->syncs[i], job); +if (err) { +drm_dbg (&stream->oa->xe->drm,"xe_sync_entry_add_deps err %d\n" , err); + goto err_put_job; + } + } +xe_sched_job_arm (job); fence =dma_fence_get (&job->drm.s_fence->finished);xe_sched_job_push (job);return fence; +err_put_job: +xe_sched_job_put (job); exit:return ERR_PTR (err); }
@@ -667,7 +684,7 @@ static int xe_oa_modify_ctx_image(struct xe_oa_stream *stream, struct xe_lrc *lrxe_oa_store_flex (stream, lrc, bb, flex, count); - fence =xe_oa_submit_bb (stream, bb); + fence =xe_oa_submit_bb (stream,XE_OA_SUBMIT_NO_DEPS , bb);if (IS_ERR (fence)) { err =PTR_ERR (fence); goto free_bb;
@@ -696,7 +713,7 @@ static int xe_oa_load_with_lri(struct xe_oa_stream *stream, struct xe_oa_reg *rewrite_cs_mi_lri (bb, reg_lri,1 ); - fence =xe_oa_submit_bb (stream, bb); + fence =xe_oa_submit_bb (stream,XE_OA_SUBMIT_NO_DEPS , bb);if (IS_ERR (fence)) { err =PTR_ERR (fence); goto free_bb;
@@ -944,7 +961,7 @@ static int xe_oa_emit_oa_config(struct xe_oa_stream *stream, struct xe_oa_config goto exit; } - fence =xe_oa_submit_bb (stream, oa_bo->bb); + fence =xe_oa_submit_bb (stream,XE_OA_SUBMIT_ADD_DEPS , oa_bo->bb);if (IS_ERR (fence)) { err =PTR_ERR (fence); goto exit;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 5/154 xe/oa: Fix query mode of operation for OAR/OAC
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Umesh Nerlige Ramappa <[email protected]>
[ Upstream commit 55039832f98c7e05f1cf9e0d8c12b2490abd0f16 ]
This is a set of squashed commits to facilitate smooth applying to stable. Each commit message is retained for reference.
1) Allow a GGTT mapped batch to be submitted to user exec queue
For a OA use case, one of the HW registers needs to be modified by submitting an MI_LOAD_REGISTER_IMM command to the users exec queue, so that the register is modified in the user's hardware context. In order to do this a batch that is mapped in GGTT, needs to be submitted to the user exec queue. Since all user submissions use q->vm and hence PPGTT, add some plumbing to enable submission of batches mapped in GGTT.
v2: ggtt is zero-initialized, so no need to set it false (Matt Brost)
2) xe/oa: Use MI_LOAD_REGISTER_IMMEDIATE to enable OAR/OAC
To enable OAR/OAC, a bit in RING_CONTEXT_CONTROL needs to be set. Setting this bit cause the context image size to change and if not done correct, can cause undesired hangs.
Current code uses a separate exec_queue to modify this bit and is error-prone. As per HW recommendation, submit MI_LOAD_REGISTER_IMM to the target hardware context to modify the relevant bit.
In v2 version, an attempt to submit everything to the user-queue was made, but it failed the unprivileged-single-ctx-counters test. It appears that the OACTXCONTROL must be modified from a remote context.
In v3 version, all context specific register configurations were moved to use LOAD_REGISTER_IMMEDIATE and that seems to work well. This is a cleaner way, since we can now submit all configuration to user exec_queue and the fence handling is simplified.
v2:
(Matt)
- set job->ggtt to true if create job is successful
- unlock vm on job error
(Ashutosh)
- don't wait on job submission
- use kernel exec queue where possible
v3:
(Ashutosh)
- Fix checkpatch issues
- Remove extra spaces/new-lines
- Add Fixes: and Cc: tags
- Reset context control bit when OA stream is closed
- Submit all config via MI_LOAD_REGISTER_IMMEDIATE
(Umesh)
- Update commit message for v3 experiment
- Squash patches for easier port to stable
v4:
(Ashutosh)
- No need to pass q to xe_oa_submit_bb
- Do not support exec queues with width > 1
- Fix disabling of CTX_CTRL_OAC_CONTEXT_ENABLE
v5:
(Ashutosh)
- Drop reg_lri related comments
- Use XE_OA_SUBMIT_NO_DEPS in xe_oa_load_with_lri
Stable-dep-of: f0ed39830e60 ("xe/oa: Fix query mode of operation for OAR/OAC")
--- drivers/gpu/drm/xe/xe_oa.c | 134 ++++++++---------------- drivers/gpu/drm/xe/xe_ring_ops.c | 5 +- drivers/gpu/drm/xe/xe_sched_job_types.h | 2 + 3 files changed, 51 insertions(+), 90 deletions(-)
drivers/gpu/drm/xe/xe_oa.c +45 -89
@@ -69,12 +69,6 @@ struct xe_oa_config {struct rcu_head rcu; }; -struct flex { -struct xe_reg reg; -u32 offset; -u32 value; -}; -struct xe_oa_open_param {struct xe_file *xef;u32 oa_unit_id;
@@ -577,19 +571,38 @@ static __poll_t xe_oa_poll(struct file *file, poll_table *wait)return ret; } +static void xe_oa_lock_vma (struct xe_exec_queue *q) +{ +if (q->vm) { +down_read (&q->vm->lock); +xe_vm_lock (q->vm, false); + } +} + +static void xe_oa_unlock_vma (struct xe_exec_queue *q) +{ +if (q->vm) { +xe_vm_unlock (q->vm); +up_read (&q->vm->lock); + } +} +static struct dma_fence *xe_oa_submit_bb (struct xe_oa_stream *stream,enum xe_oa_submit_deps deps,struct xe_bb *bb) { +struct xe_exec_queue *q = stream->exec_q ?: stream->k_exec_q;struct xe_sched_job *job;struct dma_fence *fence;int err =0 ; -/* Kernel configuration is issued on stream->k_exec_q, not stream->exec_q */ - job =xe_bb_create_job (stream->k_exec_q, bb); +xe_oa_lock_vma (q); + + job =xe_bb_create_job (q, bb);if (IS_ERR (job)) { err =PTR_ERR (job); goto exit; } + job->ggtt = true;if (deps ==XE_OA_SUBMIT_ADD_DEPS ) {for (int i =0 ; i < stream->num_syncs && !err; i++)
@@ -604,10 +617,13 @@ static struct dma_fence *xe_oa_submit_bb(struct xe_oa_stream *stream, enum xe_oa fence =dma_fence_get (&job->drm.s_fence->finished);xe_sched_job_push (job); +xe_oa_unlock_vma (q); +return fence; err_put_job:xe_sched_job_put (job); exit: +xe_oa_unlock_vma (q);return ERR_PTR (err); }
@@ -655,63 +671,19 @@ static void xe_oa_free_configs(struct xe_oa_stream *stream)free_oa_config_bo (oa_bo); } -static void xe_oa_store_flex (struct xe_oa_stream *stream,struct xe_lrc *lrc, -struct xe_bb *bb,const struct flex *flex,u32 count) -{ -u32 offset =xe_bo_ggtt_addr (lrc->bo); - -do { - bb->cs[bb->len++] =MI_STORE_DATA_IMM |MI_SDI_GGTT |MI_SDI_NUM_DW (1 ); - bb->cs[bb->len++] = offset + flex->offset *sizeof (u32); - bb->cs[bb->len++] =0 ; - bb->cs[bb->len++] = flex->value; - - }while (flex++, --count); -} - -static int xe_oa_modify_ctx_image (struct xe_oa_stream *stream,struct xe_lrc *lrc, -const struct flex *flex,u32 count) -{ -struct dma_fence *fence; -struct xe_bb *bb; -int err; - - bb =xe_bb_new (stream->gt,4 * count, false); -if (IS_ERR (bb)) { - err =PTR_ERR (bb); - goto exit; - } - -xe_oa_store_flex (stream, lrc, bb, flex, count); - - fence =xe_oa_submit_bb (stream,XE_OA_SUBMIT_NO_DEPS , bb); -if (IS_ERR (fence)) { - err =PTR_ERR (fence); - goto free_bb; - } -xe_bb_free (bb, fence); -dma_fence_put (fence); - -return 0 ; -free_bb: -xe_bb_free (bb,NULL ); -exit: -return err; -} - -static int xe_oa_load_with_lri (struct xe_oa_stream *stream,struct xe_oa_reg *reg_lri) +static int xe_oa_load_with_lri (struct xe_oa_stream *stream,struct xe_oa_reg *reg_lri,u32 count) {struct dma_fence *fence;struct xe_bb *bb;int err; - bb =xe_bb_new (stream->gt,3 , false); + bb =xe_bb_new (stream->gt,2 * count +1 , false);if (IS_ERR (bb)) { err =PTR_ERR (bb); goto exit; } -write_cs_mi_lri (bb, reg_lri,1 ); +write_cs_mi_lri (bb, reg_lri, count); fence =xe_oa_submit_bb (stream,XE_OA_SUBMIT_NO_DEPS , bb);if (IS_ERR (fence)) {
@@ -731,70 +703,54 @@ static int xe_oa_load_with_lri(struct xe_oa_stream *stream, struct xe_oa_reg *restatic int xe_oa_configure_oar_context (struct xe_oa_stream *stream,bool enable) {const struct xe_oa_format *format = stream->oa_buffer.format; -struct xe_lrc *lrc = stream->exec_q->lrc[0 ]; -u32 regs_offset =xe_lrc_regs_offset (lrc) /sizeof (u32);u32 oacontrol =__format_to_oactrl (format,OAR_OACONTROL_COUNTER_SEL_MASK ) | (enable ?OAR_OACONTROL_COUNTER_ENABLE :0 ); -struct flex regs_context[] = { +struct xe_oa_reg reg_lri[] = { {OACTXCONTROL (stream->hwe->mmio_base), - stream->oa->ctx_oactxctrl_offset[stream->hwe->class] +1 , enable ?OA_COUNTER_RESUME :0 , }, + { +OAR_OACONTROL , + oacontrol, + }, {RING_CONTEXT_CONTROL (stream->hwe->mmio_base), - regs_offset +CTX_CONTEXT_CONTROL , -_MASKED_BIT_ENABLE (CTX_CTRL_OAC_CONTEXT_ENABLE ), +_MASKED_FIELD (CTX_CTRL_OAC_CONTEXT_ENABLE , + enable ?CTX_CTRL_OAC_CONTEXT_ENABLE :0 ) }, }; -struct xe_oa_reg reg_lri = {OAR_OACONTROL , oacontrol }; -int err; - -/* Modify stream hwe context image with regs_context */ - err =xe_oa_modify_ctx_image (stream, stream->exec_q->lrc[0 ], - regs_context,ARRAY_SIZE (regs_context)); -if (err) -return err; -/* Apply reg_lri using LRI */ -return xe_oa_load_with_lri (stream, ®_lri); +return xe_oa_load_with_lri (stream, reg_lri,ARRAY_SIZE (reg_lri)); }static int xe_oa_configure_oac_context (struct xe_oa_stream *stream,bool enable) {const struct xe_oa_format *format = stream->oa_buffer.format; -struct xe_lrc *lrc = stream->exec_q->lrc[0 ]; -u32 regs_offset =xe_lrc_regs_offset (lrc) /sizeof (u32);u32 oacontrol =__format_to_oactrl (format,OAR_OACONTROL_COUNTER_SEL_MASK ) | (enable ?OAR_OACONTROL_COUNTER_ENABLE :0 ); -struct flex regs_context[] = { +struct xe_oa_reg reg_lri[] = { {OACTXCONTROL (stream->hwe->mmio_base), - stream->oa->ctx_oactxctrl_offset[stream->hwe->class] +1 , enable ?OA_COUNTER_RESUME :0 , }, + { +OAC_OACONTROL , + oacontrol + }, {RING_CONTEXT_CONTROL (stream->hwe->mmio_base), - regs_offset +CTX_CONTEXT_CONTROL , -_MASKED_BIT_ENABLE (CTX_CTRL_OAC_CONTEXT_ENABLE ) | +_MASKED_FIELD (CTX_CTRL_OAC_CONTEXT_ENABLE , + enable ?CTX_CTRL_OAC_CONTEXT_ENABLE :0 ) |_MASKED_FIELD (CTX_CTRL_RUN_ALONE , enable ?CTX_CTRL_RUN_ALONE :0 ), }, }; -struct xe_oa_reg reg_lri = {OAC_OACONTROL , oacontrol }; -int err;/* Set ccs select to enable programming of OAC_OACONTROL */ xe_mmio_write32 (stream->gt,__oa_regs (stream)->oa_ctrl,__oa_ccs_select (stream)); -/* Modify stream hwe context image with regs_context */ - err =xe_oa_modify_ctx_image (stream, stream->exec_q->lrc[0 ], - regs_context,ARRAY_SIZE (regs_context)); -if (err) -return err; - -/* Apply reg_lri using LRI */ -return xe_oa_load_with_lri (stream, ®_lri); +return xe_oa_load_with_lri (stream, reg_lri,ARRAY_SIZE (reg_lri)); }static int xe_oa_configure_oa_context (struct xe_oa_stream *stream,bool enable)
@@ -1933,8 +1889,8 @@ int xe_oa_stream_open_ioctl(struct drm_device *dev, u64 data, struct drm_file *fif (XE_IOCTL_DBG (oa->xe, !param.exec_q))return -ENOENT ; -if (param.exec_q->width >1 ) -drm_dbg (&oa->xe->drm,"exec_q->width > 1, programming only exec_q->lrc[0]\n" ); +if (XE_IOCTL_DBG (oa->xe, param.exec_q->width >1 )) +return -EOPNOTSUPP ; }/*
drivers/gpu/drm/xe/xe_ring_ops.c +4 -1
@@ -221,7 +221,10 @@ static int emit_pipe_imm_ggtt(u32 addr, u32 value, bool stall_only, u32 *dw,static u32 get_ppgtt_flag (struct xe_sched_job *job) { -return job->q->vm ?BIT (8 ) :0 ; +if (job->q->vm && !job->ggtt) +return BIT (8 ); + +return 0 ; }static int emit_copy_timestamp (struct xe_lrc *lrc,u32 *dw,int i)
drivers/gpu/drm/xe/xe_sched_job_types.h +2 -0
@@ -57,6 +57,8 @@ struct xe_sched_job {u32 migrate_flush_flags;/** @ring_ops_flush_tlb: The ring ops need to flush TLB before payload. */ bool ring_ops_flush_tlb; +/** @ggtt: mapped in ggtt. */ +bool ggtt;/** @ptrs: per instance pointers. */ struct xe_job_ptrs ptrs[]; };
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 6/154 btrfs: do not assume the full page range is not dirty in extent_writepage_io()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
[ Upstream commit 928b4de66ed3b0d9a6f201ce41ab2eed6ea2e7ef ]
The function extent_writepage_io() will submit the dirty sectors inside the page for the write.
But recently to co-operate with the incoming subpage compression enhancement, a new bitmap is introduced to btrfs_bio_ctrl::submit_bitmap, to only avoid a subset of the dirty range.
This is because we can have the following cases with 64K page size:
0 16K 32K 48K 64K
| |/////////| |/|
52KFor range [16K, 32K), we queue the dirty range for compression, which is ran in a delayed workqueue.
Then for range [48K, 52K), we go through the regular submission path.
In that case, our btrfs_bio_ctrl::submit_bitmap will exclude the range [16K, 32K).
The dirty flags for the range [16K, 32K) is only cleared when the compression is done, by the extent_clear_unlock_delalloc() call inside submit_one_async_extent().
This patch fix the false alert by removing the btrfs_folio_assert_not_dirty() check, since it's no longer correct for subpage compression cases.
Stable-dep-of: 8bf334beb349 ("btrfs: fix double accounting race when extent_writepage_io() failed")
--- fs/btrfs/extent_io.c | 2 -- 1 file changed, 2 deletions(-)
fs/btrfs/extent_io.c +0 -2
@@ -1394,8 +1394,6 @@ static noinline_for_stack int extent_writepage_io(struct btrfs_inode *inode, goto out; submitted_io = true; } - -btrfs_folio_assert_not_dirty (fs_info, folio, start, len); out:/* * If we didn't submitted any sector (>= i_size), folio dirty get
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 7/154 btrfs: move the delalloc range bitmap search into extent_io.c
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
[ Upstream commit 2bca8eb0774d271b1077b72f1be135073e0a898f ]
Currently for subpage (sector size < page size) cases, we reuse subpage locked bitmap to find out all delalloc ranges we have locked, and run all those found ranges.
However such reuse is not perfect, e.g.:
0 32K 64K 96K 128K
| |////////||///////| |////|
120KFor above range, writepage_delalloc() for page 0 will handle the range [32K, 96k), note delalloc range can be beyond the page boundary.
But writepage_delalloc() for page 64K will only handle range [120K, 128K), as the previous run on page 0 has already handled range [64K, 96K).
Meanwhile for the writeback we should expect range [64K, 96K) to also be locked, this leads to the mismatch from locked bitmap and delalloc range.
This is not causing problems yet, but it's still an inconsistent behavior.
So instead of relying on the subpage locked bitmap, move the delalloc range search using local @delalloc_bitmap, so that we can remove the existing btrfs_folio_find_writer_locked().
Stable-dep-of: 8bf334beb349 ("btrfs: fix double accounting race when extent_writepage_io() failed")
--- fs/btrfs/extent_io.c | 44 ++++++++++++++++++++++++++++++++++++++++- fs/btrfs/subpage.c | 47 -------------------------------------------- fs/btrfs/subpage.h | 4 ---- 3 files changed, 43 insertions(+), 52 deletions(-)
fs/btrfs/extent_io.c +43 -1
@@ -1105,6 +1105,45 @@ int btrfs_read_folio(struct file *file, struct folio *folio)return ret; } +static void set_delalloc_bitmap (struct folio *folio,unsigned long *delalloc_bitmap, +u64 start,u32 len) +{ +struct btrfs_fs_info *fs_info =folio_to_fs_info (folio); +const u64 folio_start =folio_pos (folio); +unsigned int start_bit; +unsigned int nbits; + +ASSERT (start >= folio_start && start + len <= folio_start +PAGE_SIZE ); + start_bit = (start - folio_start) >> fs_info->sectorsize_bits; + nbits = len >> fs_info->sectorsize_bits; +ASSERT (bitmap_test_range_all_zero (delalloc_bitmap, start_bit, nbits)); +bitmap_set (delalloc_bitmap, start_bit, nbits); +} + +static bool find_next_delalloc_bitmap (struct folio *folio, +unsigned long *delalloc_bitmap,u64 start, +u64 *found_start,u32 *found_len) +{ +struct btrfs_fs_info *fs_info =folio_to_fs_info (folio); +const u64 folio_start =folio_pos (folio); +const unsigned int bitmap_size = fs_info->sectors_per_page; +unsigned int start_bit; +unsigned int first_zero; +unsigned int first_set; + +ASSERT (start >= folio_start && start < folio_start +PAGE_SIZE ); + + start_bit = (start - folio_start) >> fs_info->sectorsize_bits; + first_set =find_next_bit (delalloc_bitmap, bitmap_size, start_bit); +if (first_set >= bitmap_size) +return false; + + *found_start = folio_start + (first_set << fs_info->sectorsize_bits); + first_zero =find_next_zero_bit (delalloc_bitmap, bitmap_size, first_set); + *found_len = (first_zero - first_set) << fs_info->sectorsize_bits; +return true; +} +/* * helper for extent_writepage(), doing all of the delayed allocation setup. *
@@ -1124,6 +1163,7 @@ static noinline_for_stack int writepage_delalloc(struct btrfs_inode *inode,const bool is_subpage =btrfs_is_subpage (fs_info, folio->mapping);const u64 page_start =folio_pos (folio);const u64 page_end = page_start +folio_size (folio) -1 ; +unsigned long delalloc_bitmap =0 ;/* * Save the last found delalloc end. As the delalloc end can go beyond * page boundary, thus we cannot rely on subpage bitmap to locate the
@@ -1151,6 +1191,8 @@ static noinline_for_stack int writepage_delalloc(struct btrfs_inode *inode, delalloc_start = delalloc_end +1 ;continue ; } +set_delalloc_bitmap (folio, &delalloc_bitmap, delalloc_start, +min (delalloc_end, page_end) +1 - delalloc_start);btrfs_folio_set_writer_lock (fs_info, folio, delalloc_start,min (delalloc_end, page_end) +1 - delalloc_start);
@@ -1178,7 +1220,7 @@ static noinline_for_stack int writepage_delalloc(struct btrfs_inode *inode, found_len = last_delalloc_end +1 - found_start; found = true; }else { - found =btrfs_subpage_find_writer_locked (fs_info, folio, + found =find_next_delalloc_bitmap (folio, &delalloc_bitmap, delalloc_start, &found_start, &found_len); }if (!found)
fs/btrfs/subpage.c +0 -47
53 lines not on this page · raw message
fs/btrfs/subpage.h +0 -4
@@ -108,10 +108,6 @@ void btrfs_folio_set_writer_lock(const struct btrfs_fs_info *fs_info, struct folio *folio, u64 start, u32 len);void btrfs_folio_end_writer_lock_bitmap (const struct btrfs_fs_info *fs_info,struct folio *folio,unsigned long bitmap); -bool btrfs_subpage_find_writer_locked (const struct btrfs_fs_info *fs_info, -struct folio *folio,u64 search_start, -u64 *found_start_ret,u32 *found_len_ret); -/* * Template for subpage related operations. *
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 8/154 btrfs: mark all dirty sectors as locked inside writepage_delalloc()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
[ Upstream commit c96d0e3921419bd3e5d8a1f355970c8ae3047ef4 ]
Currently we only mark sectors as locked if there is a *NEW* delalloc range for it.
But NEW delalloc range is not the same as dirty sectors we want to submit, e.g:
0 32K 64K 96K 128K
| |////////||///////| |////|
120KFor above 64K page size case, writepage_delalloc() for page 0 will find and lock the delalloc range [32K, 96K), which is beyond the page boundary.
Then when writepage_delalloc() is called for the page 64K, since [64K, 96K) is already locked, only [120K, 128K) will be locked.
This means, although range [64K, 96K) is dirty and will be submitted later by extent_writepage_io(), it will not be marked as locked.
This is fine for now, as we call btrfs_folio_end_writer_lock_bitmap() to free every non-compressed sector, and compression is only allowed for full page range.
But this is not safe for future sector perfect compression support, as this can lead to double folio unlock:
Thread A | Thread B
---------------------------------------+--------------------------------
| submit_one_async_extent() | |- extent_clear_unlock_delalloc()
extent_writepage() | |- btrfs_folio_end_writer_lock() |- btrfs_folio_end_writer_lock_bitmap()| |- btrfs_subpage_end_and_test_writer() | | | |- atomic_sub_and_test() | | | /* Now the atomic value is 0 */ |- if (atomic_read() == 0) | | |- folio_unlock() | |- folio_unlock()
The root cause is the above range [64K, 96K) is dirtied and should also be locked but it isn't.
So to make everything more consistent and prepare for the incoming sector perfect compression, mark all dirty sectors as locked.
Stable-dep-of: 8bf334beb349 ("btrfs: fix double accounting race when extent_writepage_io() failed")
--- fs/btrfs/extent_io.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
fs/btrfs/extent_io.c +7 -3
@@ -1174,6 +1174,7 @@ static noinline_for_stack int writepage_delalloc(struct btrfs_inode *inode,u64 delalloc_end = page_end;u64 delalloc_to_write =0 ;int ret =0 ; +int bit;/* Save the dirty bitmap as our submission bitmap will be a subset of it. */ if (btrfs_is_subpage (fs_info, inode->vfs_inode.i_mapping)) {
@@ -1183,6 +1184,12 @@ static noinline_for_stack int writepage_delalloc(struct btrfs_inode *inode, bio_ctrl->submit_bitmap =1 ; } +for_each_set_bit (bit, &bio_ctrl->submit_bitmap, fs_info->sectors_per_page) { +u64 start = page_start + (bit << fs_info->sectorsize_bits); + +btrfs_folio_set_writer_lock (fs_info, folio, start, fs_info->sectorsize); + } +/* Lock all (subpage) delalloc ranges inside the folio first. */ while (delalloc_start < page_end) { delalloc_end = page_end;
@@ -1193,9 +1200,6 @@ static noinline_for_stack int writepage_delalloc(struct btrfs_inode *inode, }set_delalloc_bitmap (folio, &delalloc_bitmap, delalloc_start,min (delalloc_end, page_end) +1 - delalloc_start); -btrfs_folio_set_writer_lock (fs_info, folio, delalloc_start, -min (delalloc_end, page_end) +1 - - delalloc_start); last_delalloc_end = delalloc_end; delalloc_start = delalloc_end +1 ; }
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 9/154 btrfs: remove unused btrfs_folio_start_writer_lock()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
[ Upstream commit 8511074c42b6255e03eceb09396338572572f1c7 ]
This function is not really suitable to lock a folio, as it lacks the proper mapping checks, thus the locked folio may not even belong to btrfs.
And due to the above reason, the last user inside lock_delalloc_folios() is already removed, and we can remove this function.
Stable-dep-of: 8bf334beb349 ("btrfs: fix double accounting race when extent_writepage_io() failed")
--- fs/btrfs/subpage.c | 47 ---------------------------------------------- fs/btrfs/subpage.h | 2 -- 2 files changed, 49 deletions(-)
fs/btrfs/subpage.c +0 -47
@@ -295,26 +295,6 @@ static void btrfs_subpage_clamp_range(struct folio *folio, u64 *start, u32 *len) orig_start + orig_len) - *start; } -static void btrfs_subpage_start_writer (const struct btrfs_fs_info *fs_info, -struct folio *folio,u64 start,u32 len) -{ -struct btrfs_subpage *subpage =folio_get_private (folio); -const int start_bit =subpage_calc_start_bit (fs_info, folio, locked, start, len); -const int nbits = (len >> fs_info->sectorsize_bits); -unsigned long flags; -int ret; - -btrfs_subpage_assert (fs_info, folio, start, len); - -spin_lock_irqsave (&subpage->lock, flags); -ASSERT (atomic_read (&subpage->readers) ==0 ); -ASSERT (bitmap_test_range_all_zero (subpage->bitmaps, start_bit, nbits)); -bitmap_set (subpage->bitmaps, start_bit, nbits); - ret =atomic_add_return (nbits, &subpage->writers); -ASSERT (ret == nbits); -spin_unlock_irqrestore (&subpage->lock, flags); -} -static bool btrfs_subpage_end_and_test_writer (const struct btrfs_fs_info *fs_info,struct folio *folio,u64 start,u32 len) {
@@ -351,33 +331,6 @@ static bool btrfs_subpage_end_and_test_writer(const struct btrfs_fs_info *fs_infreturn last; } -/* -* Lock a folio for delalloc page writeback. -* -* Return -EAGAIN if the page is not properly initialized. -* Return 0 with the page locked, and writer counter updated. -* -* Even with 0 returned, the page still need extra check to make sure -* it's really the correct page, as the caller is using -* filemap_get_folios_contig(), which can race with page invalidating. -*/ -int btrfs_folio_start_writer_lock (const struct btrfs_fs_info *fs_info, -struct folio *folio,u64 start,u32 len) -{ -if (unlikely (!fs_info) || !btrfs_is_subpage (fs_info, folio->mapping)) { -folio_lock (folio); -return 0 ; - } -folio_lock (folio); -if (!folio_test_private (folio) || !folio_get_private (folio)) { -folio_unlock (folio); -return -EAGAIN ; - } -btrfs_subpage_clamp_range (folio, &start, &len); -btrfs_subpage_start_writer (fs_info, folio, start, len); -return 0 ; -} -/* * Handle different locked folios: *
fs/btrfs/subpage.h +0 -2
@@ -100,8 +100,6 @@ void btrfs_subpage_start_reader(const struct btrfs_fs_info *fs_info,void btrfs_subpage_end_reader (const struct btrfs_fs_info *fs_info,struct folio *folio,u64 start,u32 len); -int btrfs_folio_start_writer_lock (const struct btrfs_fs_info *fs_info, -struct folio *folio,u64 start,u32 len);void btrfs_folio_end_writer_lock (const struct btrfs_fs_info *fs_info,struct folio *folio,u64 start,u32 len); void btrfs_folio_set_writer_lock(const struct btrfs_fs_info *fs_info,
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainercover 6.12.17-rc1 review
This is the start of the stable review cycle for the 6.12.17 release. There are 154 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 26 Feb 2025 14:25:29 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.12.17-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.12.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 6.12.17-rc1
Alex Deucher <[email protected]>
drm/amdgpu: bump version for RV/PCO compute fix
Alex Deucher <[email protected]>
drm/amdgpu/gfx9: manually control gfxoff for CS on RV
Tianling Shen <[email protected]>
arm64: dts: rockchip: change eth phy mode to rgmii-id for orangepi r1 plus lts
Kevin Brodsky <[email protected]>
selftests/mm: build with -O2
Tejun Heo <[email protected]>
sched_ext: Fix incorrect assumption about migration disabled tasks in task_can_run_on_remote_rq()
Kory Maincent <[email protected]>
net: pse-pd: Fix deadlock in current limit functions
Steven Rostedt <[email protected]>
tracing: Fix using ret variable in tracing_set_tracer()
Steven Rostedt <[email protected]>
ftrace: Do not add duplicate entries in subops manager ops
Steven Rostedt <[email protected]>
ftrace: Fix accounting of adding subops to a manager ops
Sebastian Andrzej Siewior <[email protected]>
ftrace: Correct preemption accounting for function tracing.
Komal Bajaj <[email protected]>
EDAC/qcom: Correct interrupt enable register configuration
Haoxiang Li <[email protected]>
smb: client: Add check for next_buffer in receive_encrypted_standard()
Marc Zyngier <[email protected]>
irqchip/gic-v3: Fix rk3399 workaround when secure interrupts are enabled
Kan Liang <[email protected]>
perf/x86/intel: Fix event constraints for LNC
Niravkumar L Rabara <[email protected]>
mtd: rawnand: cadence: fix incorrect device in dma_unmap_single
Niravkumar L Rabara <[email protected]>
mtd: rawnand: cadence: use dma_map_resource for sdma address
Niravkumar L Rabara <[email protected]>
mtd: rawnand: cadence: fix error code in cadence_nand_init()
Amit Kumar Mahapatra <[email protected]>
mtd: spi-nor: sst: Fix SST write failure
Ricardo Cañuelo Navarro <[email protected]>
mm,madvise,hugetlb: check for 0-length range after end address adjustment
Christian Brauner <[email protected]>
acct: block access to kernel internal filesystems
Christian Brauner <[email protected]>
acct: perform last write from workqueue
Peter Ujfalusi <[email protected]>
ASoC: SOF: pcm: Clear the susbstream pointer to NULL on close
John Veness <[email protected]>
ALSA: hda/conexant: Add quirk for HP ProBook 450 G4 mute LED
Wentao Liang <[email protected]>
ALSA: hda: Add error check for snd_ctl_rename_id() in snd_hda_create_dig_out_ctls()
Nikita Zhandarovich <[email protected]>
ASoC: fsl_micfil: Enable default case in micfil_set_quality()
Peter Ujfalusi <[email protected]>
ASoC: SOF: stream-ipc: Check for cstream nullity in sof_ipc_msg_data()
Joshua Washington <[email protected]>
gve: set xdp redirect target only when it is available
Haoxiang Li <[email protected]>
nfp: bpf: Add check for nfp_app_ctrl_msg_alloc()
Paulo Alcantara <[email protected]>
smb: client: fix chmod(2) regression with ATTR_READONLY
Pavel Begunkov <[email protected]>
lib/iov_iter: fix import_iovec_ubuf iovec management
Darrick J. Wong <[email protected]>
xfs: fix online repair probing when CONFIG_XFS_ONLINE_REPAIR=n
Heiko Carstens <[email protected]>
s390/boot: Fix ESSA detection
Haoxiang Li <[email protected]>
soc: loongson: loongson2_guts: Add check for devm_kstrdup()
Lukasz Czechowski <[email protected]>
arm64: dts: rockchip: Disable DMA for uart5 on px30-ringneck
Lukasz Czechowski <[email protected]>
arm64: dts: rockchip: Move uart5 pin configuration to px30 ringneck SoM
Alexander Shiyan <[email protected]>
arm64: dts: rockchip: Fix broken tsadc pinctrl names for rk3588
David Hildenbrand <[email protected]>
mm/migrate_device: don't add folio to be freed to LRU in migrate_device_finalize()
Gavrilov Ilia <[email protected]>
drop_monitor: fix incorrect initialization order
Sumit Garg <[email protected]>
tee: optee: Fix supplicant wait loop
Bartosz Golaszewski <[email protected]>
gpiolib: protect gpio_chip with SRCU in array_info paths in multi get/set
Bartosz Golaszewski <[email protected]>
gpiolib: check the return value of gpio_chip::get_direction()
Pavel Begunkov <[email protected]>
io_uring: prevent opcode speculation
Pavel Begunkov <[email protected]>
io_uring/rw: forbid multishot async reads
Krzysztof Karas <[email protected]>
drm/i915/gt: Use spin_lock_irqsave() in interruptible context
Imre Deak <[email protected]>
drm/i915/ddi: Fix HDMI port width programming in DDI_BUF_CTL
Imre Deak <[email protected]>
drm/i915/dp: Fix error handling during 128b/132b link training
Ville Syrjälä <[email protected]>
drm/i915: Make sure all planes in use by the joiner have their crtc included
Jessica Zhang <[email protected]>
drm/msm/dpu: Disable dither in phys encoder cleanup
Hugo Villeneuve <[email protected]>
drm: panel: jd9365da-h3: fix reset signal polarity
Artur Rojek <[email protected]>
irqchip/jcore-aic, clocksource/drivers/jcore: Fix jcore-pit interrupt request
Aaron Kling <[email protected]>
drm/nouveau/pmu: Fix gp10b firmware guard
Yan Zhai <[email protected]>
bpf: skip non exist keys in generic_map_lookup_batch
Caleb Sander Mateos <[email protected]>
nvme/ioctl: add missing space in err message
Caleb Sander Mateos <[email protected]>
nvme-tcp: fix connect failure on receiving partial ICResp PDU
Damien Le Moal <[email protected]>
nvme: tcp: Fix compilation warning with W=1
Krzysztof Kozlowski <[email protected]>
drm/msm/dsi/phy: Do not overwite PHY_CMN_CLK_CFG1 when choosing bitclk source
Krzysztof Kozlowski <[email protected]>
drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG1 against clock driver
Krzysztof Kozlowski <[email protected]>
drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG0 updated from driver side
Marijn Suijten <[email protected]>
drm/msm/dpu: Don't leak bits_per_component into random DSC_ENC fields
Dmitry Baryshkov <[email protected]>
drm/msm/dpu: enable DPU_WB_INPUT_CTRL for DPU 5.x
Dmitry Baryshkov <[email protected]>
drm/msm/dpu: skip watchdog timer programming through TOP on >= SM8450
Rob Clark <[email protected]>
drm/msm: Avoid rounding up to one jiffy
David Hildenbrand <[email protected]>
nouveau/svm: fix missing folio unlock + put after make_device_exclusive_range()
Geert Uytterhoeven <[email protected]>
platform: cznic: CZNIC_PLATFORMS should depend on ARCH_MVEBU
Geert Uytterhoeven <[email protected]>
firmware: imx: IMX_SCMI_MISC_DRV should depend on ARCH_MXC
Bart Van Assche <[email protected]>
md/raid*: Fix the set_queue_limits implementations
Peng Fan <[email protected]>
firmware: arm_scmi: imx: Correct tx size of scmi_imx_misc_ctrl_set
Patrick Wildt <[email protected]>
arm64: dts: rockchip: adjust SMMU interrupt type on rk3588
Alan Maguire <[email protected]>
bpf: Fix softlockup in arena_map_free on 64k page kernel
Kuniyuki Iwashima <[email protected]>
net: Add rx_skb of kfree_skb to raw_tp_null_args[].
Kumar Kartikeya Dwivedi <[email protected]>
selftests/bpf: Add tests for raw_tp null handling
Chris Morgan <[email protected]>
power: supply: axp20x_battery: Fix fault handling for AXP717
Andrey Vatoropin <[email protected]>
power: supply: da9150-fg: fix potential overflow
Andy Yan <[email protected]>
arm64: dts: rockchip: Fix lcdpwr_en pin for Cool Pi GenBook
Abel Wu <[email protected]>
bpf: Fix deadlock when freeing cgroup storage
Jiayuan Chen <[email protected]>
bpf: Disable non stream socket for strparser
Jiayuan Chen <[email protected]>
bpf: Fix wrong copied_seq calculation
Jiayuan Chen <[email protected]>
strparser: Add read_sock callback
Andrii Nakryiko <[email protected]>
bpf: avoid holding freeze_mutex during mmap operation
Andrii Nakryiko <[email protected]>
bpf: unify VM_WRITE vs VM_MAYWRITE use in BPF map mmaping logic
Shigeru Yoshida <[email protected]>
bpf, test_run: Fix use-after-free issue in eth_skb_pkt_type()
Paolo Abeni <[email protected]>
net: allow small head cache usage with large MAX_SKB_FRAGS values
Sabrina Dubroca <[email protected]>
tcp: drop secpath at the same time as we currently drop dst
Nick Hu <[email protected]>
net: axienet: Set mac_managed_pm
Breno Leitao <[email protected]>
arp: switch to dev_getbyhwaddr() in arp_req_set_public()
Breno Leitao <[email protected]>
net: Add non-RCU dev_getbyhwaddr() helper
Cong Wang <[email protected]>
flow_dissector: Fix port range key handling in BPF conversion
Cong Wang <[email protected]>
flow_dissector: Fix handling of mixed port and port-range keys
Kuniyuki Iwashima <[email protected]>
geneve: Suppress list corruption splat in geneve_destroy_tunnels().
Kuniyuki Iwashima <[email protected]>
gtp: Suppress list corruption splat in gtp_net_exit_batch_rtnl().
Kory Maincent <[email protected]>
net: pse-pd: pd692x0: Fix power limit retrieval
Kory Maincent <[email protected]>
net: pse-pd: Use power limit at driver side instead of current limit
Kory Maincent <[email protected]>
net: pse-pd: Avoid setting max_uA in regulator constraints
Jakub Kicinski <[email protected]>
tcp: adjust rcvq_space after updating scaling ratio
Michal Luczaj <[email protected]>
vsock/bpf: Warn on socket without transport
Michal Luczaj <[email protected]>
sockmap, vsock: For connectible sockets allow only connected
Nick Child <[email protected]>
ibmvnic: Don't reference skb after sending to VIOS
Nick Child <[email protected]>
ibmvnic: Add stat for tx direct vs tx batched
Julian Ruess <[email protected]>
s390/ism: add release function for struct device
Takashi Iwai <[email protected]>
ALSA: seq: Drop UMP events when no UMP-conversion is set
Pierre Riteau <[email protected]>
net/sched: cls_api: fix error handling causing NULL dereference
Vitaly Rodionov <[email protected]>
ALSA: hda/cirrus: Correct the full scale volume set logic
Kuniyuki Iwashima <[email protected]>
geneve: Fix use-after-free in geneve_find_dev().
Junnan Wu <[email protected]>
vsock/virtio: fix variables initialization during resuming
Shengjiu Wang <[email protected]>
ASoC: imx-audmix: remove cpu_mclk which is from cpu dai device
Christophe Leroy <[email protected]>
powerpc/code-patching: Fix KASAN hit by not flagging text patching area as VM_ALLOC
Kailang Yang <[email protected]>
ALSA: hda/realtek: Fixup ALC225 depop procedure
Christophe Leroy <[email protected]>
powerpc/64s: Rewrite __real_pte() and __rpte_to_hidx() as static inline
Christophe Leroy <[email protected]>
powerpc/code-patching: Disable KASAN report during patching via temporary mm
Peter Ujfalusi <[email protected]>
ASoC: SOF: ipc4-topology: Harden loops for looking up ALH copiers
John Keeping <[email protected]>
ASoC: rockchip: i2s-tdm: fix shift config for SND_SOC_DAIFMT_DSP_[AB]
Tejun Heo <[email protected]>
sched_ext: Fix migration disabled handling in targeted dispatches
Tejun Heo <[email protected]>
sched_ext: Factor out move_task_between_dsqs() from scx_dispatch_from_dsq()
Jill Donahue <[email protected]>
USB: gadget: f_midi: f_midi_complete to call queue_work
Steven Rostedt <[email protected]>
tracing: Have the error of __tracing_resize_ring_buffer() passed to user
Steven Rostedt <[email protected]>
tracing: Switch trace.c code over to use guard()
Lancelot SIX <[email protected]>
drm/amdkfd: Ensure consistent barrier state saved in gfx12 trap handler
Jay Cornwall <[email protected]>
drm/amdkfd: Move gfx12 trap handler to separate file
Jacek Lawrynowicz <[email protected]>
accel/ivpu: Fix error handling in recovery/reset
Tomasz Rusinowicz <[email protected]>
accel/ivpu: Add FW state dump on TDR
Karol Wachowski <[email protected]>
accel/ivpu: Add coredump support
Jacek Lawrynowicz <[email protected]>
accel/ivpu: Limit FW version string length
Chen-Yu Tsai <[email protected]>
arm64: dts: mediatek: mt8183: Disable DSI display output by default
Fabien Parent <[email protected]>
arm64: dts: mediatek: mt8183-pumpkin: add HDMI support
Takashi Iwai <[email protected]>
PCI: Restore original INTX_DISABLE bit by pcim_intx()
Philipp Stanner <[email protected]>
PCI: Remove devres from pci_intx()
Philipp Stanner <[email protected]>
PCI: Export pci_intx_unmanaged() and pcim_intx()
Philipp Stanner <[email protected]>
PCI: Make pcim_request_all_regions() a public function
Dan Carpenter <[email protected]>
ASoC: renesas: rz-ssi: Add a check for negative sample_space
Claudiu Beznea <[email protected]>
ASoC: renesas: rz-ssi: Terminate all the DMA transactions
Dmitry Torokhov <[email protected]>
Input: synaptics - fix crash when enabling pass-through port
Dmitry Torokhov <[email protected]>
Input: serio - define serio_pause_rx guard to pause and resume serio ports
Zijun Hu <[email protected]>
Bluetooth: qca: Fix poor RF performance for WCN6855
Cheng Jiang <[email protected]>
Bluetooth: qca: Update firmware-name to support board specific nvm
loanchen <[email protected]>
drm/amd/display: Correct register address in dcn35
Charlene Liu <[email protected]>
drm/amd/display: update dcn351 used clock offset
Lohita Mudimela <[email protected]>
drm/amd/display: Refactoring if and endif statements to enable DC_LOGGER
Chao Gao <[email protected]>
KVM: nVMX: Defer SVI update to vmcs01 on EOI when L2 is active w/o VID
Sean Christopherson <[email protected]>
KVM: x86: Inline kvm_get_apic_mode() in lapic.h
Sean Christopherson <[email protected]>
KVM: x86: Get vcpu->arch.apic_base directly and drop kvm_get_apic_base()
Qu Wenruo <[email protected]>
btrfs: fix double accounting race when extent_writepage_io() failed
Qu Wenruo <[email protected]>
btrfs: fix double accounting race when btrfs_run_delalloc_range() failed
David Sterba <[email protected]>
btrfs: use btrfs_inode in extent_writepage()
Qu Wenruo <[email protected]>
btrfs: rename btrfs_folio_(set|start|end)_writer_lock()
Qu Wenruo <[email protected]>
btrfs: unify to use writer locks for subpage locking
Qu Wenruo <[email protected]>
btrfs: remove unused btrfs_folio_start_writer_lock()
Qu Wenruo <[email protected]>
btrfs: mark all dirty sectors as locked inside writepage_delalloc()
Qu Wenruo <[email protected]>
btrfs: move the delalloc range bitmap search into extent_io.c
Qu Wenruo <[email protected]>
btrfs: do not assume the full page range is not dirty in extent_writepage_io()
Umesh Nerlige Ramappa <[email protected]>
xe/oa: Fix query mode of operation for OAR/OAC
Ashutosh Dixit <[email protected]>
drm/xe/oa: Add input fence dependencies
Ashutosh Dixit <[email protected]>
drm/xe/oa/uapi: Define and parse OA sync properties
Ashutosh Dixit <[email protected]>
drm/xe/oa: Separate batch submission from waiting for completion
Catalin Marinas <[email protected]>
arm64: mte: Do not allow PROT_MTE on MAP_HUGETLB user mappings
-------------
Diffstat:
Documentation/networking/strparser.rst | 9 +- Makefile | 4 +- arch/arm64/boot/dts/mediatek/mt8183-pumpkin.dts | 123 ++- arch/arm64/boot/dts/mediatek/mt8183.dtsi | 1 + .../boot/dts/rockchip/px30-ringneck-haikou.dts | 1 - arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi | 6 + .../dts/rockchip/rk3328-orangepi-r1-plus-lts.dts | 6 +- arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 22 +- .../dts/rockchip/rk3588-coolpi-cm5-genbook.dts | 4 +- arch/arm64/include/asm/mman.h | 9 +- arch/powerpc/include/asm/book3s/64/hash-4k.h | 12 +- arch/powerpc/lib/code-patching.c | 4 +- arch/s390/boot/startup.c | 2 +- arch/x86/events/intel/core.c | 20 +- arch/x86/events/intel/ds.c | 2 +- arch/x86/kvm/lapic.c | 11 + arch/x86/kvm/lapic.h | 8 +- arch/x86/kvm/vmx/nested.c | 5 + arch/x86/kvm/vmx/vmx.c | 21 + arch/x86/kvm/vmx/vmx.h | 1 + arch/x86/kvm/x86.c | 17 +- drivers/accel/ivpu/Kconfig | 1 + drivers/accel/ivpu/Makefile | 1 + drivers/accel/ivpu/ivpu_coredump.c | 39 + drivers/accel/ivpu/ivpu_coredump.h | 25 + drivers/accel/ivpu/ivpu_drv.c | 5 +- drivers/accel/ivpu/ivpu_drv.h | 1 + drivers/accel/ivpu/ivpu_fw.c | 7 +- drivers/accel/ivpu/ivpu_fw.h | 6 +- drivers/accel/ivpu/ivpu_fw_log.h | 8 - drivers/accel/ivpu/ivpu_hw.c | 3 + drivers/accel/ivpu/ivpu_ipc.c | 26 + drivers/accel/ivpu/ivpu_ipc.h | 2 + drivers/accel/ivpu/ivpu_jsm_msg.c | 8 + drivers/accel/ivpu/ivpu_jsm_msg.h | 2 + drivers/accel/ivpu/ivpu_pm.c | 85 +- drivers/bluetooth/btqca.c | 118 +- drivers/clocksource/jcore-pit.c | 15 +- drivers/edac/qcom_edac.c | 4 +- .../firmware/arm_scmi/vendors/imx/imx-sm-misc.c | 4 +- drivers/firmware/imx/Kconfig | 1 + drivers/gpio/gpiolib.c | 92 +- drivers/gpio/gpiolib.h | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 3 +- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 32 +- drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h | 3 +- .../gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm | 202 +--- .../gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx12.asm | 1130 ++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c | 5 +- .../amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c | 5 +- .../amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c | 6 +- .../amd/display/dc/clk_mgr/dcn35/dcn351_clk_mgr.c | 140 +++ .../amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 131 ++- .../amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.h | 4 + .../drm/amd/display/dc/inc/hw/clk_mgr_internal.h | 59 + .../display/dc/link/protocols/link_dp_capability.c | 3 +- drivers/gpu/drm/i915/display/intel_ddi.c | 2 +- drivers/gpu/drm/i915/display/intel_display.c | 18 + .../gpu/drm/i915/display/intel_dp_link_training.c | 15 +- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 4 +- drivers/gpu/drm/i915/i915_reg.h | 2 +- .../gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h | 2 +- .../drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h | 2 +- .../gpu/drm/msm/disp/dpu1/catalog/dpu_5_4_sm6125.h | 2 +- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 3 + drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c | 3 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c | 2 +- drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 53 +- drivers/gpu/drm/msm/msm_drv.h | 11 +- .../gpu/drm/msm/registers/display/dsi_phy_7nm.xml | 11 +- drivers/gpu/drm/nouveau/nouveau_svm.c | 9 +- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c | 2 +- drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c | 8 +- drivers/gpu/drm/xe/xe_oa.c | 265 +++-- drivers/gpu/drm/xe/xe_oa_types.h | 6 + drivers/gpu/drm/xe/xe_query.c | 2 +- drivers/gpu/drm/xe/xe_ring_ops.c | 5 +- drivers/gpu/drm/xe/xe_sched_job_types.h | 2 + drivers/input/mouse/synaptics.c | 56 +- drivers/input/mouse/synaptics.h | 1 + drivers/irqchip/irq-gic-v3.c | 49 +- drivers/irqchip/irq-jcore-aic.c | 2 +- drivers/md/raid0.c | 4 +- drivers/md/raid1.c | 4 +- drivers/md/raid10.c | 4 +- drivers/mtd/nand/raw/cadence-nand-controller.c | 42 +- drivers/mtd/spi-nor/sst.c | 2 +- drivers/net/ethernet/google/gve/gve.h | 10 + drivers/net/ethernet/google/gve/gve_main.c | 6 +- drivers/net/ethernet/ibm/ibmvnic.c | 27 +- drivers/net/ethernet/ibm/ibmvnic.h | 3 +- drivers/net/ethernet/netronome/nfp/bpf/cmsg.c | 2 + drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 1 + drivers/net/geneve.c | 16 +- drivers/net/gtp.c | 5 - drivers/net/pse-pd/pd692x0.c | 45 +- drivers/net/pse-pd/pse_core.c | 98 +- drivers/nvme/host/ioctl.c | 3 +- drivers/nvme/host/tcp.c | 7 +- drivers/pci/devres.c | 61 +- drivers/pci/pci.c | 16 +- drivers/platform/cznic/Kconfig | 1 + drivers/power/supply/axp20x_battery.c | 31 +- drivers/power/supply/da9150-fg.c | 4 +- drivers/s390/net/ism_drv.c | 14 +- drivers/soc/loongson/loongson2_guts.c | 5 +- drivers/tee/optee/supp.c | 35 +- drivers/usb/gadget/function/f_midi.c | 2 +- fs/btrfs/compression.c | 3 +- fs/btrfs/extent_io.c | 174 ++- fs/btrfs/inode.c | 3 +- fs/btrfs/subpage.c | 202 +--- fs/btrfs/subpage.h | 39 +- fs/smb/client/inode.c | 4 +- fs/smb/client/smb2ops.c | 4 + fs/xfs/scrub/common.h | 5 - fs/xfs/scrub/repair.h | 11 +- fs/xfs/scrub/scrub.c | 12 + include/linux/netdevice.h | 2 + include/linux/pci.h | 2 + include/linux/pse-pd/pse.h | 16 +- include/linux/serio.h | 3 + include/linux/skmsg.h | 2 + include/net/gro.h | 3 + include/net/strparser.h | 2 + include/net/tcp.h | 22 + include/uapi/drm/xe_drm.h | 17 + io_uring/io_uring.c | 2 + io_uring/rw.c | 13 +- kernel/acct.c | 134 ++- kernel/bpf/arena.c | 2 +- kernel/bpf/bpf_cgrp_storage.c | 2 +- kernel/bpf/btf.c | 2 + kernel/bpf/ringbuf.c | 4 - kernel/bpf/syscall.c | 43 +- kernel/sched/ext.c | 150 ++- kernel/trace/ftrace.c | 36 +- kernel/trace/trace.c | 277 ++--- kernel/trace/trace_functions.c | 6 +- lib/iov_iter.c | 3 +- mm/madvise.c | 11 +- mm/migrate_device.c | 13 +- net/bpf/test_run.c | 5 +- net/core/dev.c | 37 +- net/core/drop_monitor.c | 39 +- net/core/flow_dissector.c | 49 +- net/core/gro.c | 3 - net/core/skbuff.c | 10 +- net/core/skmsg.c | 7 + net/core/sock_map.c | 8 +- net/ipv4/arp.c | 2 +- net/ipv4/tcp.c | 29 +- net/ipv4/tcp_bpf.c | 36 + net/ipv4/tcp_fastopen.c | 4 +- net/ipv4/tcp_input.c | 20 +- net/ipv4/tcp_ipv4.c | 2 +- net/sched/cls_api.c | 2 +- net/strparser/strparser.c | 11 +- net/vmw_vsock/af_vsock.c | 3 + net/vmw_vsock/virtio_transport.c | 10 +- net/vmw_vsock/vsock_bpf.c | 2 +- sound/core/seq/seq_clientmgr.c | 12 +- sound/pci/hda/hda_codec.c | 4 +- sound/pci/hda/patch_conexant.c | 1 + sound/pci/hda/patch_cs8409-tables.c | 6 +- sound/pci/hda/patch_cs8409.c | 20 +- sound/pci/hda/patch_cs8409.h | 5 +- sound/pci/hda/patch_realtek.c | 1 + sound/soc/fsl/fsl_micfil.c | 2 + sound/soc/fsl/imx-audmix.c | 31 - sound/soc/rockchip/rockchip_i2s_tdm.c | 4 +- sound/soc/sh/rz-ssi.c | 10 +- sound/soc/sof/ipc4-topology.c | 12 +- sound/soc/sof/pcm.c | 2 + sound/soc/sof/stream-ipc.c | 6 +- .../selftests/bpf/bpf_testmod/bpf_testmod-events.h | 8 + .../selftests/bpf/bpf_testmod/bpf_testmod.c | 2 + .../testing/selftests/bpf/prog_tests/raw_tp_null.c | 25 + tools/testing/selftests/bpf/progs/raw_tp_null.c | 32 + tools/testing/selftests/mm/Makefile | 9 +- 181 files changed, 3590 insertions(+), 1560 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 20/154 drm/amd/display: Correct register address in dcn35
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: loanchen <[email protected]>
[ Upstream commit f88192d2335b5a911fcfa09338cc00624571ec5e ]
[Why]
the offset address of mmCLK5_spll_field_8 was incorrect for dcn35 which causes SSC not to be enabled.
--- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +1 -1
@@ -89,7 +89,7 @@#define mmCLK1_CLK4_ALLOW_DS 0x16EA8#define mmCLK1_CLK5_ALLOW_DS 0x16EB1 -#define mmCLK5_spll_field_8 0x1B04B +#define mmCLK5_spll_field_8 0x1B24B#define mmDENTIST_DISPCLK_CNTL 0x0124#define regDENTIST_DISPCLK_CNTL 0x0064#define regDENTIST_DISPCLK_CNTL_BASE_IDX 1
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 29/154 PCI: Remove devres from pci_intx()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Philipp Stanner <[email protected]>
[ Upstream commit dfa2f4d5f9e5d757700cefa8ee480099889f1c69 ]
pci_intx() is a hybrid function which can sometimes be managed through devres. This hybrid nature is undesirable.
Since all users of pci_intx() have by now been ported either to always-managed pcim_intx() or never-managed pci_intx_unmanaged(), the devres functionality can be removed from pci_intx().
Consequently, pci_intx_unmanaged() is now redundant, because pci_intx() itself is now unmanaged.
Remove the devres functionality from pci_intx(). Have all users of pci_intx_unmanaged() call pci_intx(). Remove pci_intx_unmanaged().
Stable-dep-of: d555ed45a5a1 ("PCI: Restore original INTX_DISABLE bit by pcim_intx()")
--- drivers/pci/devres.c | 4 ++-- drivers/pci/pci.c | 43 ++----------------------------------------- include/linux/pci.h | 1 - 3 files changed, 4 insertions(+), 44 deletions(-)
drivers/pci/devres.c +2 -2
@@ -416,7 +416,7 @@ static void pcim_intx_restore(struct device *dev, void *data)struct pci_dev *pdev =to_pci_dev (dev);struct pcim_intx_devres *res = data; -pci_intx_unmanaged (pdev, res->orig_intx); +pci_intx (pdev, res->orig_intx); }static struct pcim_intx_devres *get_or_create_intx_devres (struct device *dev)
@@ -453,7 +453,7 @@ int pcim_intx(struct pci_dev *pdev, int enable)return -ENOMEM ; res->orig_intx = !enable; -pci_intx_unmanaged (pdev, enable); +pci_intx (pdev, enable);return 0 ; }
drivers/pci/pci.c +2 -41
60 lines not on this page · raw message
include/linux/pci.h +0 -1
@@ -1353,7 +1353,6 @@ int __must_check pcim_set_mwi(struct pci_dev *dev);int pci_try_set_mwi (struct pci_dev *dev);void pci_clear_mwi (struct pci_dev *dev);void pci_disable_parity (struct pci_dev *dev); -void pci_intx_unmanaged (struct pci_dev *pdev,int enable);void pci_intx (struct pci_dev *dev,int enable);bool pci_check_and_mask_intx (struct pci_dev *dev);bool pci_check_and_unmask_intx (struct pci_dev *dev);
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 30/154 PCI: Restore original INTX_DISABLE bit by pcim_intx()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
[ Upstream commit d555ed45a5a10a813528c7685f432369d536ae3d ]
pcim_intx() tries to restore the INTx bit at removal via devres, but there is a chance that it restores a wrong value.
Because the value to be restored is blindly assumed to be the negative of the enable argument, when a driver calls pcim_intx() unnecessarily for the already enabled state, it'll restore to the disabled state in turn. That is, the function assumes the case like:
// INTx == 1
pcim_intx(pdev, 0); // old INTx value assumed to be 1 -> correct
but it might be like the following, too:
// INTx == 0
pcim_intx(pdev, 0); // old INTx value assumed to be 1 -> wrong
Also, when a driver calls pcim_intx() multiple times with different enable argument values, the last one will win no matter what value it is. This can lead to inconsistency, e.g.
// INTx == 1
pcim_intx(pdev, 0); // OK
...
pcim_intx(pdev, 1); // now old INTx wrongly assumed to be 0
This patch addresses those inconsistencies by saving the original INTx state at the first pcim_intx() call. For that, get_or_create_intx_devres() is folded into pcim_intx() caller side; it allows us to simply check the already allocated devres and record the original INTx along with the devres_alloc() call.
--- drivers/pci/devres.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-)
drivers/pci/devres.c +19 -15
@@ -419,19 +419,12 @@ static void pcim_intx_restore(struct device *dev, void *data)pci_intx (pdev, res->orig_intx); } -static struct pcim_intx_devres *get_or_create_intx_devres (struct device *dev) +static void save_orig_intx (struct pci_dev *pdev,struct pcim_intx_devres *res) { -struct pcim_intx_devres *res; - - res =devres_find (dev, pcim_intx_restore,NULL ,NULL ); -if (res) -return res; +u16 pci_command; - res =devres_alloc (pcim_intx_restore,sizeof (*res),GFP_KERNEL ); -if (res) -devres_add (dev, res); - -return res; +pci_read_config_word (pdev,PCI_COMMAND , &pci_command); + res->orig_intx = !(pci_command &PCI_COMMAND_INTX_DISABLE ); }/**
@@ -447,12 +440,23 @@ static struct pcim_intx_devres *get_or_create_intx_devres(struct device *dev)int pcim_intx (struct pci_dev *pdev,int enable) {struct pcim_intx_devres *res; +struct device *dev = &pdev->dev; - res =get_or_create_intx_devres (&pdev->dev); -if (!res) -return -ENOMEM ; +/* +* pcim_intx() must only restore the INTx value that existed before the +* driver was loaded, i.e., before it called pcim_intx() for the +* first time. +*/ + res =devres_find (dev, pcim_intx_restore,NULL ,NULL ); +if (!res) { + res =devres_alloc (pcim_intx_restore,sizeof (*res),GFP_KERNEL ); +if (!res) +return -ENOMEM ; + +save_orig_intx (pdev, res); +devres_add (dev, res); + } - res->orig_intx = !enable;pci_intx (pdev, enable);return 0 ;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 31/154 arm64: dts: mediatek: mt8183-pumpkin: add HDMI support
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fabien Parent <[email protected]>
[ Upstream commit 72f3e3d68cfda508ec4b6c8927c50814229cd04e ]
The MT8183 Pumpkin board has a micro-HDMI connector. HDMI support is provided by an IT66121 DPI <-> HDMI bridge.
Enable the DPI and add the node for the IT66121 bridge.
Stable-dep-of: 26f6e91fa29a ("arm64: dts: mediatek: mt8183: Disable DSI display output by default")
--- .../boot/dts/mediatek/mt8183-pumpkin.dts | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+)
arch/arm64/boot/dts/mediatek/mt8183-pumpkin.dts +123 -0
@@ -63,6 +63,18 @@ pulldown-ohm = <0>; io-channels = <&auxadc 0>; }; + + connector { + compatible = "hdmi-connector"; + label = "hdmi"; + type = "d"; + + port { + hdmi_connector_in: endpoint { + remote-endpoint = <&hdmi_connector_out>; + }; + }; + }; }; &auxadc {
@@ -120,6 +132,43 @@ pinctrl-0 = <&i2c6_pins>; status = "okay"; clock-frequency = <100000>; + #address-cells = <1>; + #size-cells = <0>; + + it66121hdmitx: hdmitx@4c { + compatible = "ite,it66121"; + reg = <0x4c>; + pinctrl-names = "default"; + pinctrl-0 = <&ite_pins>; + reset-gpios = <&pio 160 GPIO_ACTIVE_LOW>; + interrupt-parent = <&pio>; + interrupts = <4 IRQ_TYPE_LEVEL_LOW>; + vcn33-supply = <&mt6358_vcn33_reg>; + vcn18-supply = <&mt6358_vcn18_reg>; + vrf12-supply = <&mt6358_vrf12_reg>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + it66121_in: endpoint { + bus-width = <12>; + remote-endpoint = <&dpi_out>; + }; + }; + + port@1 { + reg = <1>; + + hdmi_connector_out: endpoint { + remote-endpoint = <&hdmi_connector_in>; + }; + }; + }; + }; }; &keyboard {
@@ -362,6 +411,67 @@ input-enable; }; }; + + ite_pins: ite-pins { + pins-irq { + pinmux = <PINMUX_GPIO4__FUNC_GPIO4>; + input-enable; + bias-pull-up; + }; + + pins-rst { + pinmux = <PINMUX_GPIO160__FUNC_GPIO160>; + output-high; + }; + }; + + dpi_func_pins: dpi-func-pins { + pins-dpi { + pinmux = <PINMUX_GPIO12__FUNC_I2S5_BCK>, + <PINMUX_GPIO46__FUNC_I2S5_LRCK>, + <PINMUX_GPIO47__FUNC_I2S5_DO>, + <PINMUX_GPIO13__FUNC_DBPI_D0>, + <PINMUX_GPIO14__FUNC_DBPI_D1>, + <PINMUX_GPIO15__FUNC_DBPI_D2>, + <PINMUX_GPIO16__FUNC_DBPI_D3>, + <PINMUX_GPIO17__FUNC_DBPI_D4>, + <PINMUX_GPIO18__FUNC_DBPI_D5>, + <PINMUX_GPIO19__FUNC_DBPI_D6>, + <PINMUX_GPIO20__FUNC_DBPI_D7>, + <PINMUX_GPIO21__FUNC_DBPI_D8>, + <PINMUX_GPIO22__FUNC_DBPI_D9>, + <PINMUX_GPIO23__FUNC_DBPI_D10>, + <PINMUX_GPIO24__FUNC_DBPI_D11>, + <PINMUX_GPIO25__FUNC_DBPI_HSYNC>, + <PINMUX_GPIO26__FUNC_DBPI_VSYNC>, + <PINMUX_GPIO27__FUNC_DBPI_DE>, + <PINMUX_GPIO28__FUNC_DBPI_CK>; + }; + }; + + dpi_idle_pins: dpi-idle-pins { + pins-idle { + pinmux = <PINMUX_GPIO12__FUNC_GPIO12>, + <PINMUX_GPIO46__FUNC_GPIO46>, + <PINMUX_GPIO47__FUNC_GPIO47>, + <PINMUX_GPIO13__FUNC_GPIO13>, + <PINMUX_GPIO14__FUNC_GPIO14>, + <PINMUX_GPIO15__FUNC_GPIO15>, + <PINMUX_GPIO16__FUNC_GPIO16>, + <PINMUX_GPIO17__FUNC_GPIO17>, + <PINMUX_GPIO18__FUNC_GPIO18>, + <PINMUX_GPIO19__FUNC_GPIO19>, + <PINMUX_GPIO20__FUNC_GPIO20>, + <PINMUX_GPIO21__FUNC_GPIO21>, + <PINMUX_GPIO22__FUNC_GPIO22>, + <PINMUX_GPIO23__FUNC_GPIO23>, + <PINMUX_GPIO24__FUNC_GPIO24>, + <PINMUX_GPIO25__FUNC_GPIO25>, + <PINMUX_GPIO26__FUNC_GPIO26>, + <PINMUX_GPIO27__FUNC_GPIO27>, + <PINMUX_GPIO28__FUNC_GPIO28>; + }; + }; }; &pmic {
@@ -415,3 +525,16 @@ &dsi0 { status = "disabled"; }; + +&dpi0 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&dpi_func_pins>; + pinctrl-1 = <&dpi_idle_pins>; + status = "okay"; + + port { + dpi_out: endpoint { + remote-endpoint = <&it66121_in>; + }; + }; +};
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 32/154 arm64: dts: mediatek: mt8183: Disable DSI display output by default
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen-Yu Tsai <[email protected]>
[ Upstream commit 26f6e91fa29a58fdc76b47f94f8f6027944a490c ]
Most SoC dtsi files have the display output interfaces disabled by default, and only enabled on boards that utilize them. The MT8183 has it backwards: the display outputs are left enabled by default, and only disabled at the board level.
Reverse the situation for the DSI output so that it follows the normal scheme. For ease of backporting the DPI output is handled in a separate patch.
--- arch/arm64/boot/dts/mediatek/mt8183-pumpkin.dts | 4 ---- arch/arm64/boot/dts/mediatek/mt8183.dtsi | 1 + 2 files changed, 1 insertion(+), 4 deletions(-)
arch/arm64/boot/dts/mediatek/mt8183-pumpkin.dts +0 -4
@@ -522,10 +522,6 @@ status = "okay"; }; -&dsi0 { - status = "disabled"; -}; - &dpi0 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&dpi_func_pins>;
arch/arm64/boot/dts/mediatek/mt8183.dtsi +1 -0
@@ -1835,6 +1835,7 @@ resets = <&mmsys MT8183_MMSYS_SW0_RST_B_DISP_DSI0>; phys = <&mipi_tx0>; phy-names = "dphy"; + status = "disabled"; }; dpi0: dpi@14015000 {
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 33/154 accel/ivpu: Limit FW version string length
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jacek Lawrynowicz <[email protected]>
[ Upstream commit 990b1e3d150104249115a0ad81ea77c53b28f0f8 ]
Limit FW version string, when parsing FW binary, to 256 bytes and always add NULL-terminate it.
Stable-dep-of: 41a2d8286c90 ("accel/ivpu: Fix error handling in recovery/reset")
--- drivers/accel/ivpu/ivpu_fw.c | 7 ++++--- drivers/accel/ivpu/ivpu_fw.h | 6 +++++- 2 files changed, 9 insertions(+), 4 deletions(-)
drivers/accel/ivpu/ivpu_fw.c +4 -3
@@ -25,7 +25,6 @@#define FW_SHAVE_NN_MAX_SIZE SZ_2M#define FW_RUNTIME_MIN_ADDR (FW_GLOBAL_MEM_START)#define FW_RUNTIME_MAX_ADDR (FW_GLOBAL_MEM_END - FW_SHARED_MEM_SIZE) -#define FW_VERSION_HEADER_SIZE SZ_4K#define FW_FILE_IMAGE_OFFSET (VPU_FW_HEADER_SIZE + FW_VERSION_HEADER_SIZE)#define WATCHDOG_MSS_REDIRECT 32
@@ -191,8 +190,10 @@ static int ivpu_fw_parse(struct ivpu_device *vdev)ivpu_dbg (vdev,FW_BOOT ,"Header version: 0x%x, format 0x%x\n" , fw_hdr->header_version, fw_hdr->image_format); -ivpu_info (vdev,"Firmware: %s, version: %s" , fw->name, - (const char *)fw_hdr +VPU_FW_HEADER_SIZE ); +if (!scnprintf (fw->version,sizeof (fw->version),"%s" , fw->file->data +VPU_FW_HEADER_SIZE )) +ivpu_warn (vdev,"Missing firmware version\n" ); + +ivpu_info (vdev,"Firmware: %s, version: %s\n" , fw->name, fw->version);if (IVPU_FW_CHECK_API_COMPAT (vdev, fw_hdr,BOOT ,3 ))return -EINVAL ;
drivers/accel/ivpu/ivpu_fw.h +5 -1
@@ -1,11 +1,14 @@/* SPDX-License-Identifier: GPL-2.0-only */ /* -* Copyright (C) 2020-2023 Intel Corporation +* Copyright (C) 2020-2024 Intel Corporation */ #ifndef __IVPU_FW_H__#define __IVPU_FW_H__ +#define FW_VERSION_HEADER_SIZE SZ_4K +#define FW_VERSION_STR_SIZE SZ_256 +struct ivpu_device ;struct ivpu_bo ;struct vpu_boot_params ;
@@ -13,6 +16,7 @@ struct vpu_boot_params;struct ivpu_fw_info {const struct firmware *file;const char *name; +char version[FW_VERSION_STR_SIZE ];struct ivpu_bo *mem;struct ivpu_bo *mem_shave_nn;struct ivpu_bo *mem_log_crit;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 34/154 accel/ivpu: Add coredump support
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Karol Wachowski <[email protected]>
[ Upstream commit bade0340526827d03d9c293450c0422beba77f04 ]
Use coredump (if available) to collect FW logs in case of a FW crash. This makes dmesg more readable and allows to collect more log data.
Stable-dep-of: 41a2d8286c90 ("accel/ivpu: Fix error handling in recovery/reset")
--- drivers/accel/ivpu/Kconfig | 1 + drivers/accel/ivpu/Makefile | 1 + drivers/accel/ivpu/ivpu_coredump.c | 39 ++++++++++++++++++++++++++++++ drivers/accel/ivpu/ivpu_coredump.h | 25 +++++++++++++++++++ drivers/accel/ivpu/ivpu_drv.c | 5 ++-- drivers/accel/ivpu/ivpu_fw_log.h | 8 ------ drivers/accel/ivpu/ivpu_pm.c | 9 ++++--- 7 files changed, 74 insertions(+), 14 deletions(-) create mode 100644 drivers/accel/ivpu/ivpu_coredump.c create mode 100644 drivers/accel/ivpu/ivpu_coredump.h
drivers/accel/ivpu/Kconfig +1 -0
@@ -8,6 +8,7 @@ config DRM_ACCEL_IVPU select FW_LOADER select DRM_GEM_SHMEM_HELPER select GENERIC_ALLOCATOR + select WANT_DEV_COREDUMP help Choose this option if you have a system with an 14th generation Intel CPU (Meteor Lake) or newer. Intel NPU (formerly called Intel VPU)
drivers/accel/ivpu/Makefile +1 -0
@@ -19,5 +19,6 @@ intel_vpu-y := \ ivpu_sysfs.o intel_vpu-$(CONFIG_DEBUG_FS) += ivpu_debugfs.o +intel_vpu-$(CONFIG_DEV_COREDUMP) += ivpu_coredump.o obj-$(CONFIG_DRM_ACCEL_IVPU) += intel_vpu.o
drivers/accel/ivpu/ivpu_coredump.c new file +39 -0
@@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +* Copyright (C) 2020-2024 Intel Corporation +*/ + +#include <linux/devcoredump.h> +#include <linux/firmware.h> + +#include "ivpu_coredump.h" +#include "ivpu_fw.h" +#include "ivpu_gem.h" +#include "vpu_boot_api.h" + +#define CRASH_DUMP_HEADER "Intel NPU crash dump" +#define CRASH_DUMP_HEADERS_SIZE SZ_4K + +void ivpu_dev_coredump (struct ivpu_device *vdev) +{ +struct drm_print_iterator pi = {}; +struct drm_printer p; +size_t coredump_size; +char *coredump; + + coredump_size =CRASH_DUMP_HEADERS_SIZE +FW_VERSION_HEADER_SIZE + +ivpu_bo_size (vdev->fw->mem_log_crit) +ivpu_bo_size (vdev->fw->mem_log_verb); + coredump =vmalloc (coredump_size); +if (!coredump) +return ; + + pi.data = coredump; + pi.remain = coredump_size; + p =drm_coredump_printer (&pi); + +drm_printf (&p,"%s\n" ,CRASH_DUMP_HEADER ); +drm_printf (&p,"FW version: %s\n" , vdev->fw->version); +ivpu_fw_log_print (vdev, false, &p); + +dev_coredumpv (vdev->drm.dev, coredump, pi.offset,GFP_KERNEL ); +}
drivers/accel/ivpu/ivpu_coredump.h new file +25 -0
@@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +* Copyright (C) 2020-2024 Intel Corporation +*/ + +#ifndef __IVPU_COREDUMP_H__ +#define __IVPU_COREDUMP_H__ + +#include <drm/drm_print.h> + +#include "ivpu_drv.h" +#include "ivpu_fw_log.h" + +#ifdef CONFIG_DEV_COREDUMP +void ivpu_dev_coredump (struct ivpu_device *vdev); +#else +static inline void ivpu_dev_coredump (struct ivpu_device *vdev) +{ +struct drm_printer p =drm_info_printer (vdev->drm.dev); + +ivpu_fw_log_print (vdev, false, &p); +} +#endif + +#endif /* __IVPU_COREDUMP_H__ */
drivers/accel/ivpu/ivpu_drv.c +3 -2
@@ -14,7 +14,7 @@#include <drm/drm_ioctl.h> #include <drm/drm_prime.h> -#include "vpu_boot_api.h" +#include "ivpu_coredump.h" #include "ivpu_debugfs.h" #include "ivpu_drv.h" #include "ivpu_fw.h"
@@ -29,6 +29,7 @@#include "ivpu_ms.h" #include "ivpu_pm.h" #include "ivpu_sysfs.h" +#include "vpu_boot_api.h" #ifndef DRIVER_VERSION_STR #define DRIVER_VERSION_STR __stringify(DRM_IVPU_DRIVER_MAJOR) "." \
@@ -382,7 +383,7 @@ int ivpu_boot(struct ivpu_device *vdev)ivpu_err (vdev,"Failed to boot the firmware: %d\n" , ret);ivpu_hw_diagnose_failure (vdev);ivpu_mmu_evtq_dump (vdev); -ivpu_fw_log_dump (vdev); +ivpu_dev_coredump (vdev);return ret; }
drivers/accel/ivpu/ivpu_fw_log.h +0 -8
@@ -8,8 +8,6 @@#include <linux/types.h> -#include <drm/drm_print.h> -#include "ivpu_drv.h" #define IVPU_FW_LOG_DEFAULT 0
@@ -28,11 +26,5 @@ extern unsigned int ivpu_log_level;void ivpu_fw_log_print (struct ivpu_device *vdev,bool only_new_msgs,struct drm_printer *p);void ivpu_fw_log_clear (struct ivpu_device *vdev); -static inline void ivpu_fw_log_dump (struct ivpu_device *vdev) -{ -struct drm_printer p =drm_info_printer (vdev->drm.dev); - -ivpu_fw_log_print (vdev, false, &p); -}#endif /* __IVPU_FW_LOG_H__ */
drivers/accel/ivpu/ivpu_pm.c +5 -4
@@ -9,17 +9,18 @@#include <linux/pm_runtime.h> #include <linux/reboot.h> -#include "vpu_boot_api.h" +#include "ivpu_coredump.h" #include "ivpu_drv.h" -#include "ivpu_hw.h" #include "ivpu_fw.h" #include "ivpu_fw_log.h" +#include "ivpu_hw.h" #include "ivpu_ipc.h" #include "ivpu_job.h" #include "ivpu_jsm_msg.h" #include "ivpu_mmu.h" #include "ivpu_ms.h" #include "ivpu_pm.h" +#include "vpu_boot_api.h" static bool ivpu_disable_recovery;module_param_named_unsafe (disable_recovery, ivpu_disable_recovery, bool,0644 );
@@ -123,7 +124,7 @@ static void ivpu_pm_recovery_work(struct work_struct *work)if (ret)ivpu_err (vdev,"Failed to resume NPU: %d\n" , ret); -ivpu_fw_log_dump (vdev); +ivpu_dev_coredump (vdev);atomic_inc (&vdev->pm->reset_counter);atomic_set (&vdev->pm->reset_pending,1 );
@@ -262,7 +263,7 @@ int ivpu_pm_runtime_suspend_cb(struct device *dev)if (!is_idle || ret_d0i3) {ivpu_err (vdev,"Forcing cold boot due to previous errors\n" );atomic_inc (&vdev->pm->reset_counter); -ivpu_fw_log_dump (vdev); +ivpu_dev_coredump (vdev);ivpu_pm_prepare_cold_boot (vdev); }else {ivpu_pm_prepare_warm_boot (vdev);
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 35/154 accel/ivpu: Add FW state dump on TDR
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tomasz Rusinowicz <[email protected]>
[ Upstream commit 5e162f872d7af8f041b143536617ab2563ea7de5 ]
Send JSM state dump message at the beginning of TDR handler. This allows FW to collect debug info in the FW log before the state of the NPU is lost allowing to analyze the cause of a TDR.
Wait a predefined timeout (10 ms) so the FW has a chance to write debug logs. We cannot wait for JSM response at this point because IRQs are already disabled before TDR handler is invoked.
Stable-dep-of: 41a2d8286c90 ("accel/ivpu: Fix error handling in recovery/reset")
--- drivers/accel/ivpu/ivpu_drv.h | 1 + drivers/accel/ivpu/ivpu_hw.c | 3 +++ drivers/accel/ivpu/ivpu_ipc.c | 26 ++++++++++++++++++++++++++ drivers/accel/ivpu/ivpu_ipc.h | 2 ++ drivers/accel/ivpu/ivpu_jsm_msg.c | 8 ++++++++ drivers/accel/ivpu/ivpu_jsm_msg.h | 2 ++ drivers/accel/ivpu/ivpu_pm.c | 1 + 7 files changed, 43 insertions(+)
drivers/accel/ivpu/ivpu_drv.h +1 -0
@@ -152,6 +152,7 @@ struct ivpu_device {int tdr;int autosuspend;int d0i3_entry_msg; +int state_dump_msg; } timeout; };
drivers/accel/ivpu/ivpu_hw.c +3 -0
@@ -89,12 +89,14 @@ static void timeouts_init(struct ivpu_device *vdev) vdev->timeout.tdr =2000000 ; vdev->timeout.autosuspend =-1 ; vdev->timeout.d0i3_entry_msg =500 ; + vdev->timeout.state_dump_msg =10 ; }else if (ivpu_is_simics (vdev)) { vdev->timeout.boot =50 ; vdev->timeout.jsm =500 ; vdev->timeout.tdr =10000 ; vdev->timeout.autosuspend =-1 ; vdev->timeout.d0i3_entry_msg =100 ; + vdev->timeout.state_dump_msg =10 ; }else { vdev->timeout.boot =1000 ; vdev->timeout.jsm =500 ;
@@ -104,6 +106,7 @@ static void timeouts_init(struct ivpu_device *vdev)else vdev->timeout.autosuspend =100 ; vdev->timeout.d0i3_entry_msg =5 ; + vdev->timeout.state_dump_msg =10 ; } }
drivers/accel/ivpu/ivpu_ipc.c +26 -0
@@ -353,6 +353,32 @@ int ivpu_ipc_send_receive(struct ivpu_device *vdev, struct vpu_jsm_msg *req,return ret; } +int ivpu_ipc_send_and_wait (struct ivpu_device *vdev,struct vpu_jsm_msg *req, +u32 channel,unsigned long timeout_ms) +{ +struct ivpu_ipc_consumer cons; +int ret; + + ret =ivpu_rpm_get (vdev); +if (ret <0 ) +return ret; + +ivpu_ipc_consumer_add (vdev, &cons, channel,NULL ); + + ret =ivpu_ipc_send (vdev, &cons, req); +if (ret) { +ivpu_warn_ratelimited (vdev,"IPC send failed: %d\n" , ret); + goto consumer_del; + } + +msleep (timeout_ms); + +consumer_del: +ivpu_ipc_consumer_del (vdev, &cons); +ivpu_rpm_put (vdev); +return ret; +} +static bool ivpu_ipc_match_consumer (struct ivpu_device *vdev,struct ivpu_ipc_consumer *cons,struct ivpu_ipc_hdr *ipc_hdr,struct vpu_jsm_msg *jsm_msg)
drivers/accel/ivpu/ivpu_ipc.h +2 -0
@@ -107,5 +107,7 @@ int ivpu_ipc_send_receive_internal(struct ivpu_device *vdev, struct vpu_jsm_msgint ivpu_ipc_send_receive (struct ivpu_device *vdev,struct vpu_jsm_msg *req,enum vpu_ipc_msg_type expected_resp,struct vpu_jsm_msg *resp,u32 channel,unsigned long timeout_ms); +int ivpu_ipc_send_and_wait (struct ivpu_device *vdev,struct vpu_jsm_msg *req, +u32 channel,unsigned long timeout_ms);#endif /* __IVPU_IPC_H__ */
drivers/accel/ivpu/ivpu_jsm_msg.c +8 -0
@@ -555,3 +555,11 @@ int ivpu_jsm_dct_disable(struct ivpu_device *vdev)return ivpu_ipc_send_receive_internal (vdev, &req,VPU_JSM_MSG_DCT_DISABLE_DONE , &resp,VPU_IPC_CHAN_ASYNC_CMD , vdev->timeout.jsm); } + +int ivpu_jsm_state_dump (struct ivpu_device *vdev) +{ +struct vpu_jsm_msg req = { .type =VPU_JSM_MSG_STATE_DUMP }; + +return ivpu_ipc_send_and_wait (vdev, &req,VPU_IPC_CHAN_ASYNC_CMD , + vdev->timeout.state_dump_msg); +}
drivers/accel/ivpu/ivpu_jsm_msg.h +2 -0
@@ -43,4 +43,6 @@ int ivpu_jsm_metric_streamer_info(struct ivpu_device *vdev, u64 metric_group_mas u64 buffer_size, u32 *sample_size, u64 *info_size);int ivpu_jsm_dct_enable (struct ivpu_device *vdev,u32 active_us,u32 inactive_us);int ivpu_jsm_dct_disable (struct ivpu_device *vdev); +int ivpu_jsm_state_dump (struct ivpu_device *vdev); +#endif
drivers/accel/ivpu/ivpu_pm.c +1 -0
@@ -124,6 +124,7 @@ static void ivpu_pm_recovery_work(struct work_struct *work)if (ret)ivpu_err (vdev,"Failed to resume NPU: %d\n" , ret); +ivpu_jsm_state_dump (vdev);ivpu_dev_coredump (vdev);atomic_inc (&vdev->pm->reset_counter);
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 36/154 accel/ivpu: Fix error handling in recovery/reset
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jacek Lawrynowicz <[email protected]>
[ Upstream commit 41a2d8286c905614f29007f1bc8e652d54654b82 ]
Disable runtime PM for the duration of reset/recovery so it is possible to set the correct runtime PM state depending on the outcome of the ivpu_resume(). Don’t suspend or reset the HW if the NPU is suspended when the reset/recovery is requested. Also, move common reset/recovery code to separate functions for better code readability.
--- drivers/accel/ivpu/ivpu_pm.c | 79 ++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 36 deletions(-)
drivers/accel/ivpu/ivpu_pm.c +43 -36
@@ -111,41 +111,57 @@ static int ivpu_resume(struct ivpu_device *vdev)return ret; } -static void ivpu_pm_recovery_work (struct work_struct *work) +static void ivpu_pm_reset_begin (struct ivpu_device *vdev) { - struct ivpu_pm_info *pm = container_of(work, struct ivpu_pm_info, recovery_work); -struct ivpu_device *vdev = pm->vdev; -char *evt[2 ] = {"IVPU_PM_EVENT=IVPU_RECOVER" ,NULL }; -int ret; - -ivpu_err (vdev,"Recovering the NPU (reset #%d)\n" ,atomic_read (&vdev->pm->reset_counter)); - - ret =pm_runtime_resume_and_get (vdev->drm.dev); -if (ret) -ivpu_err (vdev,"Failed to resume NPU: %d\n" , ret); - -ivpu_jsm_state_dump (vdev); -ivpu_dev_coredump (vdev); +pm_runtime_disable (vdev->drm.dev);atomic_inc (&vdev->pm->reset_counter);atomic_set (&vdev->pm->reset_pending,1 );down_write (&vdev->pm->reset_lock); +} + +static void ivpu_pm_reset_complete (struct ivpu_device *vdev) +{ +int ret; -ivpu_suspend (vdev);ivpu_pm_prepare_cold_boot (vdev);ivpu_jobs_abort_all (vdev);ivpu_ms_cleanup_all (vdev); ret =ivpu_resume (vdev); -if (ret) +if (ret) {ivpu_err (vdev,"Failed to resume NPU: %d\n" , ret); +pm_runtime_set_suspended (vdev->drm.dev); + }else { +pm_runtime_set_active (vdev->drm.dev); + }up_write (&vdev->pm->reset_lock);atomic_set (&vdev->pm->reset_pending,0 ); -kobject_uevent_env (&vdev->drm.dev->kobj,KOBJ_CHANGE , evt);pm_runtime_mark_last_busy (vdev->drm.dev); -pm_runtime_put_autosuspend (vdev->drm.dev); +pm_runtime_enable (vdev->drm.dev); +} + +static void ivpu_pm_recovery_work (struct work_struct *work) +{ + struct ivpu_pm_info *pm = container_of(work, struct ivpu_pm_info, recovery_work); +struct ivpu_device *vdev = pm->vdev; +char *evt[2 ] = {"IVPU_PM_EVENT=IVPU_RECOVER" ,NULL }; + +ivpu_err (vdev,"Recovering the NPU (reset #%d)\n" ,atomic_read (&vdev->pm->reset_counter)); + +ivpu_pm_reset_begin (vdev); + +if (!pm_runtime_status_suspended (vdev->drm.dev)) { +ivpu_jsm_state_dump (vdev); +ivpu_dev_coredump (vdev); +ivpu_suspend (vdev); + } + +ivpu_pm_reset_complete (vdev); + +kobject_uevent_env (&vdev->drm.dev->kobj,KOBJ_CHANGE , evt); }void ivpu_pm_trigger_recovery (struct ivpu_device *vdev,const char *reason)
@@ -316,16 +332,13 @@ void ivpu_pm_reset_prepare_cb(struct pci_dev *pdev)struct ivpu_device *vdev =pci_get_drvdata (pdev);ivpu_dbg (vdev,PM ,"Pre-reset..\n" ); -atomic_inc (&vdev->pm->reset_counter); -atomic_set (&vdev->pm->reset_pending,1 ); -pm_runtime_get_sync (vdev->drm.dev); -down_write (&vdev->pm->reset_lock); -ivpu_prepare_for_reset (vdev); -ivpu_hw_reset (vdev); -ivpu_pm_prepare_cold_boot (vdev); -ivpu_jobs_abort_all (vdev); -ivpu_ms_cleanup_all (vdev); +ivpu_pm_reset_begin (vdev); + +if (!pm_runtime_status_suspended (vdev->drm.dev)) { +ivpu_prepare_for_reset (vdev); +ivpu_hw_reset (vdev); + }ivpu_dbg (vdev,PM ,"Pre-reset done.\n" ); }
@@ -333,18 +346,12 @@ void ivpu_pm_reset_prepare_cb(struct pci_dev *pdev)void ivpu_pm_reset_done_cb (struct pci_dev *pdev) {struct ivpu_device *vdev =pci_get_drvdata (pdev); -int ret;ivpu_dbg (vdev,PM ,"Post-reset..\n" ); - ret =ivpu_resume (vdev); -if (ret) -ivpu_err (vdev,"Failed to set RESUME state: %d\n" , ret); -up_write (&vdev->pm->reset_lock); -atomic_set (&vdev->pm->reset_pending,0 ); -ivpu_dbg (vdev,PM ,"Post-reset done.\n" ); -pm_runtime_mark_last_busy (vdev->drm.dev); -pm_runtime_put_autosuspend (vdev->drm.dev); +ivpu_pm_reset_complete (vdev); + +ivpu_dbg (vdev,PM ,"Post-reset done.\n" ); }void ivpu_pm_init (struct ivpu_device *vdev)
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 37/154 drm/amdkfd: Move gfx12 trap handler to separate file
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jay Cornwall <[email protected]>
[ Upstream commit 62498e797aeb2bfa92a823ee1a8253f96d1cbe3f ]
gfx12 derivatives will have substantially different trap handler implementations from gfx10/gfx11. Add a separate source file for gfx12+ and remove unneeded conditional code.
No functional change.
v2: Revert copyright date to 2018, minor comment fixes
Stable-dep-of: d584198a6fe4 ("drm/amdkfd: Ensure consistent barrier state saved in gfx12 trap handler")
--- .../amd/amdkfd/cwsr_trap_handler_gfx10.asm | 202 +-- .../amd/amdkfd/cwsr_trap_handler_gfx12.asm | 1126 +++++++++++++++++ 2 files changed, 1127 insertions(+), 201 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx12.asm
drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm +1 -201
@@ -34,41 +34,24 @@ * cpp -DASIC_FAMILY=CHIP_PLUM_BONITO cwsr_trap_handler_gfx10.asm -P -o gfx11.sp3 * sp3 gfx11.sp3 -hex gfx11.hex * - * gfx12: - * cpp -DASIC_FAMILY=CHIP_GFX12 cwsr_trap_handler_gfx10.asm -P -o gfx12.sp3 - * sp3 gfx12.sp3 -hex gfx12.hex */ #define CHIP_NAVI10 26 #define CHIP_SIENNA_CICHLID 30 #define CHIP_PLUM_BONITO 36 -#define CHIP_GFX12 37 #define NO_SQC_STORE (ASIC_FAMILY >= CHIP_SIENNA_CICHLID) #define HAVE_XNACK (ASIC_FAMILY < CHIP_SIENNA_CICHLID) #define HAVE_SENDMSG_RTN (ASIC_FAMILY >= CHIP_PLUM_BONITO) #define HAVE_BUFFER_LDS_LOAD (ASIC_FAMILY < CHIP_PLUM_BONITO) -#define SW_SA_TRAP (ASIC_FAMILY >= CHIP_PLUM_BONITO && ASIC_FAMILY < CHIP_GFX12) +#define SW_SA_TRAP (ASIC_FAMILY == CHIP_PLUM_BONITO) #define SAVE_AFTER_XNACK_ERROR (HAVE_XNACK && !NO_SQC_STORE) // workaround for TCP store failure after XNACK error when ALLOW_REPLAY=0, for debugger #define SINGLE_STEP_MISSED_WORKAROUND 1 //workaround for lost MODE.DEBUG_EN exception when SAVECTX raised -#if ASIC_FAMILY < CHIP_GFX12 #define S_COHERENCE glc:1 #define V_COHERENCE slc:1 glc:1 #define S_WAITCNT_0 s_waitcnt 0 -#else -#define S_COHERENCE scope:SCOPE_SYS -#define V_COHERENCE scope:SCOPE_SYS -#define S_WAITCNT_0 s_wait_idle - -#define HW_REG_SHADER_FLAT_SCRATCH_LO HW_REG_WAVE_SCRATCH_BASE_LO -#define HW_REG_SHADER_FLAT_SCRATCH_HI HW_REG_WAVE_SCRATCH_BASE_HI -#define HW_REG_GPR_ALLOC HW_REG_WAVE_GPR_ALLOC -#define HW_REG_LDS_ALLOC HW_REG_WAVE_LDS_ALLOC -#define HW_REG_MODE HW_REG_WAVE_MODE -#endif -#if ASIC_FAMILY < CHIP_GFX12 var SQ_WAVE_STATUS_SPI_PRIO_MASK = 0x00000006 var SQ_WAVE_STATUS_HALT_MASK = 0x2000 var SQ_WAVE_STATUS_ECC_ERR_MASK = 0x20000
@@ -81,21 +64,6 @@ var S_STATUS_ALWAYS_CLEAR_MASK = SQ_WAVE_STATUS_SPI_PRIO_MASK|SQ_WAVE_STATUS_E var S_STATUS_HALT_MASK = SQ_WAVE_STATUS_HALT_MASK var S_SAVE_PC_HI_TRAP_ID_MASK = 0x00FF0000 var S_SAVE_PC_HI_HT_MASK = 0x01000000 -#else -var SQ_WAVE_STATE_PRIV_BARRIER_COMPLETE_MASK = 0x4 -var SQ_WAVE_STATE_PRIV_SCC_SHIFT = 9 -var SQ_WAVE_STATE_PRIV_SYS_PRIO_MASK = 0xC00 -var SQ_WAVE_STATE_PRIV_HALT_MASK = 0x4000 -var SQ_WAVE_STATE_PRIV_POISON_ERR_MASK = 0x8000 -var SQ_WAVE_STATE_PRIV_POISON_ERR_SHIFT = 15 -var SQ_WAVE_STATUS_WAVE64_SHIFT = 29 -var SQ_WAVE_STATUS_WAVE64_SIZE = 1 -var SQ_WAVE_LDS_ALLOC_GRANULARITY = 9 -var S_STATUS_HWREG = HW_REG_WAVE_STATE_PRIV -var S_STATUS_ALWAYS_CLEAR_MASK = SQ_WAVE_STATE_PRIV_SYS_PRIO_MASK|SQ_WAVE_STATE_PRIV_POISON_ERR_MASK -var S_STATUS_HALT_MASK = SQ_WAVE_STATE_PRIV_HALT_MASK -var S_SAVE_PC_HI_TRAP_ID_MASK = 0xF0000000 -#endif var SQ_WAVE_STATUS_NO_VGPRS_SHIFT = 24 var SQ_WAVE_LDS_ALLOC_LDS_SIZE_SHIFT = 12
@@ -110,7 +78,6 @@ var SQ_WAVE_GPR_ALLOC_VGPR_SIZE_SHIFT = 8 var SQ_WAVE_GPR_ALLOC_VGPR_SIZE_SHIFT = 12 #endif -#if ASIC_FAMILY < CHIP_GFX12 var SQ_WAVE_TRAPSTS_SAVECTX_MASK = 0x400 var SQ_WAVE_TRAPSTS_EXCP_MASK = 0x1FF var SQ_WAVE_TRAPSTS_SAVECTX_SHIFT = 10
@@ -161,39 +128,6 @@ var S_TRAPSTS_RESTORE_PART_3_SIZE = 32 - S_TRAPSTS_RESTORE_PART_3_SHIFT var S_TRAPSTS_HWREG = HW_REG_TRAPSTS var S_TRAPSTS_SAVE_CONTEXT_MASK = SQ_WAVE_TRAPSTS_SAVECTX_MASK var S_TRAPSTS_SAVE_CONTEXT_SHIFT = SQ_WAVE_TRAPSTS_SAVECTX_SHIFT -#else -var SQ_WAVE_EXCP_FLAG_PRIV_ADDR_WATCH_MASK = 0xF -var SQ_WAVE_EXCP_FLAG_PRIV_MEM_VIOL_MASK = 0x10 -var SQ_WAVE_EXCP_FLAG_PRIV_SAVE_CONTEXT_SHIFT = 5 -var SQ_WAVE_EXCP_FLAG_PRIV_SAVE_CONTEXT_MASK = 0x20 -var SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_MASK = 0x40 -var SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_SHIFT = 6 -var SQ_WAVE_EXCP_FLAG_PRIV_HOST_TRAP_MASK = 0x80 -var SQ_WAVE_EXCP_FLAG_PRIV_HOST_TRAP_SHIFT = 7 -var SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_MASK = 0x100 -var SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_SHIFT = 8 -var SQ_WAVE_EXCP_FLAG_PRIV_WAVE_END_MASK = 0x200 -var SQ_WAVE_EXCP_FLAG_PRIV_TRAP_AFTER_INST_MASK = 0x800 -var SQ_WAVE_TRAP_CTRL_ADDR_WATCH_MASK = 0x80 -var SQ_WAVE_TRAP_CTRL_TRAP_AFTER_INST_MASK = 0x200 - -var S_TRAPSTS_HWREG = HW_REG_WAVE_EXCP_FLAG_PRIV -var S_TRAPSTS_SAVE_CONTEXT_MASK = SQ_WAVE_EXCP_FLAG_PRIV_SAVE_CONTEXT_MASK -var S_TRAPSTS_SAVE_CONTEXT_SHIFT = SQ_WAVE_EXCP_FLAG_PRIV_SAVE_CONTEXT_SHIFT -var S_TRAPSTS_NON_MASKABLE_EXCP_MASK = SQ_WAVE_EXCP_FLAG_PRIV_MEM_VIOL_MASK |\ - SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_MASK |\ - SQ_WAVE_EXCP_FLAG_PRIV_HOST_TRAP_MASK |\ - SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_MASK |\ - SQ_WAVE_EXCP_FLAG_PRIV_WAVE_END_MASK |\ - SQ_WAVE_EXCP_FLAG_PRIV_TRAP_AFTER_INST_MASK -var S_TRAPSTS_RESTORE_PART_1_SIZE = SQ_WAVE_EXCP_FLAG_PRIV_SAVE_CONTEXT_SHIFT -var S_TRAPSTS_RESTORE_PART_2_SHIFT = SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_SHIFT -var S_TRAPSTS_RESTORE_PART_2_SIZE = SQ_WAVE_EXCP_FLAG_PRIV_HOST_TRAP_SHIFT - SQ_WAVE_EXCP_FLAG_PRIV_ILLEGAL_INST_SHIFT -var S_TRAPSTS_RESTORE_PART_3_SHIFT = SQ_WAVE_EXCP_FLAG_PRIV_WAVE_START_SHIFT -var S_TRAPSTS_RESTORE_PART_3_SIZE = 32 - S_TRAPSTS_RESTORE_PART_3_SHIFT -var BARRIER_STATE_SIGNAL_OFFSET = 16 -var BARRIER_STATE_VALID_OFFSET = 0 -#endif // bits [31:24] unused by SPI debug data var TTMP11_SAVE_REPLAY_W64H_SHIFT = 31
@@ -305,11 +239,7 @@ L_TRAP_NO_BARRIER: L_HALTED: // Host trap may occur while wave is halted. -#if ASIC_FAMILY < CHIP_GFX12 s_and_b32 ttmp2, s_save_pc_hi, S_SAVE_PC_HI_TRAP_ID_MASK -#else - s_and_b32 ttmp2, s_save_trapsts, SQ_WAVE_EXCP_FLAG_PRIV_HOST_TRAP_MASK -#endif s_cbranch_scc1 L_FETCH_2ND_TRAP L_CHECK_SAVE:
@@ -336,7 +266,6 @@ L_NOT_HALTED: // Check for maskable exceptions in trapsts.excp and trapsts.excp_hi. // Maskable exceptions only cause the wave to enter the trap handler if // their respective bit in mode.excp_en is set. -#if ASIC_FAMILY < CHIP_GFX12 s_and_b32 ttmp2, s_save_trapsts, SQ_WAVE_TRAPSTS_EXCP_MASK|SQ_WAVE_TRAPSTS_EXCP_HI_MASK s_cbranch_scc0 L_CHECK_TRAP_ID
@@ -349,17 +278,6 @@ L_NOT_ADDR_WATCH: s_lshl_b32 ttmp2, ttmp2, SQ_WAVE_MODE_EXCP_EN_SHIFT s_and_b32 ttmp2, ttmp2, ttmp3 s_cbranch_scc1 L_FETCH_2ND_TRAP -#else - s_getreg_b32 ttmp2, hwreg(HW_REG_WAVE_EXCP_FLAG_USER) - s_and_b32 ttmp3, s_save_trapsts, SQ_WAVE_EXCP_FLAG_PRIV_ADDR_WATCH_MASK - s_cbranch_scc0 L_NOT_ADDR_WATCH - s_or_b32 ttmp2, ttmp2, SQ_WAVE_TRAP_CTRL_ADDR_WATCH_MASK - -L_NOT_ADDR_WATCH: - s_getreg_b32 ttmp3, hwreg(HW_REG_WAVE_TRAP_CTRL) - s_and_b32 ttmp2, ttmp3, ttmp2 - s_cbranch_scc1 L_FETCH_2ND_TRAP -#endif L_CHECK_TRAP_ID: // Check trap_id != 0
@@ -369,13 +287,8 @@ L_CHECK_TRAP_ID: #if SINGLE_STEP_MISSED_WORKAROUND // Prioritize single step exception over context save. // Second-level trap will halt wave and RFE, re-entering for SAVECTX. -#if ASIC_FAMILY < CHIP_GFX12 s_getreg_b32 ttmp2, hwreg(HW_REG_MODE) s_and_b32 ttmp2, ttmp2, SQ_WAVE_MODE_DEBUG_EN_MASK -#else - // WAVE_TRAP_CTRL is already in ttmp3. - s_and_b32 ttmp3, ttmp3, SQ_WAVE_TRAP_CTRL_TRAP_AFTER_INST_MASK -#endif s_cbranch_scc1 L_FETCH_2ND_TRAP #endif
@@ -425,12 +338,7 @@ L_NO_NEXT_TRAP: s_cbranch_scc1 L_TRAP_CASE // Host trap will not cause trap re-entry. -#if ASIC_FAMILY < CHIP_GFX12 s_and_b32 ttmp2, s_save_pc_hi, S_SAVE_PC_HI_HT_MASK -#else - s_getreg_b32 ttmp2, hwreg(HW_REG_WAVE_EXCP_FLAG_PRIV) - s_and_b32 ttmp2, ttmp2, SQ_WAVE_EXCP_FLAG_PRIV_HOST_TRAP_MASK -#endif s_cbranch_scc1 L_EXIT_TRAP s_or_b32 s_save_status, s_save_status, S_STATUS_HALT_MASK
@@ -457,16 +365,7 @@ L_EXIT_TRAP: s_and_b64 exec, exec, exec // Restore STATUS.EXECZ, not writable by s_setreg_b32 s_and_b64 vcc, vcc, vcc // Restore STATUS.VCCZ, not writable by s_setreg_b32 -#if ASIC_FAMILY < CHIP_GFX12 s_setreg_b32 hwreg(S_STATUS_HWREG), s_save_status -#else - // STATE_PRIV.BARRIER_COMPLETE may have changed since we read it. - // Only restore fields which the trap handler changes. - s_lshr_b32 s_save_status, s_save_status, SQ_WAVE_STATE_PRIV_SCC_SHIFT - s_setreg_b32 hwreg(S_STATUS_HWREG, SQ_WAVE_STATE_PRIV_SCC_SHIFT, \ - SQ_WAVE_STATE_PRIV_POISON_ERR_SHIFT - SQ_WAVE_STATE_PRIV_SCC_SHIFT + 1), s_save_status -#endif - s_rfe_b64 [ttmp0, ttmp1] L_SAVE:
@@ -478,14 +377,6 @@ L_SAVE: s_endpgm L_HAVE_VGPRS: #endif -#if ASIC_FAMILY >= CHIP_GFX12 - s_getreg_b32 s_save_tmp, hwreg(HW_REG_WAVE_STATUS) - s_bitcmp1_b32 s_save_tmp, SQ_WAVE_STATUS_NO_VGPRS_SHIFT - s_cbranch_scc0 L_HAVE_VGPRS - s_endpgm -L_HAVE_VGPRS: -#endif - s_and_b32 s_save_pc_hi, s_save_pc_hi, 0x0000ffff //pc[47:32] s_mov_b32 s_save_tmp, 0 s_setreg_b32 hwreg(S_TRAPSTS_HWREG, S_TRAPSTS_SAVE_CONTEXT_SHIFT, 1), s_save_tmp //clear saveCtx bit
@@ -671,19 +562,6 @@ L_SAVE_HWREG: s_mov_b32 m0, 0x0 //Next lane of v2 to write to #endif -#if ASIC_FAMILY >= CHIP_GFX12 - // Ensure no further changes to barrier or LDS state. - // STATE_PRIV.BARRIER_COMPLETE may change up to this point. - s_barrier_signal -2 - s_barrier_wait -2 - - // Re-read final state of BARRIER_COMPLETE field for save. - s_getreg_b32 s_save_tmp, hwreg(S_STATUS_HWREG) - s_and_b32 s_save_tmp, s_save_tmp, SQ_WAVE_STATE_PRIV_BARRIER_COMPLETE_MASK - s_andn2_b32 s_save_status, s_save_status, SQ_WAVE_STATE_PRIV_BARRIER_COMPLETE_MASK - s_or_b32 s_save_status, s_save_status, s_save_tmp -#endif - write_hwreg_to_mem(s_save_m0, s_save_buf_rsrc0, s_save_mem_offset) write_hwreg_to_mem(s_save_pc_lo, s_save_buf_rsrc0, s_save_mem_offset) s_andn2_b32 s_save_tmp, s_save_pc_hi, S_SAVE_PC_HI_FIRST_WAVE_MASK
@@ -707,21 +585,6 @@ L_SAVE_HWREG: s_getreg_b32 s_save_m0, hwreg(HW_REG_SHADER_FLAT_SCRATCH_HI) write_hwreg_to_mem(s_save_m0, s_save_buf_rsrc0, s_save_mem_offset) -#if ASIC_FAMILY >= CHIP_GFX12 - s_getreg_b32 s_save_m0, hwreg(HW_REG_WAVE_EXCP_FLAG_USER) - write_hwreg_to_mem(s_save_m0, s_save_buf_rsrc0, s_save_mem_offset) - - s_getreg_b32 s_save_m0, hwreg(HW_REG_WAVE_TRAP_CTRL) - write_hwreg_to_mem(s_save_m0, s_save_buf_rsrc0, s_save_mem_offset) - - s_getreg_b32 s_save_tmp, hwreg(HW_REG_WAVE_STATUS) - write_hwreg_to_mem(s_save_tmp, s_save_buf_rsrc0, s_save_mem_offset) - - s_get_barrier_state s_save_tmp, -1 - s_wait_kmcnt (0) - write_hwreg_to_mem(s_save_tmp, s_save_buf_rsrc0, s_save_mem_offset) -#endif - #if NO_SQC_STORE // Write HWREGs with 16 VGPR lanes. TTMPs occupy space after this. s_mov_b32 exec_lo, 0xFFFF
@@ -814,9 +677,7 @@ L_SAVE_LDS_NORMAL: s_and_b32 s_save_alloc_size, s_save_alloc_size, 0xFFFFFFFF //lds_size is zero? s_cbranch_scc0 L_SAVE_LDS_DONE //no lds used? jump to L_SAVE_DONE -#if ASIC_FAMILY < CHIP_GFX12 s_barrier //LDS is used? wait for other waves in the same TG -#endif s_and_b32 s_save_tmp, s_save_pc_hi, S_SAVE_PC_HI_FIRST_WAVE_MASK s_cbranch_scc0 L_SAVE_LDS_DONE
@@ -1081,11 +942,6 @@ L_RESTORE: s_mov_b32 s_restore_buf_rsrc2, 0 //NUM_RECORDS initial value = 0 (in bytes) s_mov_b32 s_restore_buf_rsrc3, S_RESTORE_BUF_RSRC_WORD3_MISC -#if ASIC_FAMILY >= CHIP_GFX12 - // Save s_restore_spi_init_hi for later use. - s_mov_b32 s_restore_spi_init_hi_save, s_restore_spi_init_hi -#endif - //determine it is wave32 or wave64 get_wave_size2(s_restore_size)
@@ -1320,9 +1176,7 @@ L_RESTORE_SGPR: // s_barrier with MODE.DEBUG_EN=1, STATUS.PRIV=1 incorrectly asserts debug exception. // Clear DEBUG_EN before and restore MODE after the barrier. s_setreg_imm32_b32 hwreg(HW_REG_MODE), 0 -#if ASIC_FAMILY < CHIP_GFX12 s_barrier //barrier to ensure the readiness of LDS before access attemps from any other wave in the same TG -#endif /* restore HW registers */ L_RESTORE_HWREG:
@@ -1334,11 +1188,6 @@ L_RESTORE_HWREG: s_mov_b32 s_restore_buf_rsrc2, 0x1000000 //NUM_RECORDS in bytes -#if ASIC_FAMILY >= CHIP_GFX12 - // Restore s_restore_spi_init_hi before the saved value gets clobbered. - s_mov_b32 s_restore_spi_init_hi, s_restore_spi_init_hi_save -#endif - read_hwreg_from_mem(s_restore_m0, s_restore_buf_rsrc0, s_restore_mem_offset) read_hwreg_from_mem(s_restore_pc_lo, s_restore_buf_rsrc0, s_restore_mem_offset) read_hwreg_from_mem(s_restore_pc_hi, s_restore_buf_rsrc0, s_restore_mem_offset)
@@ -1358,44 +1207,6 @@ L_RESTORE_HWREG: s_setreg_b32 hwreg(HW_REG_SHADER_FLAT_SCRATCH_HI), s_restore_flat_scratch -#if ASIC_FAMILY >= CHIP_GFX12 - read_hwreg_from_mem(s_restore_tmp, s_restore_buf_rsrc0, s_restore_mem_offset) - S_WAITCNT_0 - s_setreg_b32 hwreg(HW_REG_WAVE_EXCP_FLAG_USER), s_restore_tmp - - read_hwreg_from_mem(s_restore_tmp, s_restore_buf_rsrc0, s_restore_mem_offset) - S_WAITCNT_0 - s_setreg_b32 hwreg(HW_REG_WAVE_TRAP_CTRL), s_restore_tmp - - // Only the first wave needs to restore the workgroup barrier. - s_and_b32 s_restore_tmp, s_restore_spi_init_hi, S_RESTORE_SPI_INIT_FIRST_WAVE_MASK - s_cbranch_scc0 L_SKIP_BARRIER_RESTORE - - // Skip over WAVE_STATUS, since there is no state to restore from it - s_add_u32 s_restore_mem_offset, s_restore_mem_offset, 4 - - read_hwreg_from_mem(s_restore_tmp, s_restore_buf_rsrc0, s_restore_mem_offset) - S_WAITCNT_0 - - s_bitcmp1_b32 s_restore_tmp, BARRIER_STATE_VALID_OFFSET - s_cbranch_scc0 L_SKIP_BARRIER_RESTORE - - // extract the saved signal count from s_restore_tmp - s_lshr_b32 s_restore_tmp, s_restore_tmp, BARRIER_STATE_SIGNAL_OFFSET - - // We need to call s_barrier_signal repeatedly to restore the signal - // count of the work group barrier. The member count is already - // initialized with the number of waves in the work group. -L_BARRIER_RESTORE_LOOP: - s_and_b32 s_restore_tmp, s_restore_tmp, s_restore_tmp - s_cbranch_scc0 L_SKIP_BARRIER_RESTORE - s_barrier_signal -1 - s_add_i32 s_restore_tmp, s_restore_tmp, -1 - s_branch L_BARRIER_RESTORE_LOOP - -L_SKIP_BARRIER_RESTORE: -#endif - s_mov_b32 m0, s_restore_m0 s_mov_b32 exec_lo, s_restore_exec_lo s_mov_b32 exec_hi, s_restore_exec_hi
@@ -1453,13 +1264,6 @@ L_RETURN_WITHOUT_PRIV: s_setreg_b32 hwreg(S_STATUS_HWREG), s_restore_status // SCC is included, which is changed by previous salu -#if ASIC_FAMILY >= CHIP_GFX12 - // Make barrier and LDS state visible to all waves in the group. - // STATE_PRIV.BARRIER_COMPLETE may change after this point. - s_barrier_signal -2 - s_barrier_wait -2 -#endif - s_rfe_b64 s_restore_pc_lo //Return to the main shader program and resume execution L_END_PGM:
@@ -1598,11 +1402,7 @@ function get_hwreg_size_bytes end function get_wave_size2(s_reg) -#if ASIC_FAMILY < CHIP_GFX12 s_getreg_b32 s_reg, hwreg(HW_REG_IB_STS2,SQ_WAVE_IB_STS2_WAVE64_SHIFT,SQ_WAVE_IB_STS2_WAVE64_SIZE) -#else - s_getreg_b32 s_reg, hwreg(HW_REG_WAVE_STATUS,SQ_WAVE_STATUS_WAVE64_SHIFT,SQ_WAVE_STATUS_WAVE64_SIZE) -#endif s_lshl_b32 s_reg, s_reg, S_WAVE_SIZE end
drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx12.asm new file +1126 -0
1,126 lines not on this page · raw message
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 38/154 drm/amdkfd: Ensure consistent barrier state saved in gfx12 trap handler
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lancelot SIX <[email protected]>
[ Upstream commit d584198a6fe4c51f4aa88ad72f258f8961a0f11c ]
It is possible for some waves in a workgroup to finish their save sequence before the group leader has had time to capture the workgroup barrier state. When this happens, having those waves exit do impact the barrier state. As a consequence, the state captured by the group leader is invalid, and is eventually incorrectly restored.
This patch proposes to have all waves in a workgroup wait for each other at the end of their save sequence (just before calling s_endpgm_saved).
--- drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h | 3 ++- drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx12.asm | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h +2 -1
@@ -4117,7 +4117,8 @@ static const uint32_t cwsr_trap_gfx12_hex[] = {0x0000ffff ,0x8bfe7e7e ,0x8bea6a6a ,0xb97af804 ,0xbe804ec2 ,0xbf94fffe , -0xbe804a6c ,0xbfb10000 , +0xbe804a6c ,0xbe804ec2 , +0xbf94fffe ,0xbfb10000 ,0xbf9f0000 ,0xbf9f0000 ,0xbf9f0000 ,0xbf9f0000 , 0xbf9f0000, 0x00000000,
drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx12.asm +4 -0
@@ -1049,6 +1049,10 @@ L_SKIP_BARRIER_RESTORE: s_rfe_b64 s_restore_pc_lo //Return to the main shader program and resume execution L_END_PGM: + // Make sure that no wave of the workgroup can exit the trap handler + // before the workgroup barrier state is saved. + s_barrier_signal -2 + s_barrier_wait -2 s_endpgm_saved end
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 21/154 Bluetooth: qca: Update firmware-name to support board specific nvm
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cheng Jiang <[email protected]>
[ Upstream commit a4c5a468c6329bde7dfd46bacff2cbf5f8a8152e ]
Different connectivity boards may be attached to the same platform. For example, QCA6698-based boards can support either a two-antenna or three-antenna solution, both of which work on the sa8775p-ride platform. Due to differences in connectivity boards and variations in RF performance from different foundries, different NVM configurations are used based on the board ID.
Therefore, in the firmware-name property, if the NVM file has an extension, the NVM file will be used. Otherwise, the system will first try the .bNN (board ID) file, and if that fails, it will fall back to the .bin file.
Possible configurations:
firmware-name = "QCA6698/hpnv21";
firmware-name = "QCA6698/hpnv21.bin";
Stable-dep-of: a2fad248947d ("Bluetooth: qca: Fix poor RF performance for WCN6855")
--- drivers/bluetooth/btqca.c | 113 ++++++++++++++++++++++++++++---------- 1 file changed, 85 insertions(+), 28 deletions(-)
drivers/bluetooth/btqca.c +85 -28
@@ -272,6 +272,39 @@ int qca_send_pre_shutdown_cmd(struct hci_dev *hdev) }EXPORT_SYMBOL_GPL (qca_send_pre_shutdown_cmd); +static bool qca_filename_has_extension (const char *filename) +{ +const char *suffix =strrchr (filename,'.' ); + +/* File extensions require a dot, but not as the first or last character */ +if (!suffix || suffix == filename || *(suffix +1 ) =='\0' ) +return 0 ; + +/* Avoid matching directories with names that look like files with extensions */ +return !strchr (suffix,'/' ); +} + +static bool qca_get_alt_nvm_file (char *filename,size_t max_size) +{ +char fwname[64 ]; +const char *suffix; + +/* nvm file name has an extension, replace with .bin */ +if (qca_filename_has_extension (filename)) { + suffix =strrchr (filename,'.' ); +strscpy (fwname, filename, suffix - filename +1 ); +snprintf (fwname + (suffix - filename), +sizeof (fwname) - (suffix - filename),".bin" ); +/* If nvm file is already the default one, return false to skip the retry. */ +if (strcmp (fwname, filename) ==0 ) +return false; + +snprintf (filename, max_size,"%s" , fwname); +return true; + } +return false; +} + static int qca_tlv_check_data(struct hci_dev *hdev, struct qca_fw_config *config, u8 *fw_data, size_t fw_size,
@@ -564,6 +597,19 @@ static int qca_download_firmware(struct hci_dev *hdev, config->fwname, ret);return ret; } + } +/* If the board-specific file is missing, try loading the default +* one, unless that was attempted already. +*/ +else if (config->type ==TLV_TYPE_NVM && +qca_get_alt_nvm_file (config->fwname,sizeof (config->fwname))) { +bt_dev_info (hdev,"QCA Downloading %s" , config->fwname); + ret =request_firmware (&fw, config->fwname, &hdev->dev); +if (ret) { +bt_dev_err (hdev,"QCA Failed to request file: %s (%d)" , + config->fwname, ret); +return ret; + } }else {bt_dev_err (hdev,"QCA Failed to request file: %s (%d)" , config->fwname, ret);
@@ -700,34 +746,38 @@ static int qca_check_bdaddr(struct hci_dev *hdev, const struct qca_fw_config *coreturn 0 ; } -static void qca_generate_hsp_nvm_name (char *fwname,size_t max_size, +static void qca_get_nvm_name_by_board (char *fwname,size_t max_size, +const char *stem,enum qca_btsoc_type soc_type,struct qca_btsoc_version ver,u8 rom_ver,u16 bid) {const char *variant; +const char *prefix; -/* hsp gf chip */ -if ((le32_to_cpu (ver.soc_id) &QCA_HSP_GF_SOC_MASK ) ==QCA_HSP_GF_SOC_ID ) - variant ="g" ; -else - variant ="" ; +/* Set the default value to variant and prefix */ + variant ="" ; + prefix ="b" ; -if (bid ==0x0 ) -snprintf (fwname, max_size,"qca/hpnv%02x%s.bin" , rom_ver, variant); -else -snprintf (fwname, max_size,"qca/hpnv%02x%s.%x" , rom_ver, variant, bid); -} +if (soc_type ==QCA_QCA2066 ) + prefix ="" ; -static inline void qca_get_nvm_name_generic (struct qca_fw_config *cfg, -const char *stem,u8 rom_ver,u16 bid) -{ -if (bid ==0x0 ) -snprintf (cfg->fwname,sizeof (cfg->fwname),"qca/%snv%02x.bin" , stem, rom_ver); -else if (bid &0xff00 ) -snprintf (cfg->fwname,sizeof (cfg->fwname), -"qca/%snv%02x.b%x" , stem, rom_ver, bid); -else -snprintf (cfg->fwname,sizeof (cfg->fwname), -"qca/%snv%02x.b%02x" , stem, rom_ver, bid); +if (soc_type ==QCA_WCN6855 || soc_type ==QCA_QCA2066 ) { +/* If the chip is manufactured by GlobalFoundries */ +if ((le32_to_cpu (ver.soc_id) &QCA_HSP_GF_SOC_MASK ) ==QCA_HSP_GF_SOC_ID ) + variant ="g" ; + } + +if (rom_ver !=0 ) { +if (bid ==0x0 || bid ==0xffff ) +snprintf (fwname, max_size,"qca/%s%02x%s.bin" , stem, rom_ver, variant); +else +snprintf (fwname, max_size,"qca/%s%02x%s.%s%02x" , stem, rom_ver, + variant, prefix, bid); + }else { +if (bid ==0x0 || bid ==0xffff ) +snprintf (fwname, max_size,"qca/%s%s.bin" , stem, variant); +else +snprintf (fwname, max_size,"qca/%s%s.%s%02x" , stem, variant, prefix, bid); + } } int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
@@ -816,8 +866,14 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,/* Download NVM configuration */ config.type =TLV_TYPE_NVM ;if (firmware_name) { -snprintf (config.fwname,sizeof (config.fwname), -"qca/%s" , firmware_name); +/* The firmware name has an extension, use it directly */ +if (qca_filename_has_extension (firmware_name)) { +snprintf (config.fwname,sizeof (config.fwname),"qca/%s" , firmware_name); + }else { +qca_read_fw_board_id (hdev, &boardid); +qca_get_nvm_name_by_board (config.fwname,sizeof (config.fwname), + firmware_name, soc_type, ver,0 , boardid); + } }else {switch (soc_type) {case QCA_WCN3990 :
@@ -836,8 +892,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, "qca/apnv%02x.bin", rom_ver);break ;case QCA_QCA2066 : -qca_generate_hsp_nvm_name (config.fwname, -sizeof (config.fwname), ver, rom_ver, boardid); +qca_get_nvm_name_by_board (config.fwname, +sizeof (config.fwname),"hpnv" , soc_type, ver, + rom_ver, boardid);break ;case QCA_QCA6390 : snprintf(config.fwname, sizeof(config.fwname),
@@ -852,9 +909,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, "qca/hpnv%02x.bin", rom_ver);break ;case QCA_WCN7850 : -qca_get_nvm_name_generic (&config,"hmt" , rom_ver, boardid); +qca_get_nvm_name_by_board (config.fwname,sizeof (config.fwname), +"hmtnv" , soc_type, ver, rom_ver, boardid);break ; -default :snprintf (config.fwname,sizeof (config.fwname),"qca/nvm_%08x.bin" , soc_ver);
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 39/154 tracing: Switch trace.c code over to use guard()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Steven Rostedt <[email protected]>
[ Upstream commit d33b10c0c73adca00f72bf4a153a07b7f5f34715 ]
There are several functions in trace.c that have "goto out;" or equivalent on error in order to release locks or free values that were allocated. This can be error prone or just simply make the code more complex.
Switch every location that ends with unlocking a mutex or freeing on error over to using the guard(mutex)() and __free() infrastructure to let the compiler worry about releasing locks. This makes the code easier to read and understand.
There's one place that should probably return an error but instead return
0. This does not change the return as the only changes are to do the conversion without changing the logic. Fixing that location will have to come later.
Stable-dep-of: 60b8f711143d ("tracing: Have the error of __tracing_resize_ring_buffer() passed to user")
--- kernel/trace/trace.c | 266 +++++++++++++++---------------------------- 1 file changed, 94 insertions(+), 172 deletions(-)
kernel/trace/trace.c +94 -172
@@ -26,6 +26,7 @@#include <linux/hardirq.h> #include <linux/linkage.h> #include <linux/uaccess.h> +#include <linux/cleanup.h> #include <linux/vmalloc.h> #include <linux/ftrace.h> #include <linux/module.h>
@@ -535,19 +536,16 @@ LIST_HEAD(ftrace_trace_arrays);int trace_array_get (struct trace_array *this_tr) {struct trace_array *tr; -int ret = -ENODEV ; -mutex_lock (&trace_types_lock); +guard (mutex)(&trace_types_lock);list_for_each_entry (tr, &ftrace_trace_arrays, list) {if (tr == this_tr) { tr->ref++; - ret =0 ; -break ; +return 0 ; } } -mutex_unlock (&trace_types_lock); -return ret; +return -ENODEV ; }static void __trace_array_put (struct trace_array *this_tr)
@@ -1456,22 +1454,20 @@ EXPORT_SYMBOL_GPL(tracing_snapshot_alloc);int tracing_snapshot_cond_enable (struct trace_array *tr,void *cond_data,cond_update_fn_t update) { -struct cond_snapshot *cond_snapshot; -int ret =0 ; + struct cond_snapshot *cond_snapshot __free(kfree) = +kzalloc (sizeof (*cond_snapshot),GFP_KERNEL ); +int ret; - cond_snapshot =kzalloc (sizeof (*cond_snapshot),GFP_KERNEL );if (!cond_snapshot)return -ENOMEM ; cond_snapshot->cond_data = cond_data; cond_snapshot->update = update; -mutex_lock (&trace_types_lock); +guard (mutex)(&trace_types_lock); -if (tr->current_trace->use_max_tr) { - ret = -EBUSY ; - goto fail_unlock; - } +if (tr->current_trace->use_max_tr) +return -EBUSY ;/* * The cond_snapshot can only change to NULL without the
@@ -1481,29 +1477,20 @@ int tracing_snapshot_cond_enable(struct trace_array *tr, void *cond_data,* do safely with only holding the trace_types_lock and not * having to take the max_lock. */ -if (tr->cond_snapshot) { - ret = -EBUSY ; - goto fail_unlock; - } +if (tr->cond_snapshot) +return -EBUSY ; ret =tracing_arm_snapshot_locked (tr);if (ret) - goto fail_unlock; +return ret;local_irq_disable ();arch_spin_lock (&tr->max_lock); - tr->cond_snapshot = cond_snapshot; + tr->cond_snapshot =no_free_ptr (cond_snapshot);arch_spin_unlock (&tr->max_lock);local_irq_enable (); -mutex_unlock (&trace_types_lock); - -return ret; - - fail_unlock: -mutex_unlock (&trace_types_lock); -kfree (cond_snapshot); -return ret; +return 0 ; }EXPORT_SYMBOL_GPL (tracing_snapshot_cond_enable);
@@ -2216,10 +2203,10 @@ static __init int init_trace_selftests(void) selftests_can_run = true; -mutex_lock (&trace_types_lock); +guard (mutex)(&trace_types_lock);if (list_empty (&postponed_selftests)) - goto out; +return 0 ;pr_info ("Running postponed tracer tests:\n" );
@@ -2248,9 +2235,6 @@ static __init int init_trace_selftests(void) } tracing_selftest_running = false; - out: -mutex_unlock (&trace_types_lock); -return 0 ; }core_initcall (init_trace_selftests);
@@ -2818,7 +2802,7 @@ int tracepoint_printk_sysctl(const struct ctl_table *table, int write,int save_tracepoint_printk;int ret; -mutex_lock (&tracepoint_printk_mutex); +guard (mutex)(&tracepoint_printk_mutex); save_tracepoint_printk = tracepoint_printk; ret =proc_dointvec (table, write, buffer, lenp, ppos);
@@ -2831,16 +2815,13 @@ int tracepoint_printk_sysctl(const struct ctl_table *table, int write, tracepoint_printk =0 ;if (save_tracepoint_printk == tracepoint_printk) - goto out; +return ret;if (tracepoint_printk)static_key_enable (&tracepoint_printk_key.key);else static_key_disable (&tracepoint_printk_key.key); - out: -mutex_unlock (&tracepoint_printk_mutex); -return ret; }
@@ -5150,7 +5131,8 @@ static int tracing_trace_options_show(struct seq_file *m, void *v)u32 tracer_flags;int i; -mutex_lock (&trace_types_lock); +guard (mutex)(&trace_types_lock); + tracer_flags = tr->current_trace->flags->val; trace_opts = tr->current_trace->flags->opts;
@@ -5167,7 +5149,6 @@ static int tracing_trace_options_show(struct seq_file *m, void *v)else seq_printf (m,"no%s\n" , trace_opts[i].name); } -mutex_unlock (&trace_types_lock);return 0 ; }
@@ -5832,7 +5813,7 @@ trace_insert_eval_map_file(struct module *mod, struct trace_eval_map **start,return ; } -mutex_lock (&trace_eval_mutex); +guard (mutex)(&trace_eval_mutex);if (!trace_eval_maps) trace_eval_maps = map_array;
@@ -5856,8 +5837,6 @@ trace_insert_eval_map_file(struct module *mod, struct trace_eval_map **start, map_array++; }memset (map_array,0 ,sizeof (*map_array)); - -mutex_unlock (&trace_eval_mutex); }static void trace_create_eval_file (struct dentry *d_tracer)
@@ -6021,23 +6000,18 @@ ssize_t tracing_resize_ring_buffer(struct trace_array *tr, {int ret; -mutex_lock (&trace_types_lock); +guard (mutex)(&trace_types_lock);if (cpu_id !=RING_BUFFER_ALL_CPUS ) {/* make sure, this cpu is enabled in the mask */ -if (!cpumask_test_cpu (cpu_id, tracing_buffer_mask)) { - ret = -EINVAL ; - goto out; - } +if (!cpumask_test_cpu (cpu_id, tracing_buffer_mask)) +return -EINVAL ; } ret =__tracing_resize_ring_buffer (tr, size, cpu_id);if (ret <0 ) ret = -ENOMEM ; -out: -mutex_unlock (&trace_types_lock); -return ret; }
@@ -6129,9 +6103,9 @@ int tracing_set_tracer(struct trace_array *tr, const char *buf)#ifdef CONFIG_TRACER_MAX_TRACE bool had_max_tr;#endif -int ret =0 ; +int ret; -mutex_lock (&trace_types_lock); +guard (mutex)(&trace_types_lock);update_last_data (tr);
@@ -6139,7 +6113,7 @@ int tracing_set_tracer(struct trace_array *tr, const char *buf) ret =__tracing_resize_ring_buffer (tr, trace_buf_size,RING_BUFFER_ALL_CPUS );if (ret <0 ) - goto out; +return ret; ret =0 ; }
@@ -6147,12 +6121,11 @@ int tracing_set_tracer(struct trace_array *tr, const char *buf)if (strcmp (t->name, buf) ==0 )break ; } -if (!t) { - ret = -EINVAL ; - goto out; - } +if (!t) +return -EINVAL ; +if (t == tr->current_trace) - goto out; +return 0 ;#ifdef CONFIG_TRACER_SNAPSHOT if (t->use_max_tr) {
@@ -6163,27 +6136,23 @@ int tracing_set_tracer(struct trace_array *tr, const char *buf)arch_spin_unlock (&tr->max_lock);local_irq_enable ();if (ret) - goto out; + return ret; }#endif /* Some tracers won't work on kernel command line */ if (system_state <SYSTEM_RUNNING && t->noboot) {pr_warn ("Tracer '%s' is not allowed on command line, ignored\n" , t->name); - goto out; +return 0 ; }/* Some tracers are only allowed for the top level buffer */ -if (!trace_ok_for_array (t, tr)) { - ret = -EINVAL ; - goto out; - } +if (!trace_ok_for_array (t, tr)) +return -EINVAL ;/* If trace pipe files are being read, we can't change the tracer */ -if (tr->trace_ref) { - ret = -EBUSY ; - goto out; - } +if (tr->trace_ref) +return -EBUSY ;trace_branch_disable ();
@@ -6214,7 +6183,7 @@ int tracing_set_tracer(struct trace_array *tr, const char *buf)if (!had_max_tr && t->use_max_tr) { ret =tracing_arm_snapshot_locked (tr);if (ret) - goto out; +return ret; }#else tr->current_trace = &nop_trace;
@@ -6227,17 +6196,15 @@ int tracing_set_tracer(struct trace_array *tr, const char *buf)if (t->use_max_tr)tracing_disarm_snapshot (tr);#endif - goto out; +return ret; } } tr->current_trace = t; tr->current_trace->enabled++;trace_branch_enable (tr); - out: -mutex_unlock (&trace_types_lock); -return ret; +return 0 ; } static ssize_t
@@ -6315,22 +6282,18 @@ tracing_thresh_write(struct file *filp, const char __user *ubuf,struct trace_array *tr = filp->private_data;int ret; -mutex_lock (&trace_types_lock); +guard (mutex)(&trace_types_lock); ret =tracing_nsecs_write (&tracing_thresh, ubuf, cnt, ppos);if (ret <0 ) - goto out; +return ret;if (tr->current_trace->update_thresh) { ret = tr->current_trace->update_thresh (tr);if (ret <0 ) - goto out; +return ret; } - ret = cnt; -out: -mutex_unlock (&trace_types_lock); - -return ret; +return cnt; }#ifdef CONFIG_TRACER_MAX_TRACE
@@ -6549,31 +6512,29 @@ tracing_read_pipe(struct file *filp, char __user *ubuf,* This is just a matter of traces coherency, the ring buffer itself * is protected. */ -mutex_lock (&iter->mutex); +guard (mutex)(&iter->mutex);/* return any leftover data */ sret =trace_seq_to_user (&iter->seq, ubuf, cnt);if (sret != -EBUSY ) - goto out; +return sret;trace_seq_init (&iter->seq);if (iter->trace->read) { sret = iter->trace->read (iter, filp, ubuf, cnt, ppos);if (sret) - goto out; +return sret; } waitagain: sret =tracing_wait_pipe (filp);if (sret <=0 ) - goto out; +return sret;/* stop when tracing is finished */ -if (trace_empty (iter)) { - sret =0 ; - goto out; - } +if (trace_empty (iter)) +return 0 ;if (cnt >=TRACE_SEQ_BUFFER_SIZE ) cnt =TRACE_SEQ_BUFFER_SIZE -1 ;
@@ -6637,9 +6598,6 @@ tracing_read_pipe(struct file *filp, char __user *ubuf,if (sret == -EBUSY ) goto waitagain; -out: -mutex_unlock (&iter->mutex); -return sret; }
@@ -7231,25 +7189,19 @@ u64 tracing_event_time_stamp(struct trace_buffer *buffer, struct ring_buffer_eve*/ int tracing_set_filter_buffering (struct trace_array *tr,bool set) { -int ret =0 ; - -mutex_lock (&trace_types_lock); +guard (mutex)(&trace_types_lock);if (set && tr->no_filter_buffering_ref++) - goto out; +return 0 ;if (!set) { -if (WARN_ON_ONCE (!tr->no_filter_buffering_ref)) { - ret = -EINVAL ; - goto out; - } +if (WARN_ON_ONCE (!tr->no_filter_buffering_ref)) +return -EINVAL ; --tr->no_filter_buffering_ref; } - out: -mutex_unlock (&trace_types_lock); -return ret; +return 0 ; }struct ftrace_buffer_info {
@@ -7325,12 +7277,10 @@ tracing_snapshot_write(struct file *filp, const char __user *ubuf, size_t cnt,if (ret)return ret; -mutex_lock (&trace_types_lock); +guard (mutex)(&trace_types_lock); -if (tr->current_trace->use_max_tr) { - ret = -EBUSY ; - goto out; - } +if (tr->current_trace->use_max_tr) +return -EBUSY ;local_irq_disable ();arch_spin_lock (&tr->max_lock);
@@ -7339,24 +7289,20 @@ tracing_snapshot_write(struct file *filp, const char __user *ubuf, size_t cnt,arch_spin_unlock (&tr->max_lock);local_irq_enable ();if (ret) - goto out; +return ret;switch (val) {case 0 : -if (iter->cpu_file !=RING_BUFFER_ALL_CPUS ) { - ret = -EINVAL ; -break ; - } +if (iter->cpu_file !=RING_BUFFER_ALL_CPUS ) +return -EINVAL ;if (tr->allocated_snapshot)free_snapshot (tr);break ;case 1 :/* Only allow per-cpu swap if the ring buffer supports it */ #ifndef CONFIG_RING_BUFFER_ALLOW_SWAP -if (iter->cpu_file !=RING_BUFFER_ALL_CPUS ) { - ret = -EINVAL ; -break ; - } +if (iter->cpu_file !=RING_BUFFER_ALL_CPUS ) +return -EINVAL ;#endif if (tr->allocated_snapshot) ret = resize_buffer_duplicate_size(&tr->max_buffer,
@@ -7364,7 +7310,7 @@ tracing_snapshot_write(struct file *filp, const char __user *ubuf, size_t cnt, ret =tracing_arm_snapshot_locked (tr);if (ret) -break ; +return ret;/* Now, we're going to swap */ if (iter->cpu_file ==RING_BUFFER_ALL_CPUS ) {
@@ -7391,8 +7337,7 @@ tracing_snapshot_write(struct file *filp, const char __user *ubuf, size_t cnt, *ppos += cnt; ret = cnt; } -out: -mutex_unlock (&trace_types_lock); +return ret; }
@@ -7778,12 +7723,11 @@ void tracing_log_err(struct trace_array *tr, len +=sizeof (CMD_PREFIX ) +2 *sizeof ("\n" ) +strlen (cmd) +1 ; -mutex_lock (&tracing_err_log_lock); +guard (mutex)(&tracing_err_log_lock); + err =get_tracing_log_err (tr, len); -if (PTR_ERR (err) == -ENOMEM ) { -mutex_unlock (&tracing_err_log_lock); +if (PTR_ERR (err) == -ENOMEM )return ; - }snprintf (err->loc,TRACING_LOG_LOC_MAX ,"%s: error: " , loc);snprintf (err->cmd, len,"\n" CMD_PREFIX "%s\n" , cmd);
@@ -7794,7 +7738,6 @@ void tracing_log_err(struct trace_array *tr, err->info.ts =local_clock ();list_add_tail (&err->list, &tr->err_log); -mutex_unlock (&tracing_err_log_lock); }static void clear_tracing_err_log (struct trace_array *tr)
@@ -9535,20 +9478,17 @@ static int instance_mkdir(const char *name)struct trace_array *tr;int ret; -mutex_lock (&event_mutex); -mutex_lock (&trace_types_lock); +guard (mutex)(&event_mutex); +guard (mutex)(&trace_types_lock); ret = -EEXIST ;if (trace_array_find (name)) - goto out_unlock; +return -EEXIST ; tr =trace_array_create (name); ret =PTR_ERR_OR_ZERO (tr); -out_unlock: -mutex_unlock (&trace_types_lock); -mutex_unlock (&event_mutex);return ret; }
@@ -9598,24 +9538,23 @@ struct trace_array *trace_array_get_by_name(const char *name, const char *system {struct trace_array *tr; -mutex_lock (&event_mutex); -mutex_lock (&trace_types_lock); +guard (mutex)(&event_mutex); +guard (mutex)(&trace_types_lock);list_for_each_entry (tr, &ftrace_trace_arrays, list) { -if (tr->name &&strcmp (tr->name, name) ==0 ) - goto out_unlock; +if (tr->name &&strcmp (tr->name, name) ==0 ) { + tr->ref++; +return tr; + } } tr =trace_array_create_systems (name, systems,0 ,0 );if (IS_ERR (tr)) tr =NULL ; -out_unlock: -if (tr) +else tr->ref++; -mutex_unlock (&trace_types_lock); -mutex_unlock (&event_mutex);return tr; }EXPORT_SYMBOL_GPL (trace_array_get_by_name);
@@ -9666,48 +9605,36 @@ static int __remove_instance(struct trace_array *tr)int trace_array_destroy (struct trace_array *this_tr) {struct trace_array *tr; -int ret;if (!this_tr)return -EINVAL ; -mutex_lock (&event_mutex); -mutex_lock (&trace_types_lock); +guard (mutex)(&event_mutex); +guard (mutex)(&trace_types_lock); - ret = -ENODEV ;/* Making sure trace array exists before destroying it. */ list_for_each_entry (tr, &ftrace_trace_arrays, list) { -if (tr == this_tr) { - ret =__remove_instance (tr); -break ; - } +if (tr == this_tr) +return __remove_instance (tr); } -mutex_unlock (&trace_types_lock); -mutex_unlock (&event_mutex); - -return ret; +return -ENODEV ; }EXPORT_SYMBOL_GPL (trace_array_destroy);static int instance_rmdir (const char *name) {struct trace_array *tr; -int ret; -mutex_lock (&event_mutex); -mutex_lock (&trace_types_lock); +guard (mutex)(&event_mutex); +guard (mutex)(&trace_types_lock); - ret = -ENODEV ; tr =trace_array_find (name); -if (tr) - ret =__remove_instance (tr); - -mutex_unlock (&trace_types_lock); -mutex_unlock (&event_mutex); +if (!tr) +return -ENODEV ; -return ret; +return __remove_instance (tr); }static __init void create_trace_instances (struct dentry *d_tracer)
@@ -9720,19 +9647,16 @@ static __init void create_trace_instances(struct dentry *d_tracer)if (MEM_FAIL (!trace_instance_dir,"Failed to create instances directory\n" ))return ; -mutex_lock (&event_mutex); -mutex_lock (&trace_types_lock); +guard (mutex)(&event_mutex); +guard (mutex)(&trace_types_lock);list_for_each_entry (tr, &ftrace_trace_arrays, list) {if (!tr->name)continue ;if (MEM_FAIL (trace_array_create_dir (tr) <0 ,"Failed to create instance directory\n" )) -break ; +return ; } - -mutex_unlock (&trace_types_lock); -mutex_unlock (&event_mutex); } static void
@@ -9946,7 +9870,7 @@ static void trace_module_remove_evals(struct module *mod)if (!mod->num_trace_evals)return ; -mutex_lock (&trace_eval_mutex); +guard (mutex)(&trace_eval_mutex); map = trace_eval_maps;
@@ -9958,12 +9882,10 @@ static void trace_module_remove_evals(struct module *mod) map = map->tail.next; }if (!map) - goto out; +return ; *last =trace_eval_jmp_to_tail (map)->tail.next;kfree (map); - out: -mutex_unlock (&trace_eval_mutex); }#else static inline void trace_module_remove_evals (struct module *mod) { }
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 40/154 tracing: Have the error of __tracing_resize_ring_buffer() passed to user
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Steven Rostedt <[email protected]>
[ Upstream commit 60b8f711143de7cd9c0f55be0fe7eb94b19eb5c7 ]
Currently if __tracing_resize_ring_buffer() returns an error, the tracing_resize_ringbuffer() returns -ENOMEM. But it may not be a memory issue that caused the function to fail. If the ring buffer is memory mapped, then the resizing of the ring buffer will be disabled. But if the user tries to resize the buffer, it will get an -ENOMEM returned, which is confusing because there is plenty of memory. The actual error returned was -EBUSY, which would make much more sense to the user.
--- kernel/trace/trace.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-)
kernel/trace/trace.c +1 -7
@@ -5998,8 +5998,6 @@ static int __tracing_resize_ring_buffer(struct trace_array *tr,ssize_t tracing_resize_ring_buffer (struct trace_array *tr,unsigned long size,int cpu_id) { -int ret; -guard (mutex)(&trace_types_lock);if (cpu_id !=RING_BUFFER_ALL_CPUS ) {
@@ -6008,11 +6006,7 @@ ssize_t tracing_resize_ring_buffer(struct trace_array *tr,return -EINVAL ; } - ret =__tracing_resize_ring_buffer (tr, size, cpu_id); -if (ret <0 ) - ret = -ENOMEM ; - -return ret; +return __tracing_resize_ring_buffer (tr, size, cpu_id); }static void update_last_data (struct trace_array *tr)
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 41/154 USB: gadget: f_midi: f_midi_complete to call queue_work
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jill Donahue <[email protected]>
[ Upstream commit 4ab37fcb42832cdd3e9d5e50653285ca84d6686f ]
When using USB MIDI, a lock is attempted to be acquired twice through a re-entrant call to f_midi_transmit, causing a deadlock.
Fix it by using queue_work() to schedule the inner f_midi_transmit() via a high priority work queue from the completion handler.
--- drivers/usb/gadget/function/f_midi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/gadget/function/f_midi.c +1 -1
@@ -283,7 +283,7 @@ f_midi_complete(struct usb_ep *ep, struct usb_request *req)/* Our transmit completed. See if there's more to go. * f_midi_transmit eats req, don't queue it again. */ req->length =0 ; -f_midi_transmit (midi); +queue_work (system_highpri_wq, &midi->work);return ; }break ;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 42/154 sched_ext: Factor out move_task_between_dsqs() from scx_dispatch_from_dsq()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tejun Heo <[email protected]>
[ Upstream commit 8427acb6b5861d205abca7afa656a897bbae34b7 ]
Pure reorganization. No functional changes.
Stable-dep-of: 32966821574c ("sched_ext: Fix migration disabled handling in targeted dispatches")
--- kernel/sched/ext.c | 116 +++++++++++++++++++++++++++++---------------- 1 file changed, 75 insertions(+), 41 deletions(-)
kernel/sched/ext.c +75 -41
@@ -2397,6 +2397,73 @@ static inline bool task_can_run_on_remote_rq(struct task_struct *p, struct rq *rstatic inline bool consume_remote_task (struct rq *this_rq,struct task_struct *p,struct scx_dispatch_q *dsq,struct rq *task_rq) {return false; }#endif /* CONFIG_SMP */ +/** +* move_task_between_dsqs() - Move a task from one DSQ to another +* @p: target task +* @enq_flags: %SCX_ENQ_* +* @src_dsq: DSQ @p is currently on, must not be a local DSQ +* @dst_dsq: DSQ @p is being moved to, can be any DSQ +* +* Must be called with @p's task_rq and @src_dsq locked. If @dst_dsq is a local +* DSQ and @p is on a different CPU, @p will be migrated and thus its task_rq +* will change. As @p's task_rq is locked, this function doesn't need to use the +* holding_cpu mechanism. +* +* On return, @src_dsq is unlocked and only @p's new task_rq, which is the +* return value, is locked. +*/ +static struct rq *move_task_between_dsqs (struct task_struct *p,u64 enq_flags, +struct scx_dispatch_q *src_dsq, +struct scx_dispatch_q *dst_dsq) +{ +struct rq *src_rq =task_rq (p), *dst_rq; + +BUG_ON (src_dsq->id ==SCX_DSQ_LOCAL ); +lockdep_assert_held (&src_dsq->lock); +lockdep_assert_rq_held (src_rq); + +if (dst_dsq->id ==SCX_DSQ_LOCAL ) { + dst_rq = container_of(dst_dsq, struct rq, scx.local_dsq); +if (!task_can_run_on_remote_rq (p, dst_rq, true)) { + dst_dsq =find_global_dsq (p); + dst_rq = src_rq; + } + }else { +/* no need to migrate if destination is a non-local DSQ */ + dst_rq = src_rq; + } + +/* +* Move @p into $dst_dsq. If $dst_dsq is the local DSQ of a different +* CPU, @p will be migrated. +*/ +if (dst_dsq->id ==SCX_DSQ_LOCAL ) { +/* @p is going from a non-local DSQ to a local DSQ */ +if (src_rq == dst_rq) { +task_unlink_from_dsq (p, src_dsq); +move_local_task_to_local_dsq (p, enq_flags, + src_dsq, dst_rq); +raw_spin_unlock (&src_dsq->lock); + }else { +raw_spin_unlock (&src_dsq->lock); +move_remote_task_to_local_dsq (p, enq_flags, + src_rq, dst_rq); + } + }else { +/* +* @p is going from a non-local DSQ to a non-local DSQ. As +* $src_dsq is already locked, do an abbreviated dequeue. +*/ +task_unlink_from_dsq (p, src_dsq); + p->scx.dsq =NULL ; +raw_spin_unlock (&src_dsq->lock); + +dispatch_enqueue (dst_dsq, p, enq_flags); + } + +return dst_rq; +} +static bool consume_dispatch_q (struct rq *rq,struct scx_dispatch_q *dsq) {struct task_struct *p;
@@ -6134,7 +6201,7 @@ static bool scx_dispatch_from_dsq(struct bpf_iter_scx_dsq_kern *kit, u64 enq_flags) {struct scx_dispatch_q *src_dsq = kit->dsq, *dst_dsq; -struct rq *this_rq, *src_rq, *dst_rq, *locked_rq; +struct rq *this_rq, *src_rq, *locked_rq;bool dispatched = false;bool in_balance;unsigned long flags;
@@ -6180,51 +6247,18 @@ static bool scx_dispatch_from_dsq(struct bpf_iter_scx_dsq_kern *kit,/* @p is still on $src_dsq and stable, determine the destination */ dst_dsq =find_dsq_for_dispatch (this_rq, dsq_id, p); -if (dst_dsq->id ==SCX_DSQ_LOCAL ) { - dst_rq = container_of(dst_dsq, struct rq, scx.local_dsq); -if (!task_can_run_on_remote_rq (p, dst_rq, true)) { - dst_dsq =find_global_dsq (p); - dst_rq = src_rq; - } - }else { -/* no need to migrate if destination is a non-local DSQ */ - dst_rq = src_rq; - } -/* -* Move @p into $dst_dsq. If $dst_dsq is the local DSQ of a different -* CPU, @p will be migrated. +* Apply vtime and slice updates before moving so that the new time is +* visible before inserting into $dst_dsq. @p is still on $src_dsq but +* this is safe as we're locking it. */ -if (dst_dsq->id ==SCX_DSQ_LOCAL ) { -/* @p is going from a non-local DSQ to a local DSQ */ -if (src_rq == dst_rq) { -task_unlink_from_dsq (p, src_dsq); -move_local_task_to_local_dsq (p, enq_flags, - src_dsq, dst_rq); -raw_spin_unlock (&src_dsq->lock); - }else { -raw_spin_unlock (&src_dsq->lock); -move_remote_task_to_local_dsq (p, enq_flags, - src_rq, dst_rq); - locked_rq = dst_rq; - } - }else { -/* -* @p is going from a non-local DSQ to a non-local DSQ. As -* $src_dsq is already locked, do an abbreviated dequeue. -*/ -task_unlink_from_dsq (p, src_dsq); - p->scx.dsq =NULL ; -raw_spin_unlock (&src_dsq->lock); - -if (kit->cursor.flags & __SCX_DSQ_ITER_HAS_VTIME) - p->scx.dsq_vtime = kit->vtime; -dispatch_enqueue (dst_dsq, p, enq_flags); - } - +if (kit->cursor.flags & __SCX_DSQ_ITER_HAS_VTIME) + p->scx.dsq_vtime = kit->vtime;if (kit->cursor.flags & __SCX_DSQ_ITER_HAS_SLICE) p->scx.slice = kit->slice; +/* execute move */ + locked_rq =move_task_between_dsqs (p, enq_flags, src_dsq, dst_dsq); dispatched = true; out:if (in_balance) {
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 43/154 sched_ext: Fix migration disabled handling in targeted dispatches
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tejun Heo <[email protected]>
[ Upstream commit 32966821574cd2917bd60f2554f435fe527f4702 ]
A dispatch operation that can target a specific local DSQ - scx_bpf_dsq_move_to_local() or scx_bpf_dsq_move() - checks whether the task can be migrated to the target CPU using task_can_run_on_remote_rq(). If the task can't be migrated to the targeted CPU, it is bounced through a global DSQ.
task_can_run_on_remote_rq() assumes that the task is on a CPU that's different from the targeted CPU but the callers doesn't uphold the assumption and may call the function when the task is already on the target CPU. When such task has migration disabled, task_can_run_on_remote_rq() ends up returning %false incorrectly unnecessarily bouncing the task to a global DSQ.
Fix it by updating the callers to only call task_can_run_on_remote_rq() when the task is on a different CPU than the target CPU. As this is a bit subtle, for clarity and documentation:
- Make task_can_run_on_remote_rq() trigger SCHED_WARN_ON() if the task is on the same CPU as the target CPU.
- is_migration_disabled() test in task_can_run_on_remote_rq() cannot trigger if the task is on a different CPU than the target CPU as the preceding task_allowed_on_cpu() test should fail beforehand. Convert the test into SCHED_WARN_ON().
--- kernel/sched/ext.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-)
kernel/sched/ext.c +13 -4
@@ -2300,12 +2300,16 @@ static void move_remote_task_to_local_dsq(struct task_struct *p, u64 enq_flags,* * - The BPF scheduler is bypassed while the rq is offline and we can always say * no to the BPF scheduler initiated migrations while offline. +* +* The caller must ensure that @p and @rq are on different CPUs. */ static bool task_can_run_on_remote_rq (struct task_struct *p,struct rq *rq,bool trigger_error) {int cpu =cpu_of (rq); +SCHED_WARN_ON (task_cpu (p) == cpu); +/* * We don't require the BPF scheduler to avoid dispatching to offline * CPUs mostly for convenience but also because CPUs can go offline
@@ -2319,8 +2323,11 @@ static bool task_can_run_on_remote_rq(struct task_struct *p, struct rq *rq,return false; } -if (unlikely (is_migration_disabled (p))) -return false; +/* +* If @p has migration disabled, @p->cpus_ptr only contains its current +* CPU and the above task_allowed_on_cpu() test should have failed. +*/ +SCHED_WARN_ON (is_migration_disabled (p));if (!scx_rq_online (rq))return false;
@@ -2424,7 +2431,8 @@ static struct rq *move_task_between_dsqs(struct task_struct *p, u64 enq_flags,if (dst_dsq->id ==SCX_DSQ_LOCAL ) { dst_rq = container_of(dst_dsq, struct rq, scx.local_dsq); -if (!task_can_run_on_remote_rq (p, dst_rq, true)) { +if (src_rq != dst_rq && +unlikely (!task_can_run_on_remote_rq (p, dst_rq, true))) { dst_dsq =find_global_dsq (p); dst_rq = src_rq; }
@@ -2541,7 +2549,8 @@ static void dispatch_to_local_dsq(struct rq *rq, struct scx_dispatch_q *dst_dsq, }#ifdef CONFIG_SMP -if (unlikely (!task_can_run_on_remote_rq (p, dst_rq, true))) { +if (src_rq != dst_rq && +unlikely (!task_can_run_on_remote_rq (p, dst_rq, true))) {dispatch_enqueue (find_global_dsq (p), p, enq_flags |SCX_ENQ_CLEAR_OPSS );return ;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 44/154 ASoC: rockchip: i2s-tdm: fix shift config for SND_SOC_DAIFMT_DSP_[AB]
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Keeping <[email protected]>
[ Upstream commit 6b24e67b4056ba83b1e95e005b7e50fdb1cc6cf4 ]
Commit 2f45a4e289779 ("ASoC: rockchip: i2s_tdm: Fixup config for SND_SOC_DAIFMT_DSP_A/B") applied a partial change to fix the configuration for DSP A and DSP B formats.
The shift control also needs updating to set the correct offset for frame data compared to LRCK. Set the correct values.
--- sound/soc/rockchip/rockchip_i2s_tdm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
sound/soc/rockchip/rockchip_i2s_tdm.c +2 -2
@@ -451,11 +451,11 @@ static int rockchip_i2s_tdm_set_fmt(struct snd_soc_dai *cpu_dai,break ;case SND_SOC_DAIFMT_DSP_A : val =I2S_TXCR_TFS_TDM_PCM ; - tdm_val =TDM_SHIFT_CTRL (0 ); + tdm_val =TDM_SHIFT_CTRL (2 );break ;case SND_SOC_DAIFMT_DSP_B : val =I2S_TXCR_TFS_TDM_PCM ; - tdm_val =TDM_SHIFT_CTRL (2 ); + tdm_val =TDM_SHIFT_CTRL (4 );break ;default : ret = -EINVAL ;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 45/154 ASoC: SOF: ipc4-topology: Harden loops for looking up ALH copiers
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Ujfalusi <[email protected]>
[ Upstream commit 6fd60136d256b3b948333ebdb3835f41a95ab7ef ]
Other, non DAI copier widgets could have the same stream name (sname) as the ALH copier and in that case the copier->data is NULL, no alh_data is attached, which could lead to NULL pointer dereference.
We could check for this NULL pointer in sof_ipc4_prepare_copier_module() and avoid the crash, but a similar loop in sof_ipc4_widget_setup_comp_dai() will miscalculate the ALH device count, causing broken audio.
The correct fix is to harden the matching logic by making sure that the
1. widget is a DAI widget - so dai = w->private is valid
2. the dai (and thus the copier) is ALH copier
--- sound/soc/sof/ipc4-topology.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
sound/soc/sof/ipc4-topology.c +10 -2
@@ -671,10 +671,16 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) }list_for_each_entry (w, &sdev->widget_list, list) { -if (w->widget->sname && +struct snd_sof_dai *alh_dai; + +if (!WIDGET_IS_DAI (w->id) || !w->widget->sname ||strcmp (w->widget->sname, swidget->widget->sname))continue ; + alh_dai = w->private; +if (alh_dai->type !=SOF_DAI_INTEL_ALH ) +continue ; + blob->alh_cfg.device_count++; }
@@ -1973,11 +1979,13 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,list_for_each_entry (w, &sdev->widget_list, list) {u32 node_type; -if (w->widget->sname && +if (!WIDGET_IS_DAI (w->id) || !w->widget->sname ||strcmp (w->widget->sname, swidget->widget->sname))continue ; dai = w->private; +if (dai->type !=SOF_DAI_INTEL_ALH ) +continue ; alh_copier = (struct sof_ipc4_copier *)dai->private; alh_data = &alh_copier->data; node_type =SOF_IPC4_GET_NODE_TYPE (alh_data->gtw_cfg.node_id);
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 46/154 powerpc/code-patching: Disable KASAN report during patching via temporary mm
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christophe Leroy <[email protected]>
[ Upstream commit dc9c5166c3cb044f8a001e397195242fd6796eee ]
Erhard reports the following KASAN hit on Talos II (power9) with kernel 6.13:
[ 12.028126] ================================================================== [ 12.028198] BUG: KASAN: user-memory-access in copy_to_kernel_nofault+0x8c/0x1a0 [ 12.028260] Write of size 8 at addr 0000187e458f2000 by task systemd/1
[ 12.028346] CPU: 87 UID: 0 PID: 1 Comm: systemd Tainted: G T 6.13.0-P9-dirty #3
[ 12.028408] Tainted: [T]=RANDSTRUCT
[ 12.028446] Hardware name: T2P9D01 REV 1.01 POWER9 0x4e1202 opal:skiboot-bc106a0 PowerNV
[ 12.028500] Call Trace:
[ 12.028536] [c000000008dbf3b0] [c000000001656a48] dump_stack_lvl+0xbc/0x110 (unreliable)
[ 12.028609] [c000000008dbf3f0] [c0000000006e2fc8] print_report+0x6b0/0x708
[ 12.028666] [c000000008dbf4e0] [c0000000006e2454] kasan_report+0x164/0x300
[ 12.028725] [c000000008dbf600] [c0000000006e54d4] kasan_check_range+0x314/0x370
[ 12.028784] [c000000008dbf640] [c0000000006e6310] __kasan_check_write+0x20/0x40
[ 12.028842] [c000000008dbf660] [c000000000578e8c] copy_to_kernel_nofault+0x8c/0x1a0
[ 12.028902] [c000000008dbf6a0] [c0000000000acfe4] __patch_instructions+0x194/0x210
[ 12.028965] [c000000008dbf6e0] [c0000000000ade80] patch_instructions+0x150/0x590
[ 12.029026] [c000000008dbf7c0] [c0000000001159bc] bpf_arch_text_copy+0x6c/0xe0
[ 12.029085] [c000000008dbf800] [c000000000424250] bpf_jit_binary_pack_finalize+0x40/0xc0
[ 12.029147] [c000000008dbf830] [c000000000115dec] bpf_int_jit_compile+0x3bc/0x930
[ 12.029206] [c000000008dbf990] [c000000000423720] bpf_prog_select_runtime+0x1f0/0x280
[ 12.029266] [c000000008dbfa00] [c000000000434b18] bpf_prog_load+0xbb8/0x1370
[ 12.029324] [c000000008dbfb70] [c000000000436ebc] __sys_bpf+0x5ac/0x2e00
[ 12.029379] [c000000008dbfd00] [c00000000043a228] sys_bpf+0x28/0x40
[ 12.029435] [c000000008dbfd20] [c000000000038eb4] system_call_exception+0x334/0x610
[ 12.029497] [c000000008dbfe50] [c00000000000c270] system_call_vectored_common+0xf0/0x280
[ 12.029561] --- interrupt: 3000 at 0x3fff82f5cfa8
[ 12.029608] NIP: 00003fff82f5cfa8 LR: 00003fff82f5cfa8 CTR: 0000000000000000
[ 12.029660] REGS: c000000008dbfe80 TRAP: 3000 Tainted: G T (6.13.0-P9-dirty)
[ 12.029735] MSR: 900000000280f032 <SF,HV,VEC,VSX,EE,PR,FP,ME,IR,DR,RI> CR: 42004848 XER: 00000000
[ 12.029855] IRQMASK: 0
GPR00: 0000000000000169 00003fffdcf789a0 00003fff83067100 0000000000000005
GPR04: 00003fffdcf78a98 0000000000000090 0000000000000000 0000000000000008
GPR08: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
GPR12: 0000000000000000 00003fff836ff7e0 c000000000010678 0000000000000000
GPR16: 0000000000000000 0000000000000000 00003fffdcf78f28 00003fffdcf78f90
GPR20: 0000000000000000 0000000000000000 0000000000000000 00003fffdcf78f80
GPR24: 00003fffdcf78f70 00003fffdcf78d10 00003fff835c7239 00003fffdcf78bd8
GPR28: 00003fffdcf78a98 0000000000000000 0000000000000000 000000011f547580
[ 12.030316] NIP [00003fff82f5cfa8] 0x3fff82f5cfa8
[ 12.030361] LR [00003fff82f5cfa8] 0x3fff82f5cfa8
[ 12.030405] --- interrupt: 3000
[ 12.030444] ==================================================================Commit c28c15b6d28a ("powerpc/code-patching: Use temporary mm for Radix MMU") is inspired from x86 but unlike x86 is doesn't disable KASAN reports during patching. This wasn't a problem at the begining because __patch_mem() is not instrumented.
Commit 465cabc97b42 ("powerpc/code-patching: introduce patch_instructions()") use copy_to_kernel_nofault() to copy several instructions at once. But when using temporary mm the destination is not regular kernel memory but a kind of kernel-like memory located in user address space. Because it is not in kernel address space it is not covered by KASAN shadow memory. Since commit e4137f08816b ("mm, kasan, kmsan: instrument copy_from/to_kernel_nofault") KASAN reports bad accesses from copy_to_kernel_nofault(). Here a bad access to user memory is reported because KASAN detects the lack of shadow memory and the address is below TASK_SIZE.
Do like x86 in commit b3fd8e83ada0 ("x86/alternatives: Use temporary mm for text poking") and disable KASAN reports during patching when using temporary mm.
Close: https://lore.kernel.org/all/20250201151435.48400261@yea/
--- arch/powerpc/lib/code-patching.c | 2 ++ 1 file changed, 2 insertions(+)
arch/powerpc/lib/code-patching.c +2 -0
@@ -493,7 +493,9 @@ static int __do_patch_instructions_mm(u32 *addr, u32 *code, size_t len, bool rep orig_mm =start_using_temp_mm (patching_mm); +kasan_disable_current (); err =__patch_instructions (patch_addr, code, len, repeat_instr); +kasan_enable_current ();/* context synchronisation performed by __patch_instructions */ stop_using_temp_mm (patching_mm, orig_mm);
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 47/154 powerpc/64s: Rewrite __real_pte() and __rpte_to_hidx() as static inline
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christophe Leroy <[email protected]>
[ Upstream commit 61bcc752d1b81fde3cae454ff20c1d3c359df500 ]
Rewrite __real_pte() and __rpte_to_hidx() as static inline in order to avoid following warnings/errors when building with 4k page size:
CC arch/powerpc/mm/book3s64/hash_tlb.o
arch/powerpc/mm/book3s64/hash_tlb.c: In function 'hpte_need_flush':
arch/powerpc/mm/book3s64/hash_tlb.c:49:16: error: variable 'offset' set but not used [-Werror=unused-but-set-variable]
49 | int i, offset;
| ^~~~~~
CC arch/powerpc/mm/book3s64/hash_native.o
arch/powerpc/mm/book3s64/hash_native.c: In function 'native_flush_hash_range':
arch/powerpc/mm/book3s64/hash_native.c:782:29: error: variable 'index' set but not used [-Werror=unused-but-set-variable]
782 | unsigned long hash, index, hidx, shift, slot;
| ^~~~~
--- arch/powerpc/include/asm/book3s/64/hash-4k.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
arch/powerpc/include/asm/book3s/64/hash-4k.h +10 -2
@@ -77,9 +77,17 @@/* * With 4K page size the real_pte machinery is all nops. */ -#define __real_pte (e, p, o) ((real_pte_t){(e)}) +static inline real_pte_t __real_pte (pte_t pte,pte_t *ptep,int offset) +{ +return (real_pte_t ){pte}; +} +#define __rpte_to_pte (r) ((r).pte) -#define __rpte_to_hidx (r,index) (pte_val(__rpte_to_pte(r)) >> H_PAGE_F_GIX_SHIFT) + +static inline unsigned long __rpte_to_hidx (real_pte_t rpte,unsigned long index) +{ +return pte_val (__rpte_to_pte (rpte)) >>H_PAGE_F_GIX_SHIFT ; +}#define pte_iterate_hashed_subpages (rpte, psize, va, index, shift) \ do { \
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 48/154 ALSA: hda/realtek: Fixup ALC225 depop procedure
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kailang Yang <[email protected]>
[ Upstream commit 174448badb4409491bfba2e6b46f7aa078741c5e ]
Headset MIC will no function when power_save=0.
--- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+)
sound/pci/hda/patch_realtek.c +1 -0
@@ -3790,6 +3790,7 @@ static void alc225_init(struct hda_codec *codec) AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);msleep (75 ); +alc_update_coef_idx (codec,0x4a ,3 <<10 ,0 );alc_update_coefex_idx (codec,0x57 ,0x04 ,0x0007 ,0x4 );/* Hight power */ } }
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 22/154 Bluetooth: qca: Fix poor RF performance for WCN6855
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zijun Hu <[email protected]>
[ Upstream commit a2fad248947d702ed3dcb52b8377c1a3ae201e44 ]
For WCN6855, board ID specific NVM needs to be downloaded once board ID is available, but the default NVM is always downloaded currently.
The wrong NVM causes poor RF performance, and effects user experience for several types of laptop with WCN6855 on the market.
Fix by downloading board ID specific NVM if board ID is available.
--- drivers/bluetooth/btqca.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/bluetooth/btqca.c +3 -2
@@ -905,8 +905,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, "qca/msnv%02x.bin", rom_ver);break ;case QCA_WCN6855 : -snprintf (config.fwname,sizeof (config.fwname), -"qca/hpnv%02x.bin" , rom_ver); +qca_read_fw_board_id (hdev, &boardid); +qca_get_nvm_name_by_board (config.fwname,sizeof (config.fwname), +"hpnv" , soc_type, ver, rom_ver, boardid);break ;case QCA_WCN7850 : qca_get_nvm_name_by_board(config.fwname, sizeof(config.fwname),
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 49/154 powerpc/code-patching: Fix KASAN hit by not flagging text patching area as VM_ALLOC
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christophe Leroy <[email protected]>
[ Upstream commit d262a192d38e527faa5984629aabda2e0d1c4f54 ]
Erhard reported the following KASAN hit while booting his PowerMac G4 with a KASAN-enabled kernel 6.13-rc6:
BUG: KASAN: vmalloc-out-of-bounds in copy_to_kernel_nofault+0xd8/0x1c8 Write of size 8 at addr f1000000 by task chronyd/1293 CPU: 0 UID: 123 PID: 1293 Comm: chronyd Tainted: G W 6.13.0-rc6-PMacG4 #2 Tainted: [W]=WARN Hardware name: PowerMac3,6 7455 0x80010303 PowerMac Call Trace: [c2437590] [c1631a84] dump_stack_lvl+0x70/0x8c (unreliable) [c24375b0] [c0504998] print_report+0xdc/0x504 [c2437610] [c050475c] kasan_report+0xf8/0x108 [c2437690] [c0505a3c] kasan_check_range+0x24/0x18c [c24376a0] [c03fb5e4] copy_to_kernel_nofault+0xd8/0x1c8 [c24376c0] [c004c014] patch_instructions+0x15c/0x16c [c2437710] [c00731a8] bpf_arch_text_copy+0x60/0x7c [c2437730] [c0281168] bpf_jit_binary_pack_finalize+0x50/0xac [c2437750] [c0073cf4] bpf_int_jit_compile+0xb30/0xdec [c2437880] [c0280394] bpf_prog_select_runtime+0x15c/0x478 [c24378d0] [c1263428] bpf_prepare_filter+0xbf8/0xc14 [c2437990] [c12677ec] bpf_prog_create_from_user+0x258/0x2b4 [c24379d0] [c027111c] do_seccomp+0x3dc/0x1890 [c2437ac0] [c001d8e0] system_call_exception+0x2dc/0x420 [c2437f30] [c00281ac] ret_from_syscall+0x0/0x2c --- interrupt: c00 at 0x5a1274 NIP: 005a1274 LR: 006a3b3c CTR: 005296c8 REGS: c2437f40 TRAP: 0c00 Tainted: G W (6.13.0-rc6-PMacG4) MSR: 0200f932 <VEC,EE,PR,FP,ME,IR,DR,RI> CR: 24004422 XER: 00000000
GPR00: 00000166 af8f3fa0 a7ee3540 00000001 00000000 013b6500 005a5858 0200f932
GPR08: 00000000 00001fe9 013d5fc8 005296c8 2822244c 00b2fcd8 00000000 af8f4b57
GPR16: 00000000 00000001 00000000 00000000 00000000 00000001 00000000 00000002
GPR24: 00afdbb0 00000000 00000000 00000000 006e0004 013ce060 006e7c1c 00000001 NIP [005a1274] 0x5a1274
LR [006a3b3c] 0x6a3b3c
--- interrupt: c00
The buggy address belongs to the virtual mapping at
[f1000000, f1002000) created by:
text_area_cpu_up+0x20/0x190
The buggy address belongs to the physical page:
page: refcount:1 mapcount:0 mapping:00000000 index:0x0 pfn:0x76e30
flags: 0x80000000(zone=2)
raw: 80000000 00000000 00000122 00000000 00000000 00000000 ffffffff 00000001
raw: 00000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
f0ffff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
f0ffff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>f1000000: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
^
f1000080: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
f1000100: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
==================================================================f8 corresponds to KASAN_VMALLOC_INVALID which means the area is not initialised hence not supposed to be used yet.
Powerpc text patching infrastructure allocates a virtual memory area using get_vm_area() and flags it as VM_ALLOC. But that flag is meant to be used for vmalloc() and vmalloc() allocated memory is not supposed to be used before a call to __vmalloc_node_range() which is never called for that area.
That went undetected until commit e4137f08816b ("mm, kasan, kmsan:
instrument copy_from/to_kernel_nofault")
The area allocated by text_area_cpu_up() is not vmalloc memory, it is mapped directly on demand when needed by map_kernel_page(). There is no VM flag corresponding to such usage, so just pass no flag. That way the area will be unpoisonned and usable immediately.
--- arch/powerpc/lib/code-patching.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/lib/code-patching.c +1 -1
@@ -108,7 +108,7 @@ static int text_area_cpu_up(unsigned int cpu)unsigned long addr;int err; - area =get_vm_area (PAGE_SIZE ,VM_ALLOC ); + area =get_vm_area (PAGE_SIZE ,0 );if (!area) {WARN_ONCE (1 ,"Failed to create text area for cpu %d\n" , cpu);
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 50/154 ASoC: imx-audmix: remove cpu_mclk which is from cpu dai device
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shengjiu Wang <[email protected]>
[ Upstream commit 571b69f2f9b1ec7cf7d0e9b79e52115a87a869c4 ]
When defer probe happens, there may be below error:
platform 59820000.sai: Resources present before probing
The cpu_mclk clock is from the cpu dai device, if it is not released, then the cpu dai device probe will fail for the second time.
The cpu_mclk is used to get rate for rate constraint, rate constraint may be specific for each platform, which is not necessary for machine driver, so remove it.
--- sound/soc/fsl/imx-audmix.c | 31 ------------------------------- 1 file changed, 31 deletions(-)
sound/soc/fsl/imx-audmix.c +0 -31
@@ -23,7 +23,6 @@ struct imx_audmix {struct snd_soc_card card;struct platform_device *audmix_pdev;struct platform_device *out_pdev; -struct clk *cpu_mclk;int num_dai;struct snd_soc_dai_link *dai;int num_dai_conf;
@@ -32,34 +31,11 @@ struct imx_audmix {struct snd_soc_dapm_route *dapm_routes; }; -static const u32 imx_audmix_rates[] = { -8000 ,12000 ,16000 ,24000 ,32000 ,48000 ,64000 ,96000 , -}; - -static const struct snd_pcm_hw_constraint_list imx_audmix_rate_constraints = { - .count =ARRAY_SIZE (imx_audmix_rates), - .list = imx_audmix_rates, -}; -static int imx_audmix_fe_startup (struct snd_pcm_substream *substream) { -struct snd_soc_pcm_runtime *rtd =snd_soc_substream_to_rtd (substream); -struct imx_audmix *priv =snd_soc_card_get_drvdata (rtd->card);struct snd_pcm_runtime *runtime = substream->runtime; -struct device *dev = rtd->card->dev; -unsigned long clk_rate =clk_get_rate (priv->cpu_mclk);int ret; -if (clk_rate %24576000 ==0 ) { - ret =snd_pcm_hw_constraint_list (runtime,0 , -SNDRV_PCM_HW_PARAM_RATE , - &imx_audmix_rate_constraints); -if (ret <0 ) -return ret; - }else { -dev_warn (dev,"mclk may be not supported %lu\n" , clk_rate); - } - ret =snd_pcm_hw_constraint_minmax (runtime,SNDRV_PCM_HW_PARAM_CHANNELS ,1 ,8 );if (ret <0 )
@@ -325,13 +301,6 @@ static int imx_audmix_probe(struct platform_device *pdev) }put_device (&cpu_pdev->dev); - priv->cpu_mclk =devm_clk_get (&cpu_pdev->dev,"mclk1" ); -if (IS_ERR (priv->cpu_mclk)) { - ret =PTR_ERR (priv->cpu_mclk); -dev_err (&cpu_pdev->dev,"failed to get DAI mclk1: %d\n" , ret); -return ret; - } - priv->audmix_pdev = audmix_pdev; priv->out_pdev = cpu_pdev;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 51/154 vsock/virtio: fix variables initialization during resuming
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Junnan Wu <[email protected]>
[ Upstream commit 55eff109e76a14e5ed10c8c3c3978d20a35e2a4d ]
When executing suspend to ram twice in a row,
the rx_buf_nr and rx_buf_max_nr increase to three times vq->num_free. Then after virtqueue_get_buf and rx_buf_nr decreased
in function virtio_transport_rx_work,
the condition to fill rx buffer
(rx_buf_nr < rx_buf_max_nr / 2) will never be met.
It is because that rx_buf_nr and rx_buf_max_nr are initialized only in virtio_vsock_probe(),
but they should be reset whenever virtqueues are recreated, like after a suspend/resume.
Move the rx_buf_nr and rx_buf_max_nr initialization in virtio_vsock_vqs_init(), so we are sure that they are properly initialized, every time we initialize the virtqueues, either when we load the driver or after a suspend/resume.
To prevent erroneous atomic load operations on the queued_replies in the virtio_transport_send_pkt_work() function
which may disrupt the scheduling of vsock->rx_work
when transmitting reply-required socket packets,
this atomic variable must undergo synchronized initialization alongside the preceding two variables after a suspend/resume.
--- net/vmw_vsock/virtio_transport.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
net/vmw_vsock/virtio_transport.c +7 -3
@@ -670,6 +670,13 @@ static int virtio_vsock_vqs_init(struct virtio_vsock *vsock) };int ret; +mutex_lock (&vsock->rx_lock); + vsock->rx_buf_nr =0 ; + vsock->rx_buf_max_nr =0 ; +mutex_unlock (&vsock->rx_lock); + +atomic_set (&vsock->queued_replies,0 ); + ret =virtio_find_vqs (vdev,VSOCK_VQ_MAX , vsock->vqs, vqs_info,NULL );if (ret <0 )return ret;
@@ -779,9 +786,6 @@ static int virtio_vsock_probe(struct virtio_device *vdev) vsock->vdev = vdev; - vsock->rx_buf_nr =0 ; - vsock->rx_buf_max_nr =0 ; -atomic_set (&vsock->queued_replies,0 );mutex_init (&vsock->tx_lock);mutex_init (&vsock->rx_lock);
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 52/154 geneve: Fix use-after-free in geneve_find_dev().
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 9593172d93b9f91c362baec4643003dc29802929 ]
syzkaller reported a use-after-free in geneve_find_dev() [0] without repro.
geneve_configure() links struct geneve_dev.next to net_generic(net, geneve_net_id)->geneve_list.
The net here could differ from dev_net(dev) if IFLA_NET_NS_PID, IFLA_NET_NS_FD, or IFLA_TARGET_NETNSID is set.
When dev_net(dev) is dismantled, geneve_exit_batch_rtnl() finally calls unregister_netdevice_queue() for each dev in the netns, and later the dev is freed.
However, its geneve_dev.next is still linked to the backend UDP socket netns.
Then, use-after-free will occur when another geneve dev is created in the netns.
Let's call geneve_dellink() instead in geneve_destroy_tunnels().
[0]:
BUG: KASAN: slab-use-after-free in geneve_find_dev drivers/net/geneve.c:1295 [inline] BUG: KASAN: slab-use-after-free in geneve_configure+0x234/0x858 drivers/net/geneve.c:1343 Read of size 2 at addr ffff000054d6ee24 by task syz.1.4029/13441 CPU: 1 UID: 0 PID: 13441 Comm: syz.1.4029 Not tainted 6.13.0-g0ad9617c78ac #24 dc35ca22c79fb82e8e7bc5c9c9adafea898b1e3d Hardware name: linux,dummy-virt (DT) Call trace: show_stack+0x38/0x50 arch/arm64/kernel/stacktrace.c:466 (C) __dump_stack lib/dump_stack.c:94 [inline] dump_stack_lvl+0xbc/0x108 lib/dump_stack.c:120 print_address_description mm/kasan/report.c:378 [inline] print_report+0x16c/0x6f0 mm/kasan/report.c:489 kasan_report+0xc0/0x120 mm/kasan/report.c:602 __asan_report_load2_noabort+0x20/0x30 mm/kasan/report_generic.c:379 geneve_find_dev drivers/net/geneve.c:1295 [inline] geneve_configure+0x234/0x858 drivers/net/geneve.c:1343 geneve_newlink+0xb8/0x128 drivers/net/geneve.c:1634 rtnl_newlink_create+0x23c/0x868 net/core/rtnetlink.c:3795 __rtnl_newlink net/core/rtnetlink.c:3906 [inline] rtnl_newlink+0x1054/0x1630 net/core/rtnetlink.c:4021 rtnetlink_rcv_msg+0x61c/0x918 net/core/rtnetlink.c:6911 netlink_rcv_skb+0x1dc/0x398 net/netlink/af_netlink.c:2543 rtnetlink_rcv+0x34/0x50 net/core/rtnetlink.c:6938 netlink_unicast_kernel net/netlink/af_netlink.c:1322 [inline] netlink_unicast+0x618/0x838 net/netlink/af_netlink.c:1348 netlink_sendmsg+0x5fc/0x8b0 net/netlink/af_netlink.c:1892 sock_sendmsg_nosec net/socket.c:713 [inline] __sock_sendmsg net/socket.c:728 [inline] ____sys_sendmsg+0x410/0x6f8 net/socket.c:2568 ___sys_sendmsg+0x178/0x1d8 net/socket.c:2622 __sys_sendmsg net/socket.c:2654 [inline] __do_sys_sendmsg net/socket.c:2659 [inline] __se_sys_sendmsg net/socket.c:2657 [inline] __arm64_sys_sendmsg+0x12c/0x1c8 net/socket.c:2657 __invoke_syscall arch/arm64/kernel/syscall.c:35 [inline] invoke_syscall+0x90/0x278 arch/arm64/kernel/syscall.c:49 el0_svc_common+0x13c/0x250 arch/arm64/kernel/syscall.c:132 do_el0_svc+0x54/0x70 arch/arm64/kernel/syscall.c:151 el0_svc+0x4c/0xa8 arch/arm64/kernel/entry-common.c:744 el0t_64_sync_handler+0x78/0x108 arch/arm64/kernel/entry-common.c:762 el0t_64_sync+0x198/0x1a0 arch/arm64/kernel/entry.S:600 Allocated by task 13247: kasan_save_stack mm/kasan/common.c:47 [inline] kasan_save_track+0x30/0x68 mm/kasan/common.c:68 kasan_save_alloc_info+0x44/0x58 mm/kasan/generic.c:568 poison_kmalloc_redzone mm/kasan/common.c:377 [inline] __kasan_kmalloc+0x84/0xa0 mm/kasan/common.c:394 kasan_kmalloc include/linux/kasan.h:260 [inline] __do_kmalloc_node mm/slub.c:4298 [inline] __kmalloc_node_noprof+0x2a0/0x560 mm/slub.c:4304 __kvmalloc_node_noprof+0x9c/0x230 mm/util.c:645 alloc_netdev_mqs+0xb8/0x11a0 net/core/dev.c:11470 rtnl_create_link+0x2b8/0xb50 net/core/rtnetlink.c:3604 rtnl_newlink_create+0x19c/0x868 net/core/rtnetlink.c:3780 __rtnl_newlink net/core/rtnetlink.c:3906 [inline] rtnl_newlink+0x1054/0x1630 net/core/rtnetlink.c:4021 rtnetlink_rcv_msg+0x61c/0x918 net/core/rtnetlink.c:6911 netlink_rcv_skb+0x1dc/0x398 net/netlink/af_netlink.c:2543 rtnetlink_rcv+0x34/0x50 net/core/rtnetlink.c:6938 netlink_unicast_kernel net/netlink/af_netlink.c:1322 [inline] netlink_unicast+0x618/0x838 net/netlink/af_netlink.c:1348 netlink_sendmsg+0x5fc/0x8b0 net/netlink/af_netlink.c:1892 sock_sendmsg_nosec net/socket.c:713 [inline] __sock_sendmsg net/socket.c:728 [inline] ____sys_sendmsg+0x410/0x6f8 net/socket.c:2568 ___sys_sendmsg+0x178/0x1d8 net/socket.c:2622 __sys_sendmsg net/socket.c:2654 [inline] __do_sys_sendmsg net/socket.c:2659 [inline] __se_sys_sendmsg net/socket.c:2657 [inline] __arm64_sys_sendmsg+0x12c/0x1c8 net/socket.c:2657 __invoke_syscall arch/arm64/kernel/syscall.c:35 [inline] invoke_syscall+0x90/0x278 arch/arm64/kernel/syscall.c:49 el0_svc_common+0x13c/0x250 arch/arm64/kernel/syscall.c:132 do_el0_svc+0x54/0x70 arch/arm64/kernel/syscall.c:151 el0_svc+0x4c/0xa8 arch/arm64/kernel/entry-common.c:744 el0t_64_sync_handler+0x78/0x108 arch/arm64/kernel/entry-common.c:762 el0t_64_sync+0x198/0x1a0 arch/arm64/kernel/entry.S:600 Freed by task 45: kasan_save_stack mm/kasan/common.c:47 [inline] kasan_save_track+0x30/0x68 mm/kasan/common.c:68 kasan_save_free_info+0x58/0x70 mm/kasan/generic.c:582 poison_slab_object mm/kasan/common.c:247 [inline] __kasan_slab_free+0x48/0x68 mm/kasan/common.c:264 kasan_slab_free include/linux/kasan.h:233 [inline] slab_free_hook mm/slub.c:2353 [inline] slab_free mm/slub.c:4613 [inline] kfree+0x140/0x420 mm/slub.c:4761 kvfree+0x4c/0x68 mm/util.c:688 netdev_release+0x94/0xc8 net/core/net-sysfs.c:2065 device_release+0x98/0x1c0 kobject_cleanup lib/kobject.c:689 [inline] kobject_release lib/kobject.c:720 [inline] kref_put include/linux/kref.h:65 [inline] kobject_put+0x2b0/0x438 lib/kobject.c:737 netdev_run_todo+0xe5c/0xfc8 net/core/dev.c:11185 rtnl_unlock+0x20/0x38 net/core/rtnetlink.c:151 cleanup_net+0x4fc/0x8c0 net/core/net_namespace.c:648 process_one_work+0x700/0x1398 kernel/workqueue.c:3236 process_scheduled_works kernel/workqueue.c:3317 [inline] worker_thread+0x8c4/0xe10 kernel/workqueue.c:3398 kthread+0x4bc/0x608 kernel/kthread.c:464 ret_from_fork+0x10/0x20 arch/arm64/kernel/entry.S:862 The buggy address belongs to the object at ffff000054d6e000 which belongs to the cache kmalloc-cg-4k of size 4096
The buggy address is located 3620 bytes inside of
freed 4096-byte region [ffff000054d6e000, ffff000054d6f000)
The buggy address belongs to the physical page: page: refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x94d68
head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0 memcg:ffff000016276181
flags: 0x3fffe0000000040(head|node=0|zone=0|lastcpupid=0x1ffff)page_type: f5(slab)
raw: 03fffe0000000040 ffff0000c000f500 dead000000000122 0000000000000000 raw: 0000000000000000 0000000000040004 00000001f5000000 ffff000016276181
head: 03fffe0000000040 ffff0000c000f500 dead000000000122 0000000000000000
head: 0000000000000000 0000000000040004 00000001f5000000 ffff000016276181
head: 03fffe0000000003 fffffdffc1535a01 ffffffffffffffff 0000000000000000
head: 0000000000000008 0000000000000000 00000000ffffffff 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff000054d6ed00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff000054d6ed80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff000054d6ee00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff000054d6ee80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff000054d6ef00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb--- drivers/net/geneve.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-)
drivers/net/geneve.c +3 -8
@@ -1907,16 +1907,11 @@ static void geneve_destroy_tunnels(struct net *net, struct list_head *head)/* gather any geneve devices that were moved into this ns */ for_each_netdev_safe (net, dev, aux)if (dev->rtnl_link_ops == &geneve_link_ops) -unregister_netdevice_queue (dev, head); +geneve_dellink (dev, head);/* now gather any other geneve devices that were created in this ns */ -list_for_each_entry_safe (geneve, next, &gn->geneve_list, next) { -/* If geneve->dev is in the same netns, it was already added -* to the list by the previous loop. -*/ -if (!net_eq (dev_net (geneve->dev), net)) -unregister_netdevice_queue (geneve->dev, head); - } +list_for_each_entry_safe (geneve, next, &gn->geneve_list, next) +geneve_dellink (geneve->dev, head); } static void __net_exit geneve_exit_batch_rtnl(struct list_head *net_list,
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 53/154 ALSA: hda/cirrus: Correct the full scale volume set logic
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vitaly Rodionov <[email protected]>
[ Upstream commit 08b613b9e2ba431db3bd15cb68ca72472a50ef5c ]
This patch corrects the full-scale volume setting logic. On certain platforms, the full-scale volume bit is required. The current logic mistakenly sets this bit and incorrectly clears reserved bit 0, causing the headphone output to be muted.
--- sound/pci/hda/patch_cs8409-tables.c | 6 +++--- sound/pci/hda/patch_cs8409.c | 20 +++++++++++--------- sound/pci/hda/patch_cs8409.h | 5 +++-- 3 files changed, 17 insertions(+), 14 deletions(-)
sound/pci/hda/patch_cs8409-tables.c +3 -3
@@ -121,7 +121,7 @@ static const struct cs8409_i2c_param cs42l42_init_reg_seq[] = { { CS42L42_MIXER_CHA_VOL, 0x3F }, { CS42L42_MIXER_CHB_VOL, 0x3F }, { CS42L42_MIXER_ADC_VOL, 0x3f }, - { CS42L42_HP_CTL, 0x03 }, + { CS42L42_HP_CTL, 0x0D }, { CS42L42_MIC_DET_CTL1, 0xB6 }, { CS42L42_TIPSENSE_CTL, 0xC2 }, { CS42L42_HS_CLAMP_DISABLE, 0x01 },
@@ -315,7 +315,7 @@ static const struct cs8409_i2c_param dolphin_c0_init_reg_seq[] = { { CS42L42_ASP_TX_SZ_EN, 0x01 }, { CS42L42_PWR_CTL1, 0x0A }, { CS42L42_PWR_CTL2, 0x84 }, - { CS42L42_HP_CTL, 0x03 }, + { CS42L42_HP_CTL, 0x0D }, { CS42L42_MIXER_CHA_VOL, 0x3F }, { CS42L42_MIXER_CHB_VOL, 0x3F }, { CS42L42_MIXER_ADC_VOL, 0x3f },
@@ -371,7 +371,7 @@ static const struct cs8409_i2c_param dolphin_c1_init_reg_seq[] = { { CS42L42_ASP_TX_SZ_EN, 0x00 }, { CS42L42_PWR_CTL1, 0x0E }, { CS42L42_PWR_CTL2, 0x84 }, - { CS42L42_HP_CTL, 0x01 }, + { CS42L42_HP_CTL, 0x0D }, { CS42L42_MIXER_CHA_VOL, 0x3F }, { CS42L42_MIXER_CHB_VOL, 0x3F }, { CS42L42_MIXER_ADC_VOL, 0x3f },
sound/pci/hda/patch_cs8409.c +11 -9
@@ -876,7 +876,7 @@ static void cs42l42_resume(struct sub_codec *cs42l42) { CS42L42_DET_INT_STATUS2, 0x00 }, { CS42L42_TSRS_PLUG_STATUS, 0x00 }, }; -int fsv_old, fsv_new; +unsigned int fsv;/* Bring CS42L42 out of Reset */ spec->gpio_data =snd_hda_codec_read (codec,CS8409_PIN_AFG ,0 ,AC_VERB_GET_GPIO_DATA ,0 );
@@ -893,13 +893,15 @@ static void cs42l42_resume(struct sub_codec *cs42l42)/* Clear interrupts, by reading interrupt status registers */ cs8409_i2c_bulk_read (cs42l42, irq_regs,ARRAY_SIZE (irq_regs)); - fsv_old =cs8409_i2c_read (cs42l42,CS42L42_HP_CTL ); -if (cs42l42->full_scale_vol ==CS42L42_FULL_SCALE_VOL_0DB ) - fsv_new = fsv_old & ~CS42L42_FULL_SCALE_VOL_MASK ; -else - fsv_new = fsv_old &CS42L42_FULL_SCALE_VOL_MASK ; -if (fsv_new != fsv_old) -cs8409_i2c_write (cs42l42,CS42L42_HP_CTL , fsv_new); + fsv =cs8409_i2c_read (cs42l42,CS42L42_HP_CTL ); +if (cs42l42->full_scale_vol) { +// Set the full scale volume bit + fsv |=CS42L42_FULL_SCALE_VOL_MASK ; +cs8409_i2c_write (cs42l42,CS42L42_HP_CTL , fsv); + } +// Unmute analog channels A and B + fsv = (fsv & ~CS42L42_ANA_MUTE_AB ); +cs8409_i2c_write (cs42l42,CS42L42_HP_CTL , fsv);/* we have to explicitly allow unsol event handling even during the * resume phase so that the jack event is processed properly
@@ -920,7 +922,7 @@ static void cs42l42_suspend(struct sub_codec *cs42l42) { CS42L42_MIXER_CHA_VOL, 0x3F }, { CS42L42_MIXER_ADC_VOL, 0x3F }, { CS42L42_MIXER_CHB_VOL, 0x3F }, - { CS42L42_HP_CTL, 0x0F }, + { CS42L42_HP_CTL, 0x0D }, { CS42L42_ASP_RX_DAI0_EN, 0x00 }, { CS42L42_ASP_CLK_CFG, 0x00 }, { CS42L42_PWR_CTL1, 0xFE },
sound/pci/hda/patch_cs8409.h +3 -2
@@ -230,9 +230,10 @@ enum cs8409_coefficient_index_registers {#define CS42L42_PDN_TIMEOUT_US (250000)#define CS42L42_PDN_SLEEP_US (2000)#define CS42L42_INIT_TIMEOUT_MS (45) +#define CS42L42_ANA_MUTE_AB (0x0C)#define CS42L42_FULL_SCALE_VOL_MASK (2) -#define CS42L42_FULL_SCALE_VOL_0DB (1) -#define CS42L42_FULL_SCALE_VOL_MINUS6DB (0) +#define CS42L42_FULL_SCALE_VOL_0DB (0) +#define CS42L42_FULL_SCALE_VOL_MINUS6DB (1)/* Dell BULLSEYE / WARLOCK / CYBORG Specific Definitions */
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 23/154 Input: serio - define serio_pause_rx guard to pause and resume serio ports
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <[email protected]>
[ Upstream commit 0e45a09a1da0872786885c505467aab8fb29b5b4 ]
serio_pause_rx() and serio_continue_rx() are usually used together to temporarily stop receiving interrupts/data for a given serio port. Define "serio_pause_rx" guard for this so that the port is always resumed once critical section is over.
Example:
scoped_guard(serio_pause_rx, elo->serio) {
elo->expected_packet = toupper(packet[0]);
init_completion(&elo->cmd_done);
}Stable-dep-of: 08bd5b7c9a24 ("Input: synaptics - fix crash when enabling pass-through port")
--- include/linux/serio.h | 3 +++ 1 file changed, 3 insertions(+)
include/linux/serio.h +3 -0
@@ -6,6 +6,7 @@#define _SERIO_H +#include <linux/cleanup.h> #include <linux/types.h> #include <linux/interrupt.h> #include <linux/list.h>
@@ -161,4 +162,6 @@ static inline void serio_continue_rx(struct serio *serio)spin_unlock_irq (&serio->lock); } +DEFINE_GUARD(serio_pause_rx, struct serio *, serio_pause_rx(_T), serio_continue_rx(_T)) +#endif
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 24/154 Input: synaptics - fix crash when enabling pass-through port
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <[email protected]>
[ Upstream commit 08bd5b7c9a2401faabdaa1472d45c7de0755fd7e ]
When enabling a pass-through port an interrupt might come before psmouse driver binds to the pass-through port. However synaptics sub-driver tries to access psmouse instance presumably associated with the pass-through port to figure out if only 1 byte of response or entire protocol packet needs to be forwarded to the pass-through port and may crash if psmouse instance has not been attached to the port yet.
Fix the crash by introducing open() and close() methods for the port and check if the port is open before trying to access psmouse instance. Because psmouse calls serio_open() only after attaching psmouse instance to serio port instance this prevents the potential crash.
--- drivers/input/mouse/synaptics.c | 56 ++++++++++++++++++++++++--------- drivers/input/mouse/synaptics.h | 1 + 2 files changed, 43 insertions(+), 14 deletions(-)
drivers/input/mouse/synaptics.c +42 -14
@@ -667,23 +667,50 @@ static void synaptics_pt_stop(struct serio *serio)serio_continue_rx (parent->ps2dev.serio); } +static int synaptics_pt_open (struct serio *serio) +{ +struct psmouse *parent =psmouse_from_serio (serio->parent); +struct synaptics_data *priv = parent->private; + +guard (serio_pause_rx)(parent->ps2dev.serio); + priv->pt_port_open = true; + +return 0 ; +} + +static void synaptics_pt_close (struct serio *serio) +{ +struct psmouse *parent =psmouse_from_serio (serio->parent); +struct synaptics_data *priv = parent->private; + +guard (serio_pause_rx)(parent->ps2dev.serio); + priv->pt_port_open = false; +} +static int synaptics_is_pt_packet (u8 *buf) {return (buf[0 ] &0xFC ) ==0x84 && (buf[3 ] &0xCC ) ==0xC4 ; } -static void synaptics_pass_pt_packet (struct serio *ptport,u8 *packet) +static void synaptics_pass_pt_packet (struct synaptics_data *priv,u8 *packet) { -struct psmouse *child =psmouse_from_serio (ptport); +struct serio *ptport; -if (child && child->state ==PSMOUSE_ACTIVATED ) { -serio_interrupt (ptport, packet[1 ],0 ); -serio_interrupt (ptport, packet[4 ],0 ); -serio_interrupt (ptport, packet[5 ],0 ); -if (child->pktsize ==4 ) -serio_interrupt (ptport, packet[2 ],0 ); - }else { -serio_interrupt (ptport, packet[1 ],0 ); + ptport = priv->pt_port; +if (!ptport) +return ; + +serio_interrupt (ptport, packet[1 ],0 ); + +if (priv->pt_port_open) { +struct psmouse *child =psmouse_from_serio (ptport); + +if (child->state ==PSMOUSE_ACTIVATED ) { +serio_interrupt (ptport, packet[4 ],0 ); +serio_interrupt (ptport, packet[5 ],0 ); +if (child->pktsize ==4 ) +serio_interrupt (ptport, packet[2 ],0 ); + } } }
@@ -722,6 +749,8 @@ static void synaptics_pt_create(struct psmouse *psmouse) serio->write = synaptics_pt_write; serio->start = synaptics_pt_start; serio->stop = synaptics_pt_stop; + serio->open = synaptics_pt_open; + serio->close = synaptics_pt_close; serio->parent = psmouse->ps2dev.serio; psmouse->pt_activate = synaptics_pt_activate;
@@ -1218,11 +1247,10 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse)if (SYN_CAP_PASS_THROUGH (priv->info.capabilities) &&synaptics_is_pt_packet (psmouse->packet)) { -if (priv->pt_port) -synaptics_pass_pt_packet (priv->pt_port, - psmouse->packet); - }else +synaptics_pass_pt_packet (priv, psmouse->packet); + }else {synaptics_process_packet (psmouse); + }return PSMOUSE_FULL_PACKET ; }
drivers/input/mouse/synaptics.h +1 -0
@@ -188,6 +188,7 @@ struct synaptics_data {bool disable_gesture;/* disable gestures */ struct serio *pt_port;/* Pass-through serio port */ +bool pt_port_open;/* * Last received Advanced Gesture Mode (AGM) packet. An AGM packet
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 25/154 ASoC: renesas: rz-ssi: Terminate all the DMA transactions
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Claudiu Beznea <[email protected]>
[ Upstream commit 541011dc2d7c4c82523706f726f422a5e23cc86f ]
The stop trigger invokes rz_ssi_stop() and rz_ssi_stream_quit().
- The purpose of rz_ssi_stop() is to disable TX/RX, terminate DMA transactions, and set the controller to idle.
- The purpose of rz_ssi_stream_quit() is to reset the substream-specific software data by setting strm->running and strm->substream appropriately.
The function rz_ssi_is_stream_running() checks if both strm->substream and strm->running are valid and returns true if so. Its implementation is as follows:
static inline bool rz_ssi_is_stream_running(struct rz_ssi_stream *strm)
{
return strm->substream && strm->running;
}When the controller is configured in full-duplex mode (with both playback and capture active), the rz_ssi_stop() function does not modify the controller settings when called for the first substream in the full-duplex setup. Instead, it simply sets strm->running = 0 and returns if the companion substream is still running. The following code illustrates this:
static int rz_ssi_stop(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
{
strm->running = 0;
if (rz_ssi_is_stream_running(&ssi->playback) ||
rz_ssi_is_stream_running(&ssi->capture))
return 0;
// ...
}The controller settings, along with the DMA termination (for the last stopped substream), are only applied when the last substream in the full-duplex setup is stopped.
While applying the controller settings only when the last substream stops is not problematic, terminating the DMA operations for only one substream causes failures when starting and stopping full-duplex operations multiple times in a loop.
To address this issue, call dmaengine_terminate_async() for both substreams involved in the full-duplex setup when the last substream in the setup is stopped.
--- sound/soc/sh/rz-ssi.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
sound/soc/sh/rz-ssi.c +6 -2
@@ -416,8 +416,12 @@ static int rz_ssi_stop(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)rz_ssi_reg_mask_setl (ssi,SSICR ,SSICR_TEN |SSICR_REN ,0 );/* Cancel all remaining DMA transactions */ -if (rz_ssi_is_dma_enabled (ssi)) -dmaengine_terminate_async (strm->dma_ch); +if (rz_ssi_is_dma_enabled (ssi)) { +if (ssi->playback.dma_ch) +dmaengine_terminate_async (ssi->playback.dma_ch); +if (ssi->capture.dma_ch) +dmaengine_terminate_async (ssi->capture.dma_ch); + }rz_ssi_set_idle (ssi);
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 26/154 ASoC: renesas: rz-ssi: Add a check for negative sample_space
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
[ Upstream commit 82a0a3e6f8c02b3236b55e784a083fa4ee07c321 ]
My static checker rule complains about this code. The concern is that if "sample_space" is negative then the "sample_space >= runtime->channels" condition will not work as intended because it will be type promoted to a high unsigned int value.
strm->fifo_sample_size is SSI_FIFO_DEPTH (32). The SSIFSR_TDC_MASK is 0x3f. Without any further context it does seem like a reasonable warning and it can't hurt to add a check for negatives.
--- sound/soc/sh/rz-ssi.c | 2 ++ 1 file changed, 2 insertions(+)
sound/soc/sh/rz-ssi.c +2 -0
@@ -528,6 +528,8 @@ static int rz_ssi_pio_send(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) sample_space = strm->fifo_sample_size; ssifsr =rz_ssi_reg_readl (ssi,SSIFSR ); sample_space -= (ssifsr >>SSIFSR_TDC_SHIFT ) &SSIFSR_TDC_MASK ; +if (sample_space <0 ) +return -EINVAL ;/* Only add full frames at a time */ while (frames_left && (sample_space >= runtime->channels)) {
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 27/154 PCI: Make pcim_request_all_regions() a public function
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Philipp Stanner <[email protected]>
[ Upstream commit d9d959c36bec59f11c0eb6b5308729e3c4901b5e ]
In order to remove the deprecated function pcim_iomap_regions_request_all(), a few drivers need an interface to request all BARs a PCI device offers.
Make pcim_request_all_regions() a public interface.
Stable-dep-of: d555ed45a5a1 ("PCI: Restore original INTX_DISABLE bit by pcim_intx()")
--- drivers/pci/devres.c | 3 ++- include/linux/pci.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-)
drivers/pci/devres.c +2 -1
@@ -939,7 +939,7 @@ static void pcim_release_all_regions(struct pci_dev *pdev)* desired, release individual regions with pcim_release_region() or all of * them at once with pcim_release_all_regions(). */ -static int pcim_request_all_regions (struct pci_dev *pdev,const char *name) +int pcim_request_all_regions (struct pci_dev *pdev,const char *name) {int ret;int bar;
@@ -957,6 +957,7 @@ static int pcim_request_all_regions(struct pci_dev *pdev, const char *name)return ret; } +EXPORT_SYMBOL (pcim_request_all_regions);/** * pcim_iomap_regions_request_all - Request all BARs and iomap specified ones
include/linux/pci.h +1 -0
@@ -2293,6 +2293,7 @@ static inline void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) { }#endif +int pcim_request_all_regions (struct pci_dev *pdev,const char *name);void __iomem *pcim_iomap (struct pci_dev *pdev,int bar,unsigned long maxlen);void __iomem *pcim_iomap_region (struct pci_dev *pdev,int bar,const char *name);
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 28/154 PCI: Export pci_intx_unmanaged() and pcim_intx()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Philipp Stanner <[email protected]>
[ Upstream commit f546e8033d8f3e45d49622f04ca2fde650b80f6d ]
pci_intx() is a hybrid function which sometimes performs devres operations, depending on whether pcim_enable_device() has been used to enable the pci_dev. This sometimes-managed nature of the function is problematic. Notably, it causes the function to allocate under some circumstances which makes it unusable from interrupt context.
Export pcim_intx() (which is always managed) and rename __pcim_intx() (which is never managed) to pci_intx_unmanaged() and export it as well.
Then all callers of pci_intx() can be ported to the version they need, depending whether they use pci_enable_device() or pcim_enable_device().
Stable-dep-of: d555ed45a5a1 ("PCI: Restore original INTX_DISABLE bit by pcim_intx()")
--- drivers/pci/devres.c | 24 +++--------------------- drivers/pci/pci.c | 29 +++++++++++++++++++++++++++++ include/linux/pci.h | 2 ++ 3 files changed, 34 insertions(+), 21 deletions(-)
drivers/pci/devres.c +3 -21
@@ -411,31 +411,12 @@ static inline bool mask_contains_bar(int mask, int bar)return mask &BIT (bar); } -/* -* This is a copy of pci_intx() used to bypass the problem of recursive -* function calls due to the hybrid nature of pci_intx(). -*/ -static void __pcim_intx (struct pci_dev *pdev,int enable) -{ -u16 pci_command, new; - -pci_read_config_word (pdev,PCI_COMMAND , &pci_command); - -if (enable) - new = pci_command & ~PCI_COMMAND_INTX_DISABLE ; -else - new = pci_command |PCI_COMMAND_INTX_DISABLE ; - -if (new != pci_command) -pci_write_config_word (pdev,PCI_COMMAND , new); -} -static void pcim_intx_restore (struct device *dev,void *data) {struct pci_dev *pdev =to_pci_dev (dev);struct pcim_intx_devres *res = data; -__pcim_intx (pdev, res->orig_intx); +pci_intx_unmanaged (pdev, res->orig_intx); }static struct pcim_intx_devres *get_or_create_intx_devres (struct device *dev)
@@ -472,10 +453,11 @@ int pcim_intx(struct pci_dev *pdev, int enable)return -ENOMEM ; res->orig_intx = !enable; -__pcim_intx (pdev, enable); +pci_intx_unmanaged (pdev, enable);return 0 ; } +EXPORT_SYMBOL_GPL (pcim_intx);static void pcim_disable_device (void *pdev_raw) {
drivers/pci/pci.c +29 -0
@@ -4480,6 +4480,35 @@ void pci_disable_parity(struct pci_dev *dev) } } +/** +* pci_intx_unmanaged - enables/disables PCI INTx for device dev, +* unmanaged version +* @pdev: the PCI device to operate on +* @enable: boolean: whether to enable or disable PCI INTx +* +* Enables/disables PCI INTx for device @pdev +* +* This function behavios identically to pci_intx(), but is never managed with +* devres. +*/ +void pci_intx_unmanaged (struct pci_dev *pdev,int enable) +{ +u16 pci_command, new; + +pci_read_config_word (pdev,PCI_COMMAND , &pci_command); + +if (enable) + new = pci_command & ~PCI_COMMAND_INTX_DISABLE ; +else + new = pci_command |PCI_COMMAND_INTX_DISABLE ; + +if (new == pci_command) +return ; + +pci_write_config_word (pdev,PCI_COMMAND , new); +} +EXPORT_SYMBOL_GPL (pci_intx_unmanaged); +/** * pci_intx - enables/disables PCI INTx for device dev * @pdev: the PCI device to operate on
include/linux/pci.h +2 -0
@@ -1353,6 +1353,7 @@ int __must_check pcim_set_mwi(struct pci_dev *dev);int pci_try_set_mwi (struct pci_dev *dev);void pci_clear_mwi (struct pci_dev *dev);void pci_disable_parity (struct pci_dev *dev); +void pci_intx_unmanaged (struct pci_dev *pdev,int enable);void pci_intx (struct pci_dev *dev,int enable);bool pci_check_and_mask_intx (struct pci_dev *dev);bool pci_check_and_unmask_intx (struct pci_dev *dev);
@@ -2293,6 +2294,7 @@ static inline void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) { }#endif +int pcim_intx (struct pci_dev *pdev,int enabled);int pcim_request_all_regions (struct pci_dev *pdev,const char *name);void __iomem *pcim_iomap (struct pci_dev *pdev,int bar,unsigned long maxlen); void __iomem *pcim_iomap_region(struct pci_dev *pdev, int bar,
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 19/154 drm/amd/display: update dcn351 used clock offset
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Charlene Liu <[email protected]>
[ Upstream commit a1fc2837f4960e84e9375e12292584ad2ae472da ]
[why]
hw register offset delta
Stable-dep-of: f88192d2335b ("drm/amd/display: Correct register address in dcn35")
--- .../gpu/drm/amd/display/dc/clk_mgr/Makefile | 2 +- .../gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c | 5 +- .../display/dc/clk_mgr/dcn35/dcn351_clk_mgr.c | 140 ++++++++++++++++++ .../display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 132 +++++++++++++---- .../display/dc/clk_mgr/dcn35/dcn35_clk_mgr.h | 4 + .../amd/display/dc/inc/hw/clk_mgr_internal.h | 59 ++++++++ 6 files changed, 308 insertions(+), 34 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn351_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile +1 -1
@@ -174,7 +174,7 @@ AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN32) ############################################################################### # DCN35 ############################################################################### -CLK_MGR_DCN35 = dcn35_smu.o dcn35_clk_mgr.o +CLK_MGR_DCN35 = dcn35_smu.o dcn351_clk_mgr.o dcn35_clk_mgr.o AMD_DAL_CLK_MGR_DCN35 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn35/,$(CLK_MGR_DCN35))
drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c +4 -1
@@ -355,8 +355,11 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *pBREAK_TO_DEBUGGER ();return NULL ; } +if (ctx->dce_version ==DCN_VERSION_3_51 ) +dcn351_clk_mgr_construct (ctx, clk_mgr, pp_smu, dccg); +else +dcn35_clk_mgr_construct (ctx, clk_mgr, pp_smu, dccg); -dcn35_clk_mgr_construct (ctx, clk_mgr, pp_smu, dccg);return &clk_mgr->base.base; }break ;
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn351_clk_mgr.c new file +140 -0
140 lines not on this page · raw message
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +100 -32
185 lines not on this page · raw message
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.h +4 -0
@@ -60,4 +60,8 @@ void dcn35_clk_mgr_construct(struct dc_context *ctx,void dcn35_clk_mgr_destroy (struct clk_mgr_internal *clk_mgr_int); +void dcn351_clk_mgr_construct (struct dc_context *ctx, +struct clk_mgr_dcn35 *clk_mgr, +struct pp_smu_funcs *pp_smu, +struct dccg *dccg);#endif //__DCN35_CLK_MGR_H__
drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h +59 -0
82 lines not on this page · raw message
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 55/154 ALSA: seq: Drop UMP events when no UMP-conversion is set
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
[ Upstream commit e77aa4b2eaa7fb31b2a7a50214ecb946b2a8b0f6 ]
When a destination client is a user client in the legacy MIDI mode and it sets the no-UMP-conversion flag, currently the all UMP events are still passed as-is. But this may confuse the user-space, because the event packet size is different from the legacy mode.
Since we cannot handle UMP events in user clients unless it's running in the UMP client mode, we should filter out those events instead of accepting blindly. This patch addresses it by slightly adjusting the conditions for UMP event handling at the event delivery time.
--- sound/core/seq/seq_clientmgr.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
sound/core/seq/seq_clientmgr.c +9 -3
@@ -678,12 +678,18 @@ static int snd_seq_deliver_single_event(struct snd_seq_client *client, dest_port->time_real);#if IS_ENABLED (CONFIG_SND_SEQ_UMP ) -if (!(dest->filter &SNDRV_SEQ_FILTER_NO_CONVERT )) { -if (snd_seq_ev_is_ump (event)) { +if (snd_seq_ev_is_ump (event)) { +if (!(dest->filter &SNDRV_SEQ_FILTER_NO_CONVERT )) { result =snd_seq_deliver_from_ump (client, dest, dest_port, event, atomic, hop); goto __skip; - }else if (snd_seq_client_is_ump (dest)) { + }else if (dest->type ==USER_CLIENT && + !snd_seq_client_is_ump (dest)) { + result =0 ;// drop the event + goto __skip; + } + }else if (snd_seq_client_is_ump (dest)) { +if (!(dest->filter &SNDRV_SEQ_FILTER_NO_CONVERT )) { result =snd_seq_deliver_to_ump (client, dest, dest_port, event, atomic, hop); goto __skip;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 64/154 net: pse-pd: pd692x0: Fix power limit retrieval
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kory Maincent <[email protected]>
[ Upstream commit f6093c5ec74d5cc495f89bd359253d9c738d04d9 ]
Fix incorrect data offset read in the pd692x0_pi_get_pw_limit callback. The issue was previously unnoticed as it was only used by the regulator API and not thoroughly tested, since the PSE is mainly controlled via ethtool.
The function became actively used by ethtool after commit 3e9dbfec4998 ("net: pse-pd: Split ethtool_get_status into multiple callbacks"), which led to the discovery of this issue.
Fix it by using the correct data offset.
--- drivers/net/pse-pd/pd692x0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/pse-pd/pd692x0.c +1 -1
@@ -1012,7 +1012,7 @@ static int pd692x0_pi_get_pw_limit(struct pse_controller_dev *pcdev,if (ret <0 )return ret; -return pd692x0_pi_get_pw_from_table (buf.data[2 ], buf.data[3 ]); +return pd692x0_pi_get_pw_from_table (buf.data[0 ], buf.data[1 ]); } static int pd692x0_pi_set_pw_limit(struct pse_controller_dev *pcdev,
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 65/154 gtp: Suppress list corruption splat in gtp_net_exit_batch_rtnl().
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 4ccacf86491d33d2486b62d4d44864d7101b299d ]
Brad Spengler reported the list_del() corruption splat in gtp_net_exit_batch_rtnl(). [0]
Commit eb28fd76c0a0 ("gtp: Destroy device along with udp socket's netns dismantle.") added the for_each_netdev() loop in gtp_net_exit_batch_rtnl() to destroy devices in each netns as done in geneve and ip tunnels.
However, this could trigger ->dellink() twice for the same device during ->exit_batch_rtnl().
Say we have two netns A & B and gtp device B that resides in netns B but whose UDP socket is in netns A.
1. cleanup_net() processes netns A and then B.
2. gtp_net_exit_batch_rtnl() finds the device B while iterating
netns A's gn->gtp_dev_list and calls ->dellink().
[ device B is not yet unlinked from netns B
as unregister_netdevice_many() has not been called. ]
3. gtp_net_exit_batch_rtnl() finds the device B while iterating
netns B's for_each_netdev() and calls ->dellink().
gtp_dellink() cleans up the device's hash table, unlinks the dev from gn->gtp_dev_list, and calls unregister_netdevice_queue().
Basically, calling gtp_dellink() multiple times is fine unless CONFIG_DEBUG_LIST is enabled.
Let's remove for_each_netdev() in gtp_net_exit_batch_rtnl() and delegate the destruction to default_device_exit_batch() as done in bareudp.
[0]:list_del corruption, ffff8880aaa62c00->next (autoslab_size_M_dev_P_net_core_dev_11127_8_1328_8_S_4096_A_64_n_139+0xc00/0x1000 [slab object]) is LIST_POISON1 (ffffffffffffff02) (prev is 0xffffffffffffff04) kernel BUG at lib/list_debug.c:58!
Oops: invalid opcode: 0000 [#1] PREEMPT SMP KASAN CPU: 1 UID: 0 PID: 1804 Comm: kworker/u8:7 Tainted: G T 6.12.13-grsec-full-20250211091339 #1 Tainted: [T]=RANDSTRUCT Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014 Workqueue: netns cleanup_net RIP: 0010:[<ffffffff84947381>] __list_del_entry_valid_or_report+0x141/0x200 lib/list_debug.c:58 Code: c2 76 91 31 c0 e8 9f b1 f7 fc 0f 0b 4d 89 f0 48 c7 c1 02 ff ff ff 48 89 ea 48 89 ee 48 c7 c7 e0 c2 76 91 31 c0 e8 7f b1 f7 fc <0f> 0b 4d 89 e8 48 c7 c1 04 ff ff ff 48 89 ea 48 89 ee 48 c7 c7 60 RSP: 0018:fffffe8040b4fbd0 EFLAGS: 00010283 RAX: 00000000000000cc RBX: dffffc0000000000 RCX: ffffffff818c4054 RDX: ffffffff84947381 RSI: ffffffff818d1512 RDI: 0000000000000000 RBP: ffff8880aaa62c00 R08: 0000000000000001 R09: fffffbd008169f32 R10: fffffe8040b4f997 R11: 0000000000000001 R12: a1988d84f24943e4 R13: ffffffffffffff02 R14: ffffffffffffff04 R15: ffff8880aaa62c08 RBX: kasan shadow of 0x0 RCX: __wake_up_klogd.part.0+0x74/0xe0 kernel/printk/printk.c:4554 RDX: __list_del_entry_valid_or_report+0x141/0x200 lib/list_debug.c:58 RSI: vprintk+0x72/0x100 kernel/printk/printk_safe.c:71 RBP: autoslab_size_M_dev_P_net_core_dev_11127_8_1328_8_S_4096_A_64_n_139+0xc00/0x1000 [slab object] RSP: process kstack fffffe8040b4fbd0+0x7bd0/0x8000 [kworker/u8:7+netns 1804 ] R09: kasan shadow of process kstack fffffe8040b4f990+0x7990/0x8000 [kworker/u8:7+netns 1804 ] R10: process kstack fffffe8040b4f997+0x7997/0x8000 [kworker/u8:7+netns 1804 ] R15: autoslab_size_M_dev_P_net_core_dev_11127_8_1328_8_S_4096_A_64_n_139+0xc08/0x1000 [slab object] FS: 0000000000000000(0000) GS:ffff888116000000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000748f5372c000 CR3: 0000000015408000 CR4: 00000000003406f0 shadow CR4: 00000000003406f0 Stack: 0000000000000000 ffffffff8a0c35e7 ffffffff8a0c3603 ffff8880aaa62c00 ffff8880aaa62c00 0000000000000004 ffff88811145311c 0000000000000005 0000000000000001 ffff8880aaa62000 fffffe8040b4fd40 ffffffff8a0c360d Call Trace: <TASK> [<ffffffff8a0c360d>] __list_del_entry_valid include/linux/list.h:131 [inline] fffffe8040b4fc28 [<ffffffff8a0c360d>] __list_del_entry include/linux/list.h:248 [inline] fffffe8040b4fc28 [<ffffffff8a0c360d>] list_del include/linux/list.h:262 [inline] fffffe8040b4fc28 [<ffffffff8a0c360d>] gtp_dellink+0x16d/0x360 drivers/net/gtp.c:1557 fffffe8040b4fc28 [<ffffffff8a0d0404>] gtp_net_exit_batch_rtnl+0x124/0x2c0 drivers/net/gtp.c:2495 fffffe8040b4fc88 [<ffffffff8e705b24>] cleanup_net+0x5a4/0xbe0 net/core/net_namespace.c:635 fffffe8040b4fcd0 [<ffffffff81754c97>] process_one_work+0xbd7/0x2160 kernel/workqueue.c:3326 fffffe8040b4fd88 [<ffffffff81757195>] process_scheduled_works kernel/workqueue.c:3407 [inline] fffffe8040b4fec0 [<ffffffff81757195>] worker_thread+0x6b5/0xfa0 kernel/workqueue.c:3488 fffffe8040b4fec0 [<ffffffff817782a0>] kthread+0x360/0x4c0 kernel/kthread.c:397 fffffe8040b4ff78 [<ffffffff814d8594>] ret_from_fork+0x74/0xe0 arch/x86/kernel/process.c:172 fffffe8040b4ffb8 [<ffffffff8110f509>] ret_from_fork_asm+0x29/0xc0 arch/x86/entry/entry_64.S:399 fffffe8040b4ffe8 </TASK> Modules linked in:
--- drivers/net/gtp.c | 5 ----- 1 file changed, 5 deletions(-)
drivers/net/gtp.c +0 -5
@@ -2487,11 +2487,6 @@ static void __net_exit gtp_net_exit_batch_rtnl(struct list_head *net_list,list_for_each_entry (net, net_list, exit_list) {struct gtp_net *gn =net_generic (net, gtp_net_id);struct gtp_dev *gtp, *gtp_next; -struct net_device *dev; - -for_each_netdev (net, dev) -if (dev->rtnl_link_ops == >p_link_ops) -gtp_dellink (dev, dev_to_kill);list_for_each_entry_safe (gtp, gtp_next, &gn->gtp_dev_list, list)gtp_dellink (gtp->dev, dev_to_kill);
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 66/154 geneve: Suppress list corruption splat in geneve_destroy_tunnels().
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 62fab6eef61f245dc8797e3a6a5b890ef40e8628 ]
As explained in the previous patch, iterating for_each_netdev() and gn->geneve_list during ->exit_batch_rtnl() could trigger ->dellink() twice for the same device.
If CONFIG_DEBUG_LIST is enabled, we will see a list_del() corruption splat in the 2nd call of geneve_dellink().
Let's remove for_each_netdev() in geneve_destroy_tunnels() and delegate that part to default_device_exit_batch().
--- drivers/net/geneve.c | 7 ------- 1 file changed, 7 deletions(-)
drivers/net/geneve.c +0 -7
@@ -1902,14 +1902,7 @@ static void geneve_destroy_tunnels(struct net *net, struct list_head *head) {struct geneve_net *gn =net_generic (net, geneve_net_id);struct geneve_dev *geneve, *next; -struct net_device *dev, *aux; -/* gather any geneve devices that were moved into this ns */ -for_each_netdev_safe (net, dev, aux) -if (dev->rtnl_link_ops == &geneve_link_ops) -geneve_dellink (dev, head); - -/* now gather any other geneve devices that were created in this ns */ list_for_each_entry_safe (geneve, next, &gn->geneve_list, next)geneve_dellink (geneve->dev, head); }
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 67/154 flow_dissector: Fix handling of mixed port and port-range keys
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cong Wang <[email protected]>
[ Upstream commit 3e5796862c692ea608d96f0a1437f9290f44953a ]
This patch fixes a bug in TC flower filter where rules combining a specific destination port with a source port range weren't working correctly.
The specific case was when users tried to configure rules like:
tc filter add dev ens38 ingress protocol ip flower ip_proto udp \dst_port 5000 src_port 2000-3000 action drop
The root cause was in the flow dissector code. While both FLOW_DISSECTOR_KEY_PORTS and FLOW_DISSECTOR_KEY_PORTS_RANGE flags were being set correctly in the classifier, the __skb_flow_dissect_ports() function was only populating one of them: whichever came first in the enum check. This meant that when the code needed both a specific port and a port range, one of them would be left as 0, causing the filter to not match packets as expected.
Fix it by removing the either/or logic and instead checking and populating both key types independently when they're in use.
--- net/core/flow_dissector.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-)
net/core/flow_dissector.c +19 -12
@@ -853,23 +853,30 @@ __skb_flow_dissect_ports(const struct sk_buff *skb, void *target_container, const void *data, int nhoff, u8 ip_proto, int hlen) { - enum flow_dissector_key_id dissector_ports = FLOW_DISSECTOR_KEY_MAX; -struct flow_dissector_key_ports *key_ports; + struct flow_dissector_key_ports_range *key_ports_range = NULL; +struct flow_dissector_key_ports *key_ports =NULL ; +__be32 ports;if (dissector_uses_key (flow_dissector,FLOW_DISSECTOR_KEY_PORTS )) - dissector_ports =FLOW_DISSECTOR_KEY_PORTS ; -else if (dissector_uses_key (flow_dissector, -FLOW_DISSECTOR_KEY_PORTS_RANGE )) - dissector_ports =FLOW_DISSECTOR_KEY_PORTS_RANGE ; + key_ports =skb_flow_dissector_target (flow_dissector, +FLOW_DISSECTOR_KEY_PORTS , + target_container); -if (dissector_ports ==FLOW_DISSECTOR_KEY_MAX ) +if (dissector_uses_key (flow_dissector,FLOW_DISSECTOR_KEY_PORTS_RANGE )) + key_ports_range =skb_flow_dissector_target (flow_dissector, +FLOW_DISSECTOR_KEY_PORTS_RANGE , + target_container); + +if (!key_ports && !key_ports_range)return ; - key_ports =skb_flow_dissector_target (flow_dissector, - dissector_ports, - target_container); - key_ports->ports =__skb_flow_get_ports (skb, nhoff, ip_proto, - data, hlen); + ports =__skb_flow_get_ports (skb, nhoff, ip_proto, data, hlen); + +if (key_ports) + key_ports->ports = ports; + +if (key_ports_range) + key_ports_range->tp.ports = ports; } static void
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 68/154 flow_dissector: Fix port range key handling in BPF conversion
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cong Wang <[email protected]>
[ Upstream commit 69ab34f705fbfabcace64b5d53bb7a4450fac875 ]
Fix how port range keys are handled in __skb_flow_bpf_to_target() by:
- Separating PORTS and PORTS_RANGE key handling
- Using correct key_ports_range structure for range keys
- Properly initializing both key types independently
This ensures port range information is correctly stored in its dedicated structure rather than incorrectly using the regular ports key structure.
--- net/core/flow_dissector.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-)
net/core/flow_dissector.c +10 -8
@@ -931,6 +931,7 @@ static void __skb_flow_bpf_to_target(const struct bpf_flow_keys *flow_keys,struct flow_dissector *flow_dissector, void *target_container) { + struct flow_dissector_key_ports_range *key_ports_range = NULL;struct flow_dissector_key_ports *key_ports =NULL ;struct flow_dissector_key_control *key_control;struct flow_dissector_key_basic *key_basic;
@@ -975,20 +976,21 @@ static void __skb_flow_bpf_to_target(const struct bpf_flow_keys *flow_keys, key_control->addr_type =FLOW_DISSECTOR_KEY_IPV6_ADDRS ; } -if (dissector_uses_key (flow_dissector,FLOW_DISSECTOR_KEY_PORTS )) +if (dissector_uses_key (flow_dissector,FLOW_DISSECTOR_KEY_PORTS )) { key_ports =skb_flow_dissector_target (flow_dissector,FLOW_DISSECTOR_KEY_PORTS , target_container); -else if (dissector_uses_key (flow_dissector, -FLOW_DISSECTOR_KEY_PORTS_RANGE )) - key_ports =skb_flow_dissector_target (flow_dissector, -FLOW_DISSECTOR_KEY_PORTS_RANGE , - target_container); - -if (key_ports) { key_ports->src = flow_keys->sport; key_ports->dst = flow_keys->dport; } +if (dissector_uses_key (flow_dissector, +FLOW_DISSECTOR_KEY_PORTS_RANGE )) { + key_ports_range =skb_flow_dissector_target (flow_dissector, +FLOW_DISSECTOR_KEY_PORTS_RANGE , + target_container); + key_ports_range->tp.src = flow_keys->sport; + key_ports_range->tp.dst = flow_keys->dport; + }if (dissector_uses_key (flow_dissector,FLOW_DISSECTOR_KEY_FLOW_LABEL )) {
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 69/154 net: Add non-RCU dev_getbyhwaddr() helper
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Breno Leitao <[email protected]>
[ Upstream commit 4b5a28b38c4a0106c64416a1b2042405166b26ce ]
Add dedicated helper for finding devices by hardware address when holding rtnl_lock, similar to existing dev_getbyhwaddr_rcu(). This prevents PROVE_LOCKING warnings when rtnl_lock is held but RCU read lock is not.
Extract common address comparison logic into dev_addr_cmp().
The context about this change could be found in the following discussion:
Stable-dep-of: 4eae0ee0f1e6 ("arp: switch to dev_getbyhwaddr() in arp_req_set_public()")
--- include/linux/netdevice.h | 2 ++ net/core/dev.c | 37 ++++++++++++++++++++++++++++++++++--- 2 files changed, 36 insertions(+), 3 deletions(-)
include/linux/netdevice.h +2 -0
@@ -3064,6 +3064,8 @@ static inline struct net_device *first_net_device_rcu(struct net *net) }int netdev_boot_setup_check (struct net_device *dev); +struct net_device *dev_getbyhwaddr (struct net *net,unsigned short type, +const char *hwaddr);struct net_device *dev_getbyhwaddr_rcu (struct net *net,unsigned short type,const char *hwaddr);struct net_device *dev_getfirstbyhwtype (struct net *net,unsigned short type);
net/core/dev.c +34 -3
@@ -1012,6 +1012,12 @@ int netdev_get_name(struct net *net, char *name, int ifindex)return ret; } +static bool dev_addr_cmp (struct net_device *dev,unsigned short type, +const char *ha) +{ +return dev->type == type && !memcmp (dev->dev_addr, ha, dev->addr_len); +} +/** * dev_getbyhwaddr_rcu - find a device by its hardware address * @net: the applicable net namespace
@@ -1020,7 +1026,7 @@ int netdev_get_name(struct net *net, char *name, int ifindex)* * Search for an interface by MAC address. Returns NULL if the device * is not found or a pointer to the device. -* The caller must hold RCU or RTNL. +* The caller must hold RCU. * The returned device has not had its ref count increased * and the caller must therefore be careful about locking *
@@ -1032,14 +1038,39 @@ struct net_device *dev_getbyhwaddr_rcu(struct net *net, unsigned short type,struct net_device *dev;for_each_netdev_rcu (net, dev) -if (dev->type == type && - !memcmp (dev->dev_addr, ha, dev->addr_len)) +if (dev_addr_cmp (dev, type, ha))return dev;return NULL ; }EXPORT_SYMBOL (dev_getbyhwaddr_rcu); +/** +* dev_getbyhwaddr() - find a device by its hardware address +* @net: the applicable net namespace +* @type: media type of device +* @ha: hardware address +* +* Similar to dev_getbyhwaddr_rcu(), but the owner needs to hold +* rtnl_lock. +* +* Context: rtnl_lock() must be held. +* Return: pointer to the net_device, or NULL if not found +*/ +struct net_device *dev_getbyhwaddr (struct net *net,unsigned short type, +const char *ha) +{ +struct net_device *dev; + +ASSERT_RTNL (); +for_each_netdev (net, dev) +if (dev_addr_cmp (dev, type, ha)) +return dev; + +return NULL ; +} +EXPORT_SYMBOL (dev_getbyhwaddr); +struct net_device *dev_getfirstbyhwtype (struct net *net,unsigned short type) {struct net_device *dev, *ret =NULL ;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 70/154 arp: switch to dev_getbyhwaddr() in arp_req_set_public()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Breno Leitao <[email protected]>
[ Upstream commit 4eae0ee0f1e6256d0b0b9dd6e72f1d9cf8f72e08 ]
The arp_req_set_public() function is called with the rtnl lock held, which provides enough synchronization protection. This makes the RCU variant of dev_getbyhwaddr() unnecessary. Switch to using the simpler dev_getbyhwaddr() function since we already have the required rtnl locking.
This change helps maintain consistency in the networking code by using the appropriate helper function for the existing locking context. Since we're not holding the RCU read lock in arp_req_set_public() existing code could trigger false positive locking warnings.
--- net/ipv4/arp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv4/arp.c +1 -1
@@ -1077,7 +1077,7 @@ static int arp_req_set_public(struct net *net, struct arpreq *r,__be32 mask = ((struct sockaddr_in *)&r->arp_netmask)->sin_addr.s_addr;if (!dev && (r->arp_flags &ATF_COM )) { - dev =dev_getbyhwaddr_rcu (net, r->arp_ha.sa_family, + dev =dev_getbyhwaddr (net, r->arp_ha.sa_family, r->arp_ha.sa_data);if (!dev)return -ENODEV ;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 71/154 net: axienet: Set mac_managed_pm
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nick Hu <[email protected]>
[ Upstream commit a370295367b55662a32a4be92565fe72a5aa79bb ]
The external PHY will undergo a soft reset twice during the resume process when it wake up from suspend. The first reset occurs when the axienet driver calls phylink_of_phy_connect(), and the second occurs when mdio_bus_phy_resume() invokes phy_init_hw(). The second soft reset of the external PHY does not reinitialize the internal PHY, which causes issues with the internal PHY, resulting in the PHY link being down. To prevent this, setting the mac_managed_pm flag skips the mdio_bus_phy_resume() function.
--- drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ethernet/xilinx/xilinx_axienet_main.c +1 -0
@@ -2888,6 +2888,7 @@ static int axienet_probe(struct platform_device *pdev) lp->phylink_config.dev = &ndev->dev; lp->phylink_config.type =PHYLINK_NETDEV ; + lp->phylink_config.mac_managed_pm = true; lp->phylink_config.mac_capabilities =MAC_SYM_PAUSE |MAC_ASYM_PAUSE |MAC_10FD |MAC_100FD |MAC_1000FD ;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 72/154 tcp: drop secpath at the same time as we currently drop dst
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sabrina Dubroca <[email protected]>
[ Upstream commit 9b6412e6979f6f9e0632075f8f008937b5cd4efd ]
Xiumei reported hitting the WARN in xfrm6_tunnel_net_exit while running tests that boil down to:
- create a pair of netns
- run a basic TCP test over ipcomp6
- delete the pair of netns
The xfrm_state found on spi_byaddr was not deleted at the time we delete the netns, because we still have a reference on it. This lingering reference comes from a secpath (which holds a ref on the xfrm_state), which is still attached to an skb. This skb is not leaked, it ends up on sk_receive_queue and then gets defer-free'd by skb_attempt_defer_free.
The problem happens when we defer freeing an skb (push it on one CPU's defer_list), and don't flush that list before the netns is deleted. In that case, we still have a reference on the xfrm_state that we don't expect at this point.
We already drop the skb's dst in the TCP receive path when it's no longer needed, so let's also drop the secpath. At this point, tcp_filter has already called into the LSM hooks that may require the secpath, so it should not be needed anymore. However, in some of those places, the MPTCP extension has just been attached to the skb, so we cannot simply drop all extensions.
--- include/net/tcp.h | 14 ++++++++++++++ net/ipv4/tcp_fastopen.c | 4 ++-- net/ipv4/tcp_input.c | 8 ++++---- net/ipv4/tcp_ipv4.c | 2 +- 4 files changed, 21 insertions(+), 7 deletions(-)
include/net/tcp.h +14 -0
@@ -41,6 +41,7 @@#include <net/inet_ecn.h> #include <net/dst.h> #include <net/mptcp.h> +#include <net/xfrm.h> #include <linux/seq_file.h> #include <linux/memcontrol.h>
@@ -683,6 +684,19 @@ void tcp_fin(struct sock *sk);void tcp_check_space (struct sock *sk);void tcp_sack_compress_send_ack (struct sock *sk); +static inline void tcp_cleanup_skb (struct sk_buff *skb) +{ +skb_dst_drop (skb); +secpath_reset (skb); +} + +static inline void tcp_add_receive_queue (struct sock *sk,struct sk_buff *skb) +{ +DEBUG_NET_WARN_ON_ONCE (skb_dst (skb)); +DEBUG_NET_WARN_ON_ONCE (secpath_exists (skb)); +__skb_queue_tail (&sk->sk_receive_queue, skb); +} +/* tcp_timer.c */ void tcp_init_xmit_timers (struct sock *);static inline void tcp_clear_xmit_timers (struct sock *sk)
net/ipv4/tcp_fastopen.c +2 -2
@@ -178,7 +178,7 @@ void tcp_fastopen_add_skb(struct sock *sk, struct sk_buff *skb)if (!skb)return ; -skb_dst_drop (skb); +tcp_cleanup_skb (skb);/* segs_in has been initialized to 1 in tcp_create_openreq_child(). * Hence, reset segs_in to 0 before calling tcp_segs_in() * to avoid double counting. Also, tcp_segs_in() expects
@@ -195,7 +195,7 @@ void tcp_fastopen_add_skb(struct sock *sk, struct sk_buff *skb)TCP_SKB_CB (skb)->tcp_flags &= ~TCPHDR_SYN ; tp->rcv_nxt =TCP_SKB_CB (skb)->end_seq; -__skb_queue_tail (&sk->sk_receive_queue, skb); +tcp_add_receive_queue (sk, skb); tp->syn_data_acked =1 ;/* u64_stats_update_begin(&tp->syncp) not needed here,
net/ipv4/tcp_input.c +4 -4
@@ -4970,7 +4970,7 @@ static void tcp_ofo_queue(struct sock *sk)tcp_rcv_nxt_update (tp,TCP_SKB_CB (skb)->end_seq); fin =TCP_SKB_CB (skb)->tcp_flags &TCPHDR_FIN ;if (!eaten) -__skb_queue_tail (&sk->sk_receive_queue, skb); +tcp_add_receive_queue (sk, skb);else kfree_skb_partial (skb, fragstolen);
@@ -5162,7 +5162,7 @@ static int __must_check tcp_queue_rcv(struct sock *sk, struct sk_buff *skb, skb, fragstolen)) ? 1 : 0;tcp_rcv_nxt_update (tcp_sk (sk),TCP_SKB_CB (skb)->end_seq);if (!eaten) { -__skb_queue_tail (&sk->sk_receive_queue, skb); +tcp_add_receive_queue (sk, skb);skb_set_owner_r (skb, sk); }return eaten;
@@ -5245,7 +5245,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)__kfree_skb (skb);return ; } -skb_dst_drop (skb); +tcp_cleanup_skb (skb);__skb_pull (skb,tcp_hdr (skb)->doff *4 ); reason =SKB_DROP_REASON_NOT_SPECIFIED ;
@@ -6214,7 +6214,7 @@ void tcp_rcv_established(struct sock *sk, struct sk_buff *skb)NET_INC_STATS (sock_net (sk),LINUX_MIB_TCPHPHITS );/* Bulk data transfer: receiver */ -skb_dst_drop (skb); +tcp_cleanup_skb (skb);__skb_pull (skb, tcp_header_len); eaten =tcp_queue_rcv (sk, skb, &fragstolen);
net/ipv4/tcp_ipv4.c +1 -1
@@ -2025,7 +2025,7 @@ bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb,*/ skb_condense (skb); -skb_dst_drop (skb); +tcp_cleanup_skb (skb);if (unlikely (tcp_checksum_complete (skb))) {bh_unlock_sock (sk);
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 73/154 net: allow small head cache usage with large MAX_SKB_FRAGS values
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paolo Abeni <[email protected]>
[ Upstream commit 14ad6ed30a10afbe91b0749d6378285f4225d482 ]
Sabrina reported the following splat:
WARNING: CPU: 0 PID: 1 at net/core/dev.c:6935 netif_napi_add_weight_locked+0x8f2/0xba0
Modules linked in:
CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.14.0-rc1-net-00092-g011b03359038 #996
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Arch Linux 1.16.3-1-1 04/01/2014
RIP: 0010:netif_napi_add_weight_locked+0x8f2/0xba0
Code: e8 c3 e6 6a fe 48 83 c4 28 5b 5d 41 5c 41 5d 41 5e 41 5f c3 cc cc cc cc c7 44 24 10 ff ff ff ff e9 8f fb ff ff e8 9e e6 6a fe <0f> 0b e9 d3 fe ff ff e8 92 e6 6a fe 48 8b 04 24 be ff ff ff ff 48
RSP: 0000:ffffc9000001fc60 EFLAGS: 00010293
RAX: 0000000000000000 RBX: ffff88806ce48128 RCX: 1ffff11001664b9e
RDX: ffff888008f00040 RSI: ffffffff8317ca42 RDI: ffff88800b325cb6
RBP: ffff88800b325c40 R08: 0000000000000001 R09: ffffed100167502c
R10: ffff88800b3a8163 R11: 0000000000000000 R12: ffff88800ac1c168
R13: ffff88800ac1c168 R14: ffff88800ac1c168 R15: 0000000000000007
FS: 0000000000000000(0000) GS:ffff88806ce00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: ffff888008201000 CR3: 0000000004c94001 CR4: 0000000000370ef0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
<TASK>
gro_cells_init+0x1ba/0x270
xfrm_input_init+0x4b/0x2a0
xfrm_init+0x38/0x50
ip_rt_init+0x2d7/0x350
ip_init+0xf/0x20
inet_init+0x406/0x590
do_one_initcall+0x9d/0x2e0
do_initcalls+0x23b/0x280
kernel_init_freeable+0x445/0x490
kernel_init+0x20/0x1d0
ret_from_fork+0x46/0x80
ret_from_fork_asm+0x1a/0x30
</TASK>
irq event stamp: 584330
hardirqs last enabled at (584338): [<ffffffff8168bf87>] __up_console_sem+0x77/0xb0
hardirqs last disabled at (584345): [<ffffffff8168bf6c>] __up_console_sem+0x5c/0xb0
softirqs last enabled at (583242): [<ffffffff833ee96d>] netlink_insert+0x14d/0x470
softirqs last disabled at (583754): [<ffffffff8317c8cd>] netif_napi_add_weight_locked+0x77d/0xba0on kernel built with MAX_SKB_FRAGS=45, where SKB_WITH_OVERHEAD(1024) is smaller than GRO_MAX_HEAD.
Such built additionally contains the revert of the single page frag cache so that napi_get_frags() ends up using the page frag allocator, triggering the splat.
Note that the underlying issue is independent from the mentioned revert; address it ensuring that the small head cache will fit either TCP and GRO allocation and updating napi_alloc_skb() and __netdev_alloc_skb() to select kmalloc() usage for any allocation fitting such cache.
--- include/net/gro.h | 3 +++ net/core/gro.c | 3 --- net/core/skbuff.c | 10 +++++++--- 3 files changed, 10 insertions(+), 6 deletions(-)
include/net/gro.h +3 -0
@@ -11,6 +11,9 @@#include <net/udp.h> #include <net/hotdata.h> +/* This should be increased if a protocol with a bigger head is added. */ +#define GRO_MAX_HEAD (MAX_HEADER + 128) + struct napi_gro_cb { union { struct {
net/core/gro.c +0 -3
@@ -7,9 +7,6 @@#define MAX_GRO_SKBS 8 -/* This should be increased if a protocol with a bigger head is added. */ -#define GRO_MAX_HEAD (MAX_HEADER + 128) -static DEFINE_SPINLOCK (offload_lock);/**
net/core/skbuff.c +7 -3
@@ -69,6 +69,7 @@#include <net/dst.h> #include <net/sock.h> #include <net/checksum.h> +#include <net/gro.h> #include <net/gso.h> #include <net/hotdata.h> #include <net/ip6_checksum.h>
@@ -95,7 +96,9 @@static struct kmem_cache *skbuff_ext_cache__ro_after_init ;#endif -#define SKB_SMALL_HEAD_SIZE SKB_HEAD_ALIGN(MAX_TCP_HEADER) +#define GRO_MAX_HEAD_PAD (GRO_MAX_HEAD + NET_SKB_PAD + NET_IP_ALIGN) +#define SKB_SMALL_HEAD_SIZE SKB_HEAD_ALIGN(max(MAX_TCP_HEADER, \ + GRO_MAX_HEAD_PAD))/* We want SKB_SMALL_HEAD_CACHE_SIZE to not be a power of two. * This should ensure that SKB_SMALL_HEAD_HEADROOM is a unique
@@ -736,7 +739,7 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev, unsigned int len,/* If requested length is either too small or too big, * we use kmalloc() for skb->head allocation. */ -if (len <=SKB_WITH_OVERHEAD (1024 ) || +if (len <=SKB_WITH_OVERHEAD (SKB_SMALL_HEAD_CACHE_SIZE ) || len >SKB_WITH_OVERHEAD (PAGE_SIZE ) || (gfp_mask & (__GFP_DIRECT_RECLAIM |GFP_DMA ))) { skb =__alloc_skb (len, gfp_mask,SKB_ALLOC_RX ,NUMA_NO_NODE );
@@ -816,7 +819,8 @@ struct sk_buff *napi_alloc_skb(struct napi_struct *napi, unsigned int len)* When the small frag allocator is available, prefer it over kmalloc * for small fragments */ -if ((!NAPI_HAS_SMALL_PAGE_FRAG && len <=SKB_WITH_OVERHEAD (1024 )) || +if ((!NAPI_HAS_SMALL_PAGE_FRAG && + len <=SKB_WITH_OVERHEAD (SKB_SMALL_HEAD_CACHE_SIZE )) || len >SKB_WITH_OVERHEAD (PAGE_SIZE ) || (gfp_mask & (__GFP_DIRECT_RECLAIM |GFP_DMA ))) { skb = __alloc_skb(len, gfp_mask, SKB_ALLOC_RX | SKB_ALLOC_NAPI,
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 56/154 s390/ism: add release function for struct device
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Julian Ruess <[email protected]>
[ Upstream commit 915e34d5ad35a6a9e56113f852ade4a730fb88f0 ]
According to device_release() in /drivers/base/core.c, a device without a release function is a broken device and must be fixed.
The current code directly frees the device after calling device_add() without waiting for other kernel parts to release their references. Thus, a reference could still be held to a struct device, e.g., by sysfs, leading to potential use-after-free
issues if a proper release function is not set.
--- drivers/s390/net/ism_drv.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
drivers/s390/net/ism_drv.c +12 -2
@@ -588,6 +588,15 @@ static int ism_dev_init(struct ism_dev *ism)return ret; } +static void ism_dev_release (struct device *dev) +{ +struct ism_dev *ism; + + ism = container_of(dev, struct ism_dev, dev); + +kfree (ism); +} +static int ism_probe (struct pci_dev *pdev,const struct pci_device_id *id) {struct ism_dev *ism;
@@ -601,6 +610,7 @@ static int ism_probe(struct pci_dev *pdev, const struct pci_device_id *id)dev_set_drvdata (&pdev->dev, ism); ism->pdev = pdev; ism->dev.parent = &pdev->dev; + ism->dev.release = ism_dev_release;device_initialize (&ism->dev);dev_set_name (&ism->dev,dev_name (&pdev->dev)); ret =device_add (&ism->dev);
@@ -637,7 +647,7 @@ static int ism_probe(struct pci_dev *pdev, const struct pci_device_id *id)device_del (&ism->dev); err_dev:dev_set_drvdata (&pdev->dev,NULL ); -kfree (ism); +put_device (&ism->dev);return ret; }
@@ -682,7 +692,7 @@ static void ism_remove(struct pci_dev *pdev)pci_disable_device (pdev);device_del (&ism->dev);dev_set_drvdata (&pdev->dev,NULL ); -kfree (ism); +put_device (&ism->dev); }static struct pci_driver ism_driver = {
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 74/154 bpf, test_run: Fix use-after-free issue in eth_skb_pkt_type()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shigeru Yoshida <[email protected]>
[ Upstream commit 6b3d638ca897e099fa99bd6d02189d3176f80a47 ]
KMSAN reported a use-after-free issue in eth_skb_pkt_type()[1]. The cause of the issue was that eth_skb_pkt_type() accessed skb's data that didn't contain an Ethernet header. This occurs when bpf_prog_test_run_xdp() passes an invalid value as the user_data argument to bpf_test_init().
Fix this by returning an error when user_data is less than ETH_HLEN in bpf_test_init(). Additionally, remove the check for "if (user_size > size)" as it is unnecessary.
[1]
BUG: KMSAN: use-after-free in eth_skb_pkt_type include/linux/etherdevice.h:627 [inline] BUG: KMSAN: use-after-free in eth_type_trans+0x4ee/0x980 net/ethernet/eth.c:165 eth_skb_pkt_type include/linux/etherdevice.h:627 [inline] eth_type_trans+0x4ee/0x980 net/ethernet/eth.c:165 __xdp_build_skb_from_frame+0x5a8/0xa50 net/core/xdp.c:635 xdp_recv_frames net/bpf/test_run.c:272 [inline] xdp_test_run_batch net/bpf/test_run.c:361 [inline] bpf_test_run_xdp_live+0x2954/0x3330 net/bpf/test_run.c:390 bpf_prog_test_run_xdp+0x148e/0x1b10 net/bpf/test_run.c:1318 bpf_prog_test_run+0x5b7/0xa30 kernel/bpf/syscall.c:4371 __sys_bpf+0x6a6/0xe20 kernel/bpf/syscall.c:5777 __do_sys_bpf kernel/bpf/syscall.c:5866 [inline] __se_sys_bpf kernel/bpf/syscall.c:5864 [inline] __x64_sys_bpf+0xa4/0xf0 kernel/bpf/syscall.c:5864 x64_sys_call+0x2ea0/0x3d90 arch/x86/include/generated/asm/syscalls_64.h:322 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xd9/0x1d0 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f
Uninit was created at:
free_pages_prepare mm/page_alloc.c:1056 [inline] free_unref_page+0x156/0x1320 mm/page_alloc.c:2657 __free_pages+0xa3/0x1b0 mm/page_alloc.c:4838 bpf_ringbuf_free kernel/bpf/ringbuf.c:226 [inline] ringbuf_map_free+0xff/0x1e0 kernel/bpf/ringbuf.c:235 bpf_map_free kernel/bpf/syscall.c:838 [inline] bpf_map_free_deferred+0x17c/0x310 kernel/bpf/syscall.c:862 process_one_work kernel/workqueue.c:3229 [inline] process_scheduled_works+0xa2b/0x1b60 kernel/workqueue.c:3310 worker_thread+0xedf/0x1550 kernel/workqueue.c:3391 kthread+0x535/0x6b0 kernel/kthread.c:389 ret_from_fork+0x6e/0x90 arch/x86/kernel/process.c:147 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244 CPU: 1 UID: 0 PID: 17276 Comm: syz.1.16450 Not tainted 6.12.0-05490-g9bb88c659673 #8 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-3.fc41 04/01/2014
--- net/bpf/test_run.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
net/bpf/test_run.c +1 -4
@@ -660,12 +660,9 @@ static void *bpf_test_init(const union bpf_attr *kattr, u32 user_size,void __user *data_in =u64_to_user_ptr (kattr->test.data_in);void *data; -if (size <ETH_HLEN || size >PAGE_SIZE - headroom - tailroom) +if (user_size <ETH_HLEN || user_size >PAGE_SIZE - headroom - tailroom)return ERR_PTR (-EINVAL ); -if (user_size > size) -return ERR_PTR (-EMSGSIZE ); - size =SKB_DATA_ALIGN (size); data =kzalloc (size + headroom + tailroom,GFP_USER );if (!data)
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 75/154 bpf: unify VM_WRITE vs VM_MAYWRITE use in BPF map mmaping logic
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andrii Nakryiko <[email protected]>
[ Upstream commit 98671a0fd1f14e4a518ee06b19037c20014900eb ]
For all BPF maps we ensure that VM_MAYWRITE is cleared when memory-mapping BPF map contents as initially read-only VMA. This is because in some cases BPF verifier relies on the underlying data to not be modified afterwards by user space, so once something is mapped read-only, it shouldn't be re-mmap'ed as read-write.
As such, it's not necessary to check VM_MAYWRITE in bpf_map_mmap() and map->ops->map_mmap() callbacks: VM_WRITE should be consistently set for read-write mappings, and if VM_WRITE is not set, there is no way for user space to upgrade read-only mapping to read-write one.
This patch cleans up this VM_WRITE vs VM_MAYWRITE handling within bpf_map_mmap(), which is an entry point for any BPF map mmap()-ing logic. We also drop unnecessary sanitization of VM_MAYWRITE in BPF ringbuf's map_mmap() callback implementation, as it is already performed by common code in bpf_map_mmap().
Note, though, that in bpf_map_mmap_{open,close}() callbacks we can't drop VM_MAYWRITE use, because it's possible (and is outside of subsystem's control) to have initially read-write memory mapping, which is subsequently dropped to read-only by user space through mprotect(). In such case, from BPF verifier POV it's read-write data throughout the lifetime of BPF map, and is counted as "active writer".
But its VMAs will start out as VM_WRITE|VM_MAYWRITE, then mprotect() can change it to just VM_MAYWRITE (and no VM_WRITE), so when its finally munmap()'ed and bpf_map_mmap_close() is called, vm_flags will be just VM_MAYWRITE, but we still need to decrement active writer count with bpf_map_write_active_dec() as it's still considered to be a read-write mapping by the rest of BPF subsystem.
Similar reasoning applies to bpf_map_mmap_open(), which is called whenever mmap(), munmap(), and/or mprotect() forces mm subsystem to split original VMA into multiple discontiguous VMAs.
Memory-mapping handling is a bit tricky, yes.
Stable-dep-of: bc27c52eea18 ("bpf: avoid holding freeze_mutex during mmap operation")
--- kernel/bpf/ringbuf.c | 4 ---- kernel/bpf/syscall.c | 10 ++++++++-- 2 files changed, 8 insertions(+), 6 deletions(-)
kernel/bpf/ringbuf.c +0 -4
@@ -268,8 +268,6 @@ static int ringbuf_map_mmap_kern(struct bpf_map *map, struct vm_area_struct *vma/* allow writable mapping for the consumer_pos only */ if (vma->vm_pgoff !=0 || vma->vm_end - vma->vm_start !=PAGE_SIZE )return -EPERM ; - }else { -vm_flags_clear (vma,VM_MAYWRITE ); }/* remap_vmalloc_range() checks size and offset constraints */ return remap_vmalloc_range(vma, rb_map->rb,
@@ -289,8 +287,6 @@ static int ringbuf_map_mmap_user(struct bpf_map *map, struct vm_area_struct *vma* position, and the ring buffer data itself. */ return -EPERM ; - }else { -vm_flags_clear (vma,VM_MAYWRITE ); }/* remap_vmalloc_range() checks size and offset constraints */ return remap_vmalloc_range (vma, rb_map->rb, vma->vm_pgoff +RINGBUF_PGOFF );
kernel/bpf/syscall.c +8 -2
@@ -966,15 +966,21 @@ static int bpf_map_mmap(struct file *filp, struct vm_area_struct *vma) vma->vm_ops = &bpf_map_default_vmops; vma->vm_private_data = map;vm_flags_clear (vma,VM_MAYEXEC ); +/* If mapping is read-only, then disallow potentially re-mapping with +* PROT_WRITE by dropping VM_MAYWRITE flag. This VM_MAYWRITE clearing +* means that as far as BPF map's memory-mapped VMAs are concerned, +* VM_WRITE and VM_MAYWRITE and equivalent, if one of them is set, +* both should be set, so we can forget about VM_MAYWRITE and always +* check just VM_WRITE +*/ if (!(vma->vm_flags &VM_WRITE )) -/* disallow re-mapping with PROT_WRITE */ vm_flags_clear (vma,VM_MAYWRITE ); err = map->ops->map_mmap (map, vma);if (err) goto out; -if (vma->vm_flags &VM_MAYWRITE ) +if (vma->vm_flags &VM_WRITE )bpf_map_write_active_inc (map); out:mutex_unlock (&map->freeze_mutex);
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 76/154 bpf: avoid holding freeze_mutex during mmap operation
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andrii Nakryiko <[email protected]>
[ Upstream commit bc27c52eea189e8f7492d40739b7746d67b65beb ]
We use map->freeze_mutex to prevent races between map_freeze() and memory mapping BPF map contents with writable permissions. The way we naively do this means we'll hold freeze_mutex for entire duration of all the mm and VMA manipulations, which is completely unnecessary. This can potentially also lead to deadlocks, as reported by syzbot in [0].
So, instead, hold freeze_mutex only during writeability checks, bump (proactively) "write active" count for the map, unlock the mutex and proceed with mmap logic. And only if something went wrong during mmap logic, then undo that "write active" counter increment.
[0] https://lore.kernel.org/bpf/[email protected]/
--- kernel/bpf/syscall.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-)
kernel/bpf/syscall.c +10 -7
@@ -936,7 +936,7 @@ static const struct vm_operations_struct bpf_map_default_vmops = {static int bpf_map_mmap (struct file *filp,struct vm_area_struct *vma) {struct bpf_map *map = filp->private_data; -int err; +int err =0 ;if (!map->ops->map_mmap || !IS_ERR_OR_NULL (map->record))return -ENOTSUPP ;
@@ -960,7 +960,12 @@ static int bpf_map_mmap(struct file *filp, struct vm_area_struct *vma) err = -EACCES ; goto out; } +bpf_map_write_active_inc (map); } +out: +mutex_unlock (&map->freeze_mutex); +if (err) +return err;/* set default open/close callbacks */ vma->vm_ops = &bpf_map_default_vmops;
@@ -977,13 +982,11 @@ static int bpf_map_mmap(struct file *filp, struct vm_area_struct *vma)vm_flags_clear (vma,VM_MAYWRITE ); err = map->ops->map_mmap (map, vma); -if (err) - goto out; +if (err) { +if (vma->vm_flags &VM_WRITE ) +bpf_map_write_active_dec (map); + } -if (vma->vm_flags &VM_WRITE ) -bpf_map_write_active_inc (map); -out: -mutex_unlock (&map->freeze_mutex);return err; }
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 77/154 strparser: Add read_sock callback
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiayuan Chen <[email protected]>
[ Upstream commit 0532a79efd68a4d9686b0385e4993af4b130ff82 ]
Added a new read_sock handler, allowing users to customize read operations instead of relying on the native socket's read_sock.
Stable-dep-of: 36b62df5683c ("bpf: Fix wrong copied_seq calculation")
--- Documentation/networking/strparser.rst | 9 ++++++++- include/net/strparser.h | 2 ++ net/strparser/strparser.c | 11 +++++++++-- 3 files changed, 19 insertions(+), 3 deletions(-)
Documentation/networking/strparser.rst +8 -1
@@ -112,7 +112,7 @@ Functions Callbacks ========= -There are six callbacks: +There are seven callbacks: ::
@@ -182,6 +182,13 @@ There are six callbacks: the length of the message. skb->len - offset may be greater then full_len since strparser does not trim the skb. + :: + + int (*read_sock)(struct strparser *strp, read_descriptor_t *desc, + sk_read_actor_t recv_actor); + + The read_sock callback is used by strparser instead of + sock->ops->read_sock, if provided. :: int (*read_sock_done)(struct strparser *strp, int err);
include/net/strparser.h +2 -0
@@ -43,6 +43,8 @@ struct strparser;struct strp_callbacks {int (*parse_msg)(struct strparser *strp,struct sk_buff *skb);void (*rcv_msg)(struct strparser *strp,struct sk_buff *skb); +int (*read_sock)(struct strparser *strp,read_descriptor_t *desc, +sk_read_actor_t recv_actor);int (*read_sock_done)(struct strparser *strp,int err);void (*abort_parser)(struct strparser *strp,int err);void (*lock)(struct strparser *strp);
net/strparser/strparser.c +9 -2
@@ -347,7 +347,10 @@ static int strp_read_sock(struct strparser *strp)struct socket *sock = strp->sk->sk_socket;read_descriptor_t desc; -if (unlikely (!sock || !sock->ops || !sock->ops->read_sock)) +if (unlikely (!sock || !sock->ops)) +return -EBUSY ; + +if (unlikely (!strp->cb.read_sock && !sock->ops->read_sock))return -EBUSY ; desc.arg.data = strp;
@@ -355,7 +358,10 @@ static int strp_read_sock(struct strparser *strp) desc.count =1 ;/* give more than one skb per call */ /* sk should be locked here, so okay to do read_sock */ - sock->ops->read_sock (strp->sk, &desc, strp_recv); +if (strp->cb.read_sock) + strp->cb.read_sock (strp, &desc, strp_recv); +else + sock->ops->read_sock (strp->sk, &desc, strp_recv); desc.error = strp->cb.read_sock_done (strp, desc.error);
@@ -468,6 +474,7 @@ int strp_init(struct strparser *strp, struct sock *sk, strp->cb.unlock = cb->unlock ? : strp_sock_unlock; strp->cb.rcv_msg = cb->rcv_msg; strp->cb.parse_msg = cb->parse_msg; + strp->cb.read_sock = cb->read_sock; strp->cb.read_sock_done = cb->read_sock_done ? : default_read_sock_done; strp->cb.abort_parser = cb->abort_parser ? : strp_abort_strp;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 78/154 bpf: Fix wrong copied_seq calculation
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiayuan Chen <[email protected]>
[ Upstream commit 36b62df5683c315ba58c950f1a9c771c796c30ec ]
'sk->copied_seq' was updated in the tcp_eat_skb() function when the action of a BPF program was SK_REDIRECT. For other actions, like SK_PASS, the update logic for 'sk->copied_seq' was moved to tcp_bpf_recvmsg_parser() to ensure the accuracy of the 'fionread' feature.
It works for a single stream_verdict scenario, as it also modified sk_data_ready->sk_psock_verdict_data_ready->tcp_read_skb to remove updating 'sk->copied_seq'.
However, for programs where both stream_parser and stream_verdict are active (strparser purpose), tcp_read_sock() was used instead of tcp_read_skb() (sk_data_ready->strp_data_ready->tcp_read_sock). tcp_read_sock() now still updates 'sk->copied_seq', leading to duplicate updates.
In summary, for strparser + SK_PASS, copied_seq is redundantly calculated in both tcp_read_sock() and tcp_bpf_recvmsg_parser().
The issue causes incorrect copied_seq calculations, which prevent correct data reads from the recv() interface in user-land.
We do not want to add new proto_ops to implement a new version of tcp_read_sock, as this would introduce code complexity [1].
We could have added noack and copied_seq to desc, and then called ops->read_sock. However, unfortunately, other modules didn’t fully initialize desc to zero. So, for now, we are directly calling tcp_read_sock_noack() in tcp_bpf.c.
[1]: https://lore.kernel.org/bpf/[email protected]
--- include/linux/skmsg.h | 2 ++ include/net/tcp.h | 8 ++++++++ net/core/skmsg.c | 7 +++++++ net/ipv4/tcp.c | 29 ++++++++++++++++++++++++----- net/ipv4/tcp_bpf.c | 36 ++++++++++++++++++++++++++++++++++++ 5 files changed, 77 insertions(+), 5 deletions(-)
include/linux/skmsg.h +2 -0
@@ -91,6 +91,8 @@ struct sk_psock {struct sk_psock_progs progs;#if IS_ENABLED (CONFIG_BPF_STREAM_PARSER )struct strparser strp; +u32 copied_seq; +u32 ingress_bytes;#endif struct sk_buff_head ingress_skb;struct list_head ingress_msg;
include/net/tcp.h +8 -0
@@ -743,6 +743,9 @@ void tcp_get_info(struct sock *, struct tcp_info *);/* Read 'sendfile()'-style from a TCP socket */ int tcp_read_sock (struct sock *sk,read_descriptor_t *desc,sk_read_actor_t recv_actor); +int tcp_read_sock_noack (struct sock *sk,read_descriptor_t *desc, +sk_read_actor_t recv_actor,bool noack, +u32 *copied_seq);int tcp_read_skb (struct sock *sk,skb_read_actor_t recv_actor);struct sk_buff *tcp_recv_skb (struct sock *sk,u32 seq,u32 *off);void tcp_read_done (struct sock *sk,size_t len);
@@ -2609,6 +2612,11 @@ struct sk_psock;#ifdef CONFIG_BPF_SYSCALL int tcp_bpf_update_proto (struct sock *sk,struct sk_psock *psock,bool restore);void tcp_bpf_clone (const struct sock *sk,struct sock *newsk); +#ifdef CONFIG_BPF_STREAM_PARSER +struct strparser ; +int tcp_bpf_strp_read_sock (struct strparser *strp,read_descriptor_t *desc, +sk_read_actor_t recv_actor); +#endif /* CONFIG_BPF_STREAM_PARSER */ #endif /* CONFIG_BPF_SYSCALL */ #ifdef CONFIG_INET
net/core/skmsg.c +7 -0
@@ -548,6 +548,9 @@ static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb,return num_sge; } +#if IS_ENABLED (CONFIG_BPF_STREAM_PARSER ) + psock->ingress_bytes += len; +#endif copied = len; msg->sg.start =0 ; msg->sg.size = copied;
@@ -1143,6 +1146,10 @@ int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock)if (!ret)sk_psock_set_state (psock,SK_PSOCK_RX_STRP_ENABLED ); +if (sk_is_tcp (sk)) { + psock->strp.cb.read_sock = tcp_bpf_strp_read_sock; + psock->copied_seq =tcp_sk (sk)->copied_seq; + }return ret; }
net/ipv4/tcp.c +24 -5
@@ -1564,12 +1564,13 @@ EXPORT_SYMBOL(tcp_recv_skb);* or for 'peeking' the socket using this routine * (although both would be easy to implement). */ -int tcp_read_sock (struct sock *sk,read_descriptor_t *desc, -sk_read_actor_t recv_actor) +static int __tcp_read_sock (struct sock *sk,read_descriptor_t *desc, +sk_read_actor_t recv_actor,bool noack, +u32 *copied_seq) {struct sk_buff *skb;struct tcp_sock *tp =tcp_sk (sk); -u32 seq = tp->copied_seq; +u32 seq = *copied_seq;u32 offset;int copied =0 ;
@@ -1623,9 +1624,12 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,tcp_eat_recv_skb (sk, skb);if (!desc->count)break ; -WRITE_ONCE (tp->copied_seq, seq); +WRITE_ONCE (*copied_seq, seq); } -WRITE_ONCE (tp->copied_seq, seq); +WRITE_ONCE (*copied_seq, seq); + +if (noack) + goto out;tcp_rcv_space_adjust (sk);
@@ -1634,10 +1638,25 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,tcp_recv_skb (sk, seq, &offset);tcp_cleanup_rbuf (sk, copied); } +out:return copied; } + +int tcp_read_sock (struct sock *sk,read_descriptor_t *desc, +sk_read_actor_t recv_actor) +{ +return __tcp_read_sock (sk, desc, recv_actor, false, + &tcp_sk (sk)->copied_seq); +}EXPORT_SYMBOL (tcp_read_sock); +int tcp_read_sock_noack (struct sock *sk,read_descriptor_t *desc, +sk_read_actor_t recv_actor,bool noack, +u32 *copied_seq) +{ +return __tcp_read_sock (sk, desc, recv_actor, noack, copied_seq); +} +int tcp_read_skb (struct sock *sk,skb_read_actor_t recv_actor) {struct sk_buff *skb;
net/ipv4/tcp_bpf.c +36 -0
@@ -646,6 +646,42 @@ static int tcp_bpf_assert_proto_ops(struct proto *ops) ops->sendmsg == tcp_sendmsg ?0 : -ENOTSUPP ; } +#if IS_ENABLED (CONFIG_BPF_STREAM_PARSER ) +int tcp_bpf_strp_read_sock (struct strparser *strp,read_descriptor_t *desc, +sk_read_actor_t recv_actor) +{ +struct sock *sk = strp->sk; +struct sk_psock *psock; +struct tcp_sock *tp; +int copied =0 ; + + tp =tcp_sk (sk); +rcu_read_lock (); + psock =sk_psock (sk); +if (WARN_ON_ONCE (!psock)) { + desc->error = -EINVAL ; + goto out; + } + + psock->ingress_bytes =0 ; + copied =tcp_read_sock_noack (sk, desc, recv_actor, true, + &psock->copied_seq); +if (copied <0 ) + goto out; +/* recv_actor may redirect skb to another socket (SK_REDIRECT) or +* just put skb into ingress queue of current socket (SK_PASS). +* For SK_REDIRECT, we need to ack the frame immediately but for +* SK_PASS, we want to delay the ack until tcp_bpf_recvmsg_parser(). +*/ + tp->copied_seq = psock->copied_seq - psock->ingress_bytes; +tcp_rcv_space_adjust (sk); +__tcp_cleanup_rbuf (sk, copied - psock->ingress_bytes); +out: +rcu_read_unlock (); +return copied; +} +#endif /* CONFIG_BPF_STREAM_PARSER */ +int tcp_bpf_update_proto (struct sock *sk,struct sk_psock *psock,bool restore) {int family = sk->sk_family ==AF_INET6 ?TCP_BPF_IPV6 :TCP_BPF_IPV4 ;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 79/154 bpf: Disable non stream socket for strparser
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiayuan Chen <[email protected]>
[ Upstream commit 5459cce6bf49e72ee29be21865869c2ac42419f5 ]
Currently, only TCP supports strparser, but sockmap doesn't intercept non-TCP connections to attach strparser. For example, with UDP, although the read/write handlers are replaced, strparser is not executed due to the lack of a read_sock operation.
Furthermore, in udp_bpf_recvmsg(), it checks whether the psock has data, and if not, it falls back to the native UDP read interface, making UDP + strparser appear to read correctly. According to its commit history, this behavior is unexpected.
Moreover, since UDP lacks the concept of streams, we intercept it directly.
--- net/core/sock_map.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
net/core/sock_map.c +4 -1
@@ -303,7 +303,10 @@ static int sock_map_link(struct bpf_map *map, struct sock *sk)write_lock_bh (&sk->sk_callback_lock);if (stream_parser && stream_verdict && !psock->saved_data_ready) { - ret =sk_psock_init_strp (sk, psock); +if (sk_is_tcp (sk)) + ret =sk_psock_init_strp (sk, psock); +else + ret = -EOPNOTSUPP ;if (ret) {write_unlock_bh (&sk->sk_callback_lock);sk_psock_put (sk, psock);
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 80/154 bpf: Fix deadlock when freeing cgroup storage
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abel Wu <[email protected]>
[ Upstream commit c78f4afbd962f43a3989f45f3ca04300252b19b5 ]
The following commitbc235cdb423a ("bpf: Prevent deadlock from recursive bpf_task_storage_[get|delete]") first introduced deadlock prevention for fentry/fexit programs attaching on bpf_task_storage helpers. That commit also employed the logic in map free path in its v6 version.
Later bpf_cgrp_storage was first introduced inc4bcfb38a95e ("bpf: Implement cgroup storage available to non-cgroup-attached bpf progs") which faces the same issue as bpf_task_storage, instead of its busy counter, NULL was passed to bpf_local_storage_map_free() which opened
a window to cause deadlock:
<TASK> (acquiring local_storage->lock) _raw_spin_lock_irqsave+0x3d/0x50 bpf_local_storage_update+0xd1/0x460 bpf_cgrp_storage_get+0x109/0x130 bpf_prog_a4d4a370ba857314_cgrp_ptr+0x139/0x170 ? __bpf_prog_enter_recur+0x16/0x80 bpf_trampoline_6442485186+0x43/0xa4 cgroup_storage_ptr+0x9/0x20 (holding local_storage->lock) bpf_selem_unlink_storage_nolock.constprop.0+0x135/0x160 bpf_selem_unlink_storage+0x6f/0x110 bpf_local_storage_map_free+0xa2/0x110 bpf_map_free_deferred+0x5b/0x90 process_one_work+0x17c/0x390 worker_thread+0x251/0x360 kthread+0xd2/0x100 ret_from_fork+0x34/0x50 ret_from_fork_asm+0x1a/0x30 </TASK>
Progs:
- A: SEC("fentry/cgroup_storage_ptr")
- cgid (BPF_MAP_TYPE_HASH)
Record the id of the cgroup the current task belonging to in this hash map, using the address of the cgroup as the map key.
- cgrpa (BPF_MAP_TYPE_CGRP_STORAGE)
If current task is a kworker, lookup the above hash map using function parameter @owner as the key to get its corresponding cgroup id which is then used to get a trusted pointer to the cgroup through bpf_cgroup_from_id(). This trusted pointer can then be passed to bpf_cgrp_storage_get() to finally trigger the deadlock issue.
- B: SEC("tp_btf/sys_enter")
- cgrpb (BPF_MAP_TYPE_CGRP_STORAGE)
The only purpose of this prog is to fill Prog A's hash map by calling bpf_cgrp_storage_get() for as many userspace tasks as possible.
Steps to reproduce:
- Run A;
- while (true) { Run B; Destroy B; }
Fix this issue by passing its busy counter to the free procedure so it can be properly incremented before storage/smap locking.
--- kernel/bpf/bpf_cgrp_storage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/bpf/bpf_cgrp_storage.c +1 -1
@@ -154,7 +154,7 @@ static struct bpf_map *cgroup_storage_map_alloc(union bpf_attr *attr)static void cgroup_storage_map_free (struct bpf_map *map) { -bpf_local_storage_map_free (map, &cgroup_cache,NULL ); +bpf_local_storage_map_free (map, &cgroup_cache, &bpf_cgrp_storage_busy); }/* *gfp_flags* is a hidden argument provided by the verifier */
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 81/154 arm64: dts: rockchip: Fix lcdpwr_en pin for Cool Pi GenBook
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andy Yan <[email protected]>
[ Upstream commit a1d939055a22be06d8c12bf53afb258b9d38575f ]
According to the schematic, the lcdpwr_en pin is GPIO0_C4, not GPIO1_C4.
--- arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5-genbook.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5-genbook.dts +2 -2
@@ -101,7 +101,7 @@ vcc3v3_lcd: vcc3v3-lcd-regulator { compatible = "regulator-fixed"; regulator-name = "vcc3v3_lcd"; enable-active-high; - gpio = <&gpio1 RK_PC4 GPIO_ACTIVE_HIGH>; + gpio = <&gpio0 RK_PC4 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&lcdpwr_en>; vin-supply = <&vcc3v3_sys>;
@@ -207,7 +207,7 @@ &pcie3x4 { &pinctrl { lcd { lcdpwr_en: lcdpwr-en { - rockchip,pins = <1 RK_PC4 RK_FUNC_GPIO &pcfg_pull_down>; + rockchip,pins = <0 RK_PC4 RK_FUNC_GPIO &pcfg_pull_down>; }; bl_en: bl-en {
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 82/154 power: supply: da9150-fg: fix potential overflow
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andrey Vatoropin <[email protected]>
[ Upstream commit 3fb3cb4350befc4f901c54e0cb4a2a47b1302e08 ]
Size of variable sd_gain equals four bytes - DA9150_QIF_SD_GAIN_SIZE. Size of variable shunt_val equals two bytes - DA9150_QIF_SHUNT_VAL_SIZE.
The expression sd_gain * shunt_val is currently being evaluated using 32-bit arithmetic. So during the multiplication an overflow may occur.
As the value of type 'u64' is used as storage for the eventual result, put ULL variable at the first position of each expression in order to give the compiler complete information about the proper arithmetic to use. According to C99 the guaranteed width for a variable of type 'unsigned long long' >= 64 bits.
Remove the explicit cast to u64 as it is meaningless.
Just for the sake of consistency, perform the similar trick with another expression concerning 'iavg'.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- drivers/power/supply/da9150-fg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/power/supply/da9150-fg.c +2 -2
@@ -247,9 +247,9 @@ static int da9150_fg_current_avg(struct da9150_fg *fg, DA9150_QIF_SD_GAIN_SIZE);da9150_fg_read_sync_end (fg); - div = (u64) (sd_gain * shunt_val *65536ULL ); + div =65536ULL * sd_gain * shunt_val;do_div (div,1000000 ); - res = (u64) (iavg *1000000ULL ); + res =1000000ULL * iavg;do_div (res, div); val->intval = (int ) res;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 83/154 power: supply: axp20x_battery: Fix fault handling for AXP717
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chris Morgan <[email protected]>
[ Upstream commit 98380110bd48fbfd6a798ee11fffff893d36062c ]
Correct the fault handling for the AXP717 by changing the i2c write from regmap_update_bits() to regmap_write_bits(). The update bits function does not work properly on a RW1C register where we must write a 1 back to an existing register to clear it.
Additionally, as part of this testing I confirmed the behavior of errors reappearing, so remove comment about assumptions.
--- drivers/power/supply/axp20x_battery.c | 31 +++++++++++++-------------- 1 file changed, 15 insertions(+), 16 deletions(-)
drivers/power/supply/axp20x_battery.c +15 -16
@@ -466,10 +466,9 @@ static int axp717_battery_get_prop(struct power_supply *psy,/* * If a fault is detected it must also be cleared; if the -* condition persists it should reappear (This is an -* assumption, it's actually not documented). A restart was -* not sufficient to clear the bit in testing despite the -* register listed as POR. +* condition persists it should reappear. A restart was not +* sufficient to clear the bit in testing despite the register +* listed as POR. */ case POWER_SUPPLY_PROP_HEALTH : ret = regmap_read(axp20x_batt->regmap, AXP717_PMU_FAULT,
@@ -480,26 +479,26 @@ static int axp717_battery_get_prop(struct power_supply *psy,switch (reg &AXP717_BATT_PMU_FAULT_MASK ) {case AXP717_BATT_UVLO_2_5V : val->intval =POWER_SUPPLY_HEALTH_DEAD ; -regmap_update_bits (axp20x_batt->regmap, -AXP717_PMU_FAULT , -AXP717_BATT_UVLO_2_5V , -AXP717_BATT_UVLO_2_5V ); +regmap_write_bits (axp20x_batt->regmap, +AXP717_PMU_FAULT , +AXP717_BATT_UVLO_2_5V , +AXP717_BATT_UVLO_2_5V );return 0 ;case AXP717_BATT_OVER_TEMP : val->intval =POWER_SUPPLY_HEALTH_HOT ; -regmap_update_bits (axp20x_batt->regmap, -AXP717_PMU_FAULT , -AXP717_BATT_OVER_TEMP , -AXP717_BATT_OVER_TEMP ); +regmap_write_bits (axp20x_batt->regmap, +AXP717_PMU_FAULT , +AXP717_BATT_OVER_TEMP , +AXP717_BATT_OVER_TEMP );return 0 ;case AXP717_BATT_UNDER_TEMP : val->intval =POWER_SUPPLY_HEALTH_COLD ; -regmap_update_bits (axp20x_batt->regmap, -AXP717_PMU_FAULT , -AXP717_BATT_UNDER_TEMP , -AXP717_BATT_UNDER_TEMP ); +regmap_write_bits (axp20x_batt->regmap, +AXP717_PMU_FAULT , +AXP717_BATT_UNDER_TEMP , +AXP717_BATT_UNDER_TEMP );return 0 ;default :
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 57/154 ibmvnic: Add stat for tx direct vs tx batched
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nick Child <[email protected]>
[ Upstream commit 2ee73c54a615b74d2e7ee6f20844fd3ba63fc485 ]
Allow tracking of packets sent with send_subcrq direct vs indirect. ethtool -S <dev> will now provide a counter of the number of uses of each xmit method. This metric will be useful in performance debugging.
Stable-dep-of: bdf5d13aa05e ("ibmvnic: Don't reference skb after sending to VIOS")
--- drivers/net/ethernet/ibm/ibmvnic.c | 23 ++++++++++++++++------- drivers/net/ethernet/ibm/ibmvnic.h | 3 ++- 2 files changed, 18 insertions(+), 8 deletions(-)
drivers/net/ethernet/ibm/ibmvnic.c +16 -7
@@ -2310,7 +2310,7 @@ static void ibmvnic_tx_scrq_clean_buffer(struct ibmvnic_adapter *adapter, tx_buff = &tx_pool->tx_buff[index]; adapter->netdev->stats.tx_packets--; adapter->netdev->stats.tx_bytes -= tx_buff->skb->len; - adapter->tx_stats_buffers[queue_num].packets--; + adapter->tx_stats_buffers[queue_num].batched_packets--; adapter->tx_stats_buffers[queue_num].bytes -= tx_buff->skb->len;dev_kfree_skb_any (tx_buff->skb);
@@ -2402,7 +2402,8 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)unsigned int tx_map_failed =0 ;union sub_crq indir_arr[16 ];unsigned int tx_dropped =0 ; -unsigned int tx_packets =0 ; +unsigned int tx_dpackets =0 ; +unsigned int tx_bpackets =0 ;unsigned int tx_bytes =0 ;dma_addr_t data_dma_addr;struct netdev_queue *txq;
@@ -2575,6 +2576,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)if (lpar_rc !=H_SUCCESS ) goto tx_err; + tx_dpackets++; goto early_exit; }
@@ -2603,6 +2605,8 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev) goto tx_err; } + tx_bpackets++; + early_exit:if (atomic_add_return (num_entries, &tx_scrq->used) >= adapter->req_tx_entries_per_subcrq) {
@@ -2610,7 +2614,6 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)netif_stop_subqueue (netdev, queue_num); } - tx_packets++; tx_bytes += skb->len;txq_trans_cond_update (txq); ret =NETDEV_TX_OK ;
@@ -2640,10 +2643,11 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)rcu_read_unlock (); netdev->stats.tx_dropped += tx_dropped; netdev->stats.tx_bytes += tx_bytes; - netdev->stats.tx_packets += tx_packets; + netdev->stats.tx_packets += tx_bpackets + tx_dpackets; adapter->tx_send_failed += tx_send_failed; adapter->tx_map_failed += tx_map_failed; - adapter->tx_stats_buffers[queue_num].packets += tx_packets; + adapter->tx_stats_buffers[queue_num].batched_packets += tx_bpackets; + adapter->tx_stats_buffers[queue_num].direct_packets += tx_dpackets; adapter->tx_stats_buffers[queue_num].bytes += tx_bytes; adapter->tx_stats_buffers[queue_num].dropped_packets += tx_dropped;
@@ -3808,7 +3812,10 @@ static void ibmvnic_get_strings(struct net_device *dev, u32 stringset, u8 *data)memcpy (data, ibmvnic_stats[i].name,ETH_GSTRING_LEN );for (i =0 ; i < adapter->req_tx_queues; i++) { -snprintf (data,ETH_GSTRING_LEN ,"tx%d_packets" , i); +snprintf (data,ETH_GSTRING_LEN ,"tx%d_batched_packets" , i); + data +=ETH_GSTRING_LEN ; + +snprintf (data,ETH_GSTRING_LEN ,"tx%d_direct_packets" , i); data +=ETH_GSTRING_LEN ;snprintf (data,ETH_GSTRING_LEN ,"tx%d_bytes" , i);
@@ -3873,7 +3880,9 @@ static void ibmvnic_get_ethtool_stats(struct net_device *dev, (adapter, ibmvnic_stats[i].offset));for (j =0 ; j < adapter->req_tx_queues; j++) { - data[i] = adapter->tx_stats_buffers[j].packets; + data[i] = adapter->tx_stats_buffers[j].batched_packets; + i++; + data[i] = adapter->tx_stats_buffers[j].direct_packets; i++; data[i] = adapter->tx_stats_buffers[j].bytes; i++;
drivers/net/ethernet/ibm/ibmvnic.h +2 -1
@@ -213,7 +213,8 @@ struct ibmvnic_statistics {#define NUM_TX_STATS 3struct ibmvnic_tx_queue_stats { -u64 packets; +u64 batched_packets; +u64 direct_packets;u64 bytes;u64 dropped_packets; };
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 84/154 selftests/bpf: Add tests for raw_tp null handling
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kumar Kartikeya Dwivedi <[email protected]>
[ Upstream commit d798ce3f4cab1b0d886b19ec5cc8e6b3d7e35081 ]
Ensure that trusted PTR_TO_BTF_ID accesses perform PROBE_MEM handling in raw_tp program. Without the previous fix, this selftest crashes the kernel due to a NULL-pointer dereference. Also ensure that dead code elimination does not kick in for checks on the pointer.
Stable-dep-of: 5da7e15fb5a1 ("net: Add rx_skb of kfree_skb to raw_tp_null_args[].")
--- .../bpf/bpf_testmod/bpf_testmod-events.h | 8 +++++ .../selftests/bpf/bpf_testmod/bpf_testmod.c | 2 ++ .../selftests/bpf/prog_tests/raw_tp_null.c | 25 +++++++++++++++ .../testing/selftests/bpf/progs/raw_tp_null.c | 32 +++++++++++++++++++ 4 files changed, 67 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/raw_tp_null.c create mode 100644 tools/testing/selftests/bpf/progs/raw_tp_null.c
tools/testing/selftests/bpf/bpf_testmod/bpf_testmod-events.h +8 -0
@@ -40,6 +40,14 @@ DECLARE_TRACE(bpf_testmod_test_nullable_bare,TP_ARGS (ctx__nullable) ); +struct sk_buff ; + +DECLARE_TRACE (bpf_testmod_test_raw_tp_null, + TP_PROTO(struct sk_buff *skb), +TP_ARGS (skb) +); + +#undef BPF_TESTMOD_DECLARE_TRACE#ifdef DECLARE_TRACE_WRITABLE #define BPF_TESTMOD_DECLARE_TRACE (call, proto, args, size) \
tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c +2 -0
@@ -380,6 +380,8 @@ bpf_testmod_test_read(struct file *file, struct kobject *kobj, (void )bpf_testmod_test_arg_ptr_to_struct (&struct_arg1_2); + (void )trace_bpf_testmod_test_raw_tp_null (NULL ); + struct_arg3 =kmalloc ((sizeof (struct bpf_testmod_struct_arg_3 ) +sizeof (int )),GFP_KERNEL );if (struct_arg3 !=NULL ) {
tools/testing/selftests/bpf/prog_tests/raw_tp_null.c new file +25 -0
@@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */ + +#include <test_progs.h> +#include "raw_tp_null.skel.h" + +void test_raw_tp_null (void ) +{ +struct raw_tp_null *skel; + + skel =raw_tp_null__open_and_load (); +if (!ASSERT_OK_PTR (skel,"raw_tp_null__open_and_load" )) +return ; + + skel->bss->tid =sys_gettid (); + +if (!ASSERT_OK (raw_tp_null__attach (skel),"raw_tp_null__attach" )) + goto end; + +ASSERT_OK (trigger_module_test_read (2 ),"trigger testmod read" ); +ASSERT_EQ (skel->bss->i,3 ,"invocations" ); + +end: +raw_tp_null__destroy (skel); +}
tools/testing/selftests/bpf/progs/raw_tp_null.c new file +32 -0
@@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */ + +#include <vmlinux.h> +#include <bpf/bpf_tracing.h> + +char _license[] SEC("license") = "GPL"; + +int tid; +int i; + +SEC("tp_btf/bpf_testmod_test_raw_tp_null") +int BPF_PROG (test_raw_tp_null ,struct sk_buff *skb) +{ +struct task_struct *task =bpf_get_current_task_btf (); + +if (task->pid != tid) +return 0 ; + + i = i + skb->mark +1 ; +/* The compiler may move the NULL check before this deref, which causes +* the load to fail as deref of scalar. Prevent that by using a barrier. +*/ +barrier (); +/* If dead code elimination kicks in, the increment below will +* be removed. For raw_tp programs, we mark input arguments as +* PTR_MAYBE_NULL, so branch prediction should never kick in. +*/ +if (!skb) + i +=2 ; +return 0 ; +}
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 85/154 net: Add rx_skb of kfree_skb to raw_tp_null_args[].
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 5da7e15fb5a12e78de974d8908f348e279922ce9 ]
Yan Zhai reported a BPF prog could trigger a null-ptr-deref [0] in trace_kfree_skb if the prog does not check if rx_sk is NULL.
Commit c53795d48ee8 ("net: add rx_sk to trace_kfree_skb") added rx_sk to trace_kfree_skb, but rx_sk is optional and could be NULL.
Let's add kfree_skb to raw_tp_null_args[] to let the BPF verifier validate such a prog and prevent the issue.
Now we fail to load such a prog:
libbpf: prog 'drop': -- BEGIN PROG LOAD LOG --
0: R1=ctx() R10=fp0
; int BPF_PROG(drop, struct sk_buff *skb, void *location, @ kfree_skb_sk_null.bpf.c:21 0: (79) r3 = *(u64 *)(r1 +24)
func 'kfree_skb' arg3 has btf_id 5253 type STRUCT 'sock'
1: R1=ctx() R3_w=trusted_ptr_or_null_sock(id=1)
; bpf_printk("sk: %d, %d\n", sk, sk->__sk_common.skc_family); @ kfree_skb_sk_null.bpf.c:24 1: (69) r4 = *(u16 *)(r3 +16)
R3 invalid mem access 'trusted_ptr_or_null_'
processed 2 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0 -- END PROG LOAD LOG --
Note this fix requires commit 838a10bd2ebf ("bpf: Augment raw_tp arguments with PTR_MAYBE_NULL").
[0]:
BUG: kernel NULL pointer dereference, address: 0000000000000010 PF: supervisor read access in kernel mode PF: error_code(0x0000) - not-present page PGD 0 P4D 0 PREEMPT SMP RIP: 0010:bpf_prog_5e21a6db8fcff1aa_drop+0x10/0x2d Call Trace: <TASK> ? __die+0x1f/0x60 ? page_fault_oops+0x148/0x420 ? search_bpf_extables+0x5b/0x70 ? fixup_exception+0x27/0x2c0 ? exc_page_fault+0x75/0x170 ? asm_exc_page_fault+0x22/0x30 ? bpf_prog_5e21a6db8fcff1aa_drop+0x10/0x2d bpf_trace_run4+0x68/0xd0 ? unix_stream_connect+0x1f4/0x6f0 sk_skb_reason_drop+0x90/0x120 unix_stream_connect+0x1f4/0x6f0 __sys_connect+0x7f/0xb0 __x64_sys_connect+0x14/0x20 do_syscall_64+0x47/0xc30 entry_SYSCALL_64_after_hwframe+0x4b/0x53
--- kernel/bpf/btf.c | 2 ++ 1 file changed, 2 insertions(+)
kernel/bpf/btf.c +2 -0
@@ -6483,6 +6483,8 @@ static const struct bpf_raw_tp_null_args raw_tp_null_args[] = {/* rxrpc */ { "rxrpc_recvdata", 0x1 }, { "rxrpc_resend", 0x10 }, +/* skb */ + {"kfree_skb", 0x1000},/* sunrpc */ { "xs_stream_read_data", 0x1 },/* ... from xprt_cong_event event class */
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 86/154 bpf: Fix softlockup in arena_map_free on 64k page kernel
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alan Maguire <[email protected]>
[ Upstream commit 517e8a7835e8cfb398a0aeb0133de50e31cae32b ]
On an aarch64 kernel with CONFIG_PAGE_SIZE_64KB=y, arena_htab tests cause a segmentation fault and soft lockup. The same failure is not observed with 4k pages on aarch64.
It turns out arena_map_free() is calling apply_to_existing_page_range() with the address returned by bpf_arena_get_kern_vm_start(). If this address is not page-aligned the code ends up calling apply_to_pte_range() with that unaligned address causing soft lockup.
Fix it by round up GUARD_SZ to PAGE_SIZE << 1 so that the division by 2 in bpf_arena_get_kern_vm_start() returns a page-aligned value.
--- kernel/bpf/arena.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/bpf/arena.c +1 -1
@@ -37,7 +37,7 @@*/ /* number of bytes addressable by LDX/STX insn with 16-bit 'off' field */ -#define GUARD_SZ (1ull << sizeof_field(struct bpf_insn, off) * 8) +#define GUARD_SZ round_up(1ull << sizeof_field(struct bpf_insn, off) * 8, PAGE_SIZE << 1)#define KERN_VM_SZ (SZ_4G + GUARD_SZ)struct bpf_arena {
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 87/154 arm64: dts: rockchip: adjust SMMU interrupt type on rk3588
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Patrick Wildt <[email protected]>
[ Upstream commit 8546cfd08aa4b982acd2357403a1f15495d622ec ]
The SMMU architecture requires wired interrupts to be edge triggered, which does not align with the DT description for the RK3588. This leads to interrupt storms, as the SMMU continues to hold the pin high and only pulls it down for a short amount when issuing an IRQ. Update the DT description to be in line with the spec and perceived reality.
--- arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi +8 -8
@@ -549,10 +549,10 @@ usb_host2_xhci: usb@fcd00000 { mmu600_pcie: iommu@fc900000 { compatible = "arm,smmu-v3"; reg = <0x0 0xfc900000 0x0 0x200000>; - interrupts = <GIC_SPI 369 IRQ_TYPE_LEVEL_HIGH 0>, - <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH 0>, - <GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH 0>, - <GIC_SPI 367 IRQ_TYPE_LEVEL_HIGH 0>; + interrupts = <GIC_SPI 369 IRQ_TYPE_EDGE_RISING 0>, + <GIC_SPI 371 IRQ_TYPE_EDGE_RISING 0>, + <GIC_SPI 374 IRQ_TYPE_EDGE_RISING 0>, + <GIC_SPI 367 IRQ_TYPE_EDGE_RISING 0>; interrupt-names = "eventq", "gerror", "priq", "cmdq-sync"; #iommu-cells = <1>; status = "disabled";
@@ -561,10 +561,10 @@ mmu600_pcie: iommu@fc900000 { mmu600_php: iommu@fcb00000 { compatible = "arm,smmu-v3"; reg = <0x0 0xfcb00000 0x0 0x200000>; - interrupts = <GIC_SPI 381 IRQ_TYPE_LEVEL_HIGH 0>, - <GIC_SPI 383 IRQ_TYPE_LEVEL_HIGH 0>, - <GIC_SPI 386 IRQ_TYPE_LEVEL_HIGH 0>, - <GIC_SPI 379 IRQ_TYPE_LEVEL_HIGH 0>; + interrupts = <GIC_SPI 381 IRQ_TYPE_EDGE_RISING 0>, + <GIC_SPI 383 IRQ_TYPE_EDGE_RISING 0>, + <GIC_SPI 386 IRQ_TYPE_EDGE_RISING 0>, + <GIC_SPI 379 IRQ_TYPE_EDGE_RISING 0>; interrupt-names = "eventq", "gerror", "priq", "cmdq-sync"; #iommu-cells = <1>; status = "disabled";
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 58/154 ibmvnic: Dont reference skb after sending to VIOS
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nick Child <[email protected]>
[ Upstream commit bdf5d13aa05ec314d4385b31ac974d6c7e0997c9 ]
Previously, after successfully flushing the xmit buffer to VIOS, the tx_bytes stat was incremented by the length of the skb.
It is invalid to access the skb memory after sending the buffer to the VIOS because, at any point after sending, the VIOS can trigger an interrupt to free this memory. A race between reading skb->len and freeing the skb is possible (especially during LPM) and will result in use-after-free:
==================================================================
BUG: KASAN: slab-use-after-free in ibmvnic_xmit+0x75c/0x1808 [ibmvnic] Read of size 4 at addr c00000024eb48a70 by task hxecom/14495 <...> Call Trace: [c000000118f66cf0] [c0000000018cba6c] dump_stack_lvl+0x84/0xe8 (unreliable) [c000000118f66d20] [c0000000006f0080] print_report+0x1a8/0x7f0 [c000000118f66df0] [c0000000006f08f0] kasan_report+0x128/0x1f8 [c000000118f66f00] [c0000000006f2868] __asan_load4+0xac/0xe0 [c000000118f66f20] [c0080000046eac84] ibmvnic_xmit+0x75c/0x1808 [ibmvnic] [c000000118f67340] [c0000000014be168] dev_hard_start_xmit+0x150/0x358 <...> Freed by task 0: kasan_save_stack+0x34/0x68 kasan_save_track+0x2c/0x50 kasan_save_free_info+0x64/0x108 __kasan_mempool_poison_object+0x148/0x2d4 napi_skb_cache_put+0x5c/0x194 net_tx_action+0x154/0x5b8 handle_softirqs+0x20c/0x60c do_softirq_own_stack+0x6c/0x88 <...> The buggy address belongs to the object at c00000024eb48a00 which belongs to the cache skbuff_head_cache of size 224 ==================================================================
--- drivers/net/ethernet/ibm/ibmvnic.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/net/ethernet/ibm/ibmvnic.c +3 -1
@@ -2408,6 +2408,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)dma_addr_t data_dma_addr;struct netdev_queue *txq;unsigned long lpar_rc; +unsigned int skblen;union sub_crq tx_crq;unsigned int offset;bool use_scrq_send_direct = false;
@@ -2522,6 +2523,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev) tx_buff->skb = skb; tx_buff->index = bufidx; tx_buff->pool_index = queue_num; + skblen = skb->len;memset (&tx_crq,0 ,sizeof (tx_crq)); tx_crq.v1.first =IBMVNIC_CRQ_CMD ;
@@ -2614,7 +2616,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)netif_stop_subqueue (netdev, queue_num); } - tx_bytes += skb->len; + tx_bytes += skblen;txq_trans_cond_update (txq); ret =NETDEV_TX_OK ; goto out;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 59/154 sockmap, vsock: For connectible sockets allow only connected
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michal Luczaj <[email protected]>
[ Upstream commit 8fb5bb169d17cdd12c2dcc2e96830ed487d77a0f ]
sockmap expects all vsocks to have a transport assigned, which is expressed in vsock_proto::psock_update_sk_prot(). However, there is an edge case where an unconnected (connectible) socket may lose its previously assigned transport. This is handled with a NULL check in the vsock/BPF recv path.
Another design detail is that listening vsocks are not supposed to have any transport assigned at all. Which implies they are not supported by the sockmap. But this is complicated by the fact that a socket, before switching to TCP_LISTEN, may have had some transport assigned during a failed connect() attempt. Hence, we may end up with a listening vsock in a sockmap, which blows up quickly:
KASAN: null-ptr-deref in range [0x0000000000000120-0x0000000000000127] CPU: 7 UID: 0 PID: 56 Comm: kworker/7:0 Not tainted 6.14.0-rc1+ Workqueue: vsock-loopback vsock_loopback_work RIP: 0010:vsock_read_skb+0x4b/0x90 Call Trace: sk_psock_verdict_data_ready+0xa4/0x2e0 virtio_transport_recv_pkt+0x1ca8/0x2acc vsock_loopback_work+0x27d/0x3f0 process_one_work+0x846/0x1420 worker_thread+0x5b3/0xf80 kthread+0x35a/0x700 ret_from_fork+0x2d/0x70 ret_from_fork_asm+0x1a/0x30
For connectible sockets, instead of relying solely on the state of vsk->transport, tell sockmap to only allow those representing established connections. This aligns with the behaviour for AF_INET and AF_UNIX.
--- net/core/sock_map.c | 3 +++ 1 file changed, 3 insertions(+)
net/core/sock_map.c +3 -0
@@ -541,6 +541,9 @@ static bool sock_map_sk_state_allowed(const struct sock *sk)return (1 << sk->sk_state) & (TCPF_ESTABLISHED |TCPF_LISTEN );if (sk_is_stream_unix (sk))return (1 << sk->sk_state) &TCPF_ESTABLISHED ; +if (sk_is_vsock (sk) && + (sk->sk_type ==SOCK_STREAM || sk->sk_type ==SOCK_SEQPACKET )) +return (1 << sk->sk_state) &TCPF_ESTABLISHED ;return true; }
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 60/154 vsock/bpf: Warn on socket without transport
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michal Luczaj <[email protected]>
[ Upstream commit 857ae05549ee2542317e7084ecaa5f8536634dd9 ]
In the spirit of commit 91751e248256 ("vsock: prevent null-ptr-deref in vsock_*[has_data|has_space]"), armorize the "impossible" cases with a warning.
--- net/vmw_vsock/af_vsock.c | 3 +++ net/vmw_vsock/vsock_bpf.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-)
net/vmw_vsock/af_vsock.c +3 -0
@@ -1189,6 +1189,9 @@ static int vsock_read_skb(struct sock *sk, skb_read_actor_t read_actor) {struct vsock_sock *vsk =vsock_sk (sk); +if (WARN_ON_ONCE (!vsk->transport)) +return -ENODEV ; +return vsk->transport->read_skb (vsk, read_actor); }
net/vmw_vsock/vsock_bpf.c +1 -1
@@ -87,7 +87,7 @@ static int vsock_bpf_recvmsg(struct sock *sk, struct msghdr *msg,lock_sock (sk); vsk =vsock_sk (sk); -if (!vsk->transport) { +if (WARN_ON_ONCE (!vsk->transport)) { copied = -ENODEV ; goto out; }
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 61/154 tcp: adjust rcvq_space after updating scaling ratio
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jakub Kicinski <[email protected]>
[ Upstream commit f5da7c45188eea71394bf445655cae2df88a7788 ]
Since commit under Fixes we set the window clamp in accordance to newly measured rcvbuf scaling_ratio. If the scaling_ratio decreased significantly we may put ourselves in a situation where windows become smaller than rcvq_space, preventing tcp_rcv_space_adjust() from increasing rcvbuf.
The significant decrease of scaling_ratio is far more likely since commit 697a6c8cec03 ("tcp: increase the default TCP scaling ratio"), which increased the "default" scaling ratio from ~30% to 50%.
Hitting the bad condition depends a lot on TCP tuning, and drivers at play. One of Meta's workloads hits it reliably under following conditions:
- default rcvbuf of 125k
- sender MTU 1500, receiver MTU 5000
- driver settles on scaling_ratio of 78 for the config above.
Initial rcvq_space gets calculated as TCP_INIT_CWND * tp->advmss (10 * 5k = 50k). Once we find out the true scaling ratio and MSS we clamp the windows to 38k. Triggering the condition also depends on the message sequence of this workload. I can't repro the problem with simple iperf or TCP_RR-style tests.
--- net/ipv4/tcp_input.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
net/ipv4/tcp_input.c +9 -3
@@ -243,9 +243,15 @@ static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb)do_div (val, skb->truesize);tcp_sk (sk)->scaling_ratio = val ? val :1 ; -if (old_ratio !=tcp_sk (sk)->scaling_ratio) -WRITE_ONCE (tcp_sk (sk)->window_clamp, -tcp_win_from_space (sk, sk->sk_rcvbuf)); +if (old_ratio !=tcp_sk (sk)->scaling_ratio) { +struct tcp_sock *tp =tcp_sk (sk); + + val =tcp_win_from_space (sk, sk->sk_rcvbuf); +tcp_set_window_clamp (sk, val); + +if (tp->window_clamp < tp->rcvq_space.space) + tp->rcvq_space.space = tp->window_clamp; + } } icsk->icsk_ack.rcv_mss = min_t(unsigned int, len,tcp_sk (sk)->advmss);
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 62/154 net: pse-pd: Avoid setting max_uA in regulator constraints
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kory Maincent <[email protected]>
[ Upstream commit 675d0e3cacc3ae7c29294a5f6a820187f862ad8b ]
Setting the max_uA constraint in the regulator API imposes a current limit during the regulator registration process. This behavior conflicts with preserving the maximum PI power budget configuration across reboots.
Instead, compare the desired current limit to MAX_PI_CURRENT in the pse_pi_set_current_limit() function to ensure proper handling of the power budget.
Stable-dep-of: f6093c5ec74d ("net: pse-pd: pd692x0: Fix power limit retrieval")
--- drivers/net/pse-pd/pse_core.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/net/pse-pd/pse_core.c +4 -3
@@ -357,6 +357,9 @@ static int pse_pi_set_current_limit(struct regulator_dev *rdev, int min_uA,if (!ops->pi_set_current_limit)return -EOPNOTSUPP ; +if (max_uA >MAX_PI_CURRENT ) +return -ERANGE ; + id =rdev_get_id (rdev);mutex_lock (&pcdev->lock); ret = ops->pi_set_current_limit (pcdev, id, max_uA);
@@ -403,11 +406,9 @@ devm_pse_pi_regulator_register(struct pse_controller_dev *pcdev, rinit_data->constraints.valid_ops_mask =REGULATOR_CHANGE_STATUS ; -if (pcdev->ops->pi_set_current_limit) { +if (pcdev->ops->pi_set_current_limit) rinit_data->constraints.valid_ops_mask |=REGULATOR_CHANGE_CURRENT ; - rinit_data->constraints.max_uA =MAX_PI_CURRENT ; - } rinit_data->supply_regulator ="vpwr" ;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 63/154 net: pse-pd: Use power limit at driver side instead of current limit
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kory Maincent <[email protected]>
[ Upstream commit e0a5e2bba38aa61a900934b45d6e846e0a6d7524 ]
The regulator framework uses current limits, but the PSE standard and known PSE controllers rely on power limits. Instead of converting current to power within each driver, perform the conversion in the PSE core. This avoids redundancy in driver implementation and aligns better with the standard, simplifying driver development.
Remove at the same time the _pse_ethtool_get_status() function which is not needed anymore.
Stable-dep-of: f6093c5ec74d ("net: pse-pd: pd692x0: Fix power limit retrieval")
--- drivers/net/pse-pd/pd692x0.c | 45 ++++------------- drivers/net/pse-pd/pse_core.c | 91 ++++++++++++++++------------------- include/linux/pse-pd/pse.h | 16 +++--- 3 files changed, 57 insertions(+), 95 deletions(-)
drivers/net/pse-pd/pd692x0.c +10 -35
@@ -999,13 +999,12 @@ static int pd692x0_pi_get_voltage(struct pse_controller_dev *pcdev, int id)return (buf.sub[0 ] <<8 | buf.sub[1 ]) *100000 ; } -static int pd692x0_pi_get_current_limit (struct pse_controller_dev *pcdev, -int id) +static int pd692x0_pi_get_pw_limit (struct pse_controller_dev *pcdev, +int id) {struct pd692x0_priv *priv =to_pd692x0_priv (pcdev);struct pd692x0_msg msg, buf = {0 }; -int mW, uV, uA, ret; -s64 tmp_64; +int ret; msg = pd692x0_msg_template_list[PD692X0_MSG_GET_PORT_PARAM ]; msg.sub[2 ] = id;
@@ -1013,48 +1012,24 @@ static int pd692x0_pi_get_current_limit(struct pse_controller_dev *pcdev,if (ret <0 )return ret; - ret =pd692x0_pi_get_pw_from_table (buf.data[2 ], buf.data[3 ]); -if (ret <0 ) -return ret; - mW = ret; - - ret =pd692x0_pi_get_voltage (pcdev, id); -if (ret <0 ) -return ret; - uV = ret; - - tmp_64 = mW; - tmp_64 *=1000000000ull ; -/* uA = mW * 1000000000 / uV */ - uA =DIV_ROUND_CLOSEST_ULL (tmp_64, uV); -return uA; +return pd692x0_pi_get_pw_from_table (buf.data[2 ], buf.data[3 ]); } -static int pd692x0_pi_set_current_limit (struct pse_controller_dev *pcdev, -int id,int max_uA) +static int pd692x0_pi_set_pw_limit (struct pse_controller_dev *pcdev, +int id,int max_mW) {struct pd692x0_priv *priv =to_pd692x0_priv (pcdev);struct device *dev = &priv->client->dev;struct pd692x0_msg msg, buf = {0 }; -int uV, ret, mW; -s64 tmp_64; +int ret; ret =pd692x0_fw_unavailable (priv);if (ret)return ret; - ret =pd692x0_pi_get_voltage (pcdev, id); -if (ret <0 ) -return ret; - uV = ret; - msg = pd692x0_msg_template_list[PD692X0_MSG_SET_PORT_PARAM ]; msg.sub[2 ] = id; - tmp_64 = uV; - tmp_64 *= max_uA; -/* mW = uV * uA / 1000000000 */ - mW =DIV_ROUND_CLOSEST_ULL (tmp_64,1000000000 ); - ret =pd692x0_pi_set_pw_from_table (dev, &msg, mW); + ret =pd692x0_pi_set_pw_from_table (dev, &msg, max_mW);if (ret)return ret;
@@ -1068,8 +1043,8 @@ static const struct pse_controller_ops pd692x0_ops = { .pi_disable = pd692x0_pi_disable, .pi_is_enabled = pd692x0_pi_is_enabled, .pi_get_voltage = pd692x0_pi_get_voltage, - .pi_get_current_limit = pd692x0_pi_get_current_limit, - .pi_set_current_limit = pd692x0_pi_set_current_limit, + .pi_get_pw_limit = pd692x0_pi_get_pw_limit, + .pi_set_pw_limit = pd692x0_pi_set_pw_limit, };#define PD692X0_FW_LINE_MAX_SZ 0xff
drivers/net/pse-pd/pse_core.c +41 -50
148 lines not on this page · raw message
include/linux/pse-pd/pse.h +6 -10
@@ -75,12 +75,8 @@ struct pse_control_status {* @pi_disable: Configure the PSE PI as disabled. * @pi_get_voltage: Return voltage similarly to get_voltage regulator * callback. -* @pi_get_current_limit: Get the configured current limit similarly to -* get_current_limit regulator callback. -* @pi_set_current_limit: Configure the current limit similarly to -* set_current_limit regulator callback. -* Should not return an error in case of MAX_PI_CURRENT -* current value set. +* @pi_get_pw_limit: Get the configured power limit of the PSE PI. +* @pi_set_pw_limit: Configure the power limit of the PSE PI. */ struct pse_controller_ops { int (*ethtool_get_status)(struct pse_controller_dev *pcdev,
@@ -91,10 +87,10 @@ struct pse_controller_ops {int (*pi_enable)(struct pse_controller_dev *pcdev,int id);int (*pi_disable)(struct pse_controller_dev *pcdev,int id);int (*pi_get_voltage)(struct pse_controller_dev *pcdev,int id); -int (*pi_get_current_limit)(struct pse_controller_dev *pcdev, -int id); -int (*pi_set_current_limit)(struct pse_controller_dev *pcdev, -int id,int max_uA); +int (*pi_get_pw_limit)(struct pse_controller_dev *pcdev, +int id); +int (*pi_set_pw_limit)(struct pse_controller_dev *pcdev, +int id,int max_mW); };struct module ;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 54/154 net/sched: cls_api: fix error handling causing NULL dereference
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pierre Riteau <[email protected]>
[ Upstream commit 071ed42cff4fcdd89025d966d48eabef59913bf2 ]
tcf_exts_miss_cookie_base_alloc() calls xa_alloc_cyclic() which can return 1 if the allocation succeeded after wrapping. This was treated as an error, with value 1 returned to caller tcf_exts_init_ex() which sets exts->actions to NULL and returns 1 to caller fl_change().
fl_change() treats err == 1 as success, calling tcf_exts_validate_ex() which calls tcf_action_init() with exts->actions as argument, where it is dereferenced.
Example trace:
BUG: kernel NULL pointer dereference, address: 0000000000000000 CPU: 114 PID: 16151 Comm: handler114 Kdump: loaded Not tainted 5.14.0-503.16.1.el9_5.x86_64 #1 RIP: 0010:tcf_action_init+0x1f8/0x2c0 Call Trace: tcf_action_init+0x1f8/0x2c0 tcf_exts_validate_ex+0x175/0x190 fl_change+0x537/0x1120 [cls_flower]
--- net/sched/cls_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/sched/cls_api.c +1 -1
@@ -97,7 +97,7 @@ tcf_exts_miss_cookie_base_alloc(struct tcf_exts *exts, struct tcf_proto *tp, err =xa_alloc_cyclic (&tcf_exts_miss_cookies_xa, &n->miss_cookie_base, n, xa_limit_32b, &next,GFP_KERNEL ); -if (err) +if (err <0 ) goto err_xa_alloc; exts->miss_cookie_node = n;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 89/154 md/raid*: Fix the set_queue_limits implementations
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bart Van Assche <[email protected]>
[ Upstream commit fbe8f2fa971c537571994a0df532c511c4fb5537 ]
queue_limits_cancel_update() must only be called if queue_limits_start_update() is called first. Remove the queue_limits_cancel_update() calls from the raid*_set_limits() functions because there is no corresponding queue_limits_start_update() call.
--- drivers/md/raid0.c | 4 +--- drivers/md/raid1.c | 4 +--- drivers/md/raid10.c | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-)
drivers/md/raid0.c +1 -3
@@ -385,10 +385,8 @@ static int raid0_set_limits(struct mddev *mddev) lim.io_min = mddev->chunk_sectors <<9 ; lim.io_opt = lim.io_min * mddev->raid_disks; err =mddev_stack_rdev_limits (mddev, &lim,MDDEV_STACK_INTEGRITY ); -if (err) { -queue_limits_cancel_update (mddev->gendisk->queue); +if (err)return err; - }return queue_limits_set (mddev->gendisk->queue, &lim); }
drivers/md/raid1.c +1 -3
@@ -3171,10 +3171,8 @@ static int raid1_set_limits(struct mddev *mddev)md_init_stacking_limits (&lim); lim.max_write_zeroes_sectors =0 ; err =mddev_stack_rdev_limits (mddev, &lim,MDDEV_STACK_INTEGRITY ); -if (err) { -queue_limits_cancel_update (mddev->gendisk->queue); +if (err)return err; - }return queue_limits_set (mddev->gendisk->queue, &lim); }
drivers/md/raid10.c +1 -3
@@ -3963,10 +3963,8 @@ static int raid10_set_queue_limits(struct mddev *mddev) lim.io_min = mddev->chunk_sectors <<9 ; lim.io_opt = lim.io_min *raid10_nr_stripes (conf); err =mddev_stack_rdev_limits (mddev, &lim,MDDEV_STACK_INTEGRITY ); -if (err) { -queue_limits_cancel_update (mddev->gendisk->queue); +if (err)return err; - }return queue_limits_set (mddev->gendisk->queue, &lim); }
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 98/154 drm/msm/dsi/phy: Protect PHY_CMN_CLK_CFG1 against clock driver
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Kozlowski <[email protected]>
[ Upstream commit 5a97bc924ae0804b8dbf627e357acaa5ef761483 ]
PHY_CMN_CLK_CFG1 register is updated by the PHY driver and by a mux clock from Common Clock Framework:devm_clk_hw_register_mux_parent_hws(). There could be a path leading to concurrent and conflicting updates between PHY driver and clock framework, e.g. changing the mux and enabling PLL clocks.
Add dedicated spinlock to be sure all PHY_CMN_CLK_CFG1 updates are synchronized.
While shuffling the code, define and use PHY_CMN_CLK_CFG1 bitfields to make the code more readable and obvious.
Patchwork: https://patchwork.freedesktop.org/patch/637378/
--- drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 35 ++++++++++++------- .../drm/msm/registers/display/dsi_phy_7nm.xml | 5 ++- 2 files changed, 26 insertions(+), 14 deletions(-)
drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c +22 -13
@@ -83,6 +83,9 @@ struct dsi_pll_7nm {/* protects REG_DSI_7nm_PHY_CMN_CLK_CFG0 register */ spinlock_t postdiv_lock; +/* protects REG_DSI_7nm_PHY_CMN_CLK_CFG1 register */ +spinlock_t pclk_mux_lock; +struct pll_7nm_cached_state cached_state;struct dsi_pll_7nm *slave;
@@ -381,22 +384,32 @@ static void dsi_pll_cmn_clk_cfg0_write(struct dsi_pll_7nm *pll, u32 val)spin_unlock_irqrestore (&pll->postdiv_lock, flags); } -static void dsi_pll_disable_global_clk (struct dsi_pll_7nm *pll) +static void dsi_pll_cmn_clk_cfg1_update (struct dsi_pll_7nm *pll,u32 mask, +u32 val) { +unsigned long flags;u32 data; +spin_lock_irqsave (&pll->pclk_mux_lock, flags); data =readl (pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); -writel (data & ~BIT (5 ), pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); + data &= ~mask; + data |= val & mask; + +writel (data, pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); +spin_unlock_irqrestore (&pll->pclk_mux_lock, flags); +} + +static void dsi_pll_disable_global_clk (struct dsi_pll_7nm *pll) +{ +dsi_pll_cmn_clk_cfg1_update (pll, DSI_7nm_PHY_CMN_CLK_CFG1_CLK_EN,0 ); }static void dsi_pll_enable_global_clk (struct dsi_pll_7nm *pll) { -u32 data; +u32 cfg_1 = DSI_7nm_PHY_CMN_CLK_CFG1_CLK_EN | DSI_7nm_PHY_CMN_CLK_CFG1_CLK_EN_SEL;writel (0x04 , pll->phy->base + REG_DSI_7nm_PHY_CMN_CTRL_3); - - data =readl (pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); -writel (data |BIT (5 ) |BIT (4 ), pll->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); +dsi_pll_cmn_clk_cfg1_update (pll, cfg_1, cfg_1); }static void dsi_pll_phy_dig_reset (struct dsi_pll_7nm *pll)
@@ -574,7 +587,6 @@ static int dsi_7nm_pll_restore_state(struct msm_dsi_phy *phy) {struct dsi_pll_7nm *pll_7nm =to_pll_7nm (phy->vco_hw);struct pll_7nm_cached_state *cached = &pll_7nm->cached_state; -void __iomem *phy_base = pll_7nm->phy->base;u32 val;int ret;
@@ -586,11 +598,7 @@ static int dsi_7nm_pll_restore_state(struct msm_dsi_phy *phy)dsi_pll_cmn_clk_cfg0_write (pll_7nm,DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_3_0 (cached->bit_clk_div) |DSI_7nm_PHY_CMN_CLK_CFG0_DIV_CTRL_7_4 (cached->pix_clk_div)); - - val =readl (phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); - val &= ~0x3 ; - val |= cached->pll_mux; -writel (val, phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); +dsi_pll_cmn_clk_cfg1_update (pll_7nm,0x3 , cached->pll_mux); ret = dsi_pll_7nm_vco_set_rate(phy->vco_hw, pll_7nm->vco_current_rate,
@@ -743,7 +751,7 @@ static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm, struct clk_hw **provide pll_by_2_bit, }), 2, 0, pll_7nm->phy->base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, - 0, 1, 0, NULL); + 0, 1, 0, &pll_7nm->pclk_mux_lock);if (IS_ERR (hw)) { ret =PTR_ERR (hw); goto fail;
@@ -788,6 +796,7 @@ static int dsi_pll_7nm_init(struct msm_dsi_phy *phy) pll_7nm_list[phy->id] = pll_7nm;spin_lock_init (&pll_7nm->postdiv_lock); +spin_lock_init (&pll_7nm->pclk_mux_lock); pll_7nm->phy = phy;
drivers/gpu/drm/msm/registers/display/dsi_phy_7nm.xml +4 -1
@@ -13,7 +13,10 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> <bitfield name="DIV_CTRL_3_0" low="0" high="3" type="uint"/> <bitfield name="DIV_CTRL_7_4" low="4" high="7" type="uint"/> </reg32> - <reg32 offset="0x00014" name="CLK_CFG1"/> + <reg32 offset="0x00014" name="CLK_CFG1"> + <bitfield name="CLK_EN" pos="5" type="boolean"/> + <bitfield name="CLK_EN_SEL" pos="4" type="boolean"/> + </reg32> <reg32 offset="0x00018" name="GLBL_CTRL"/> <reg32 offset="0x0001c" name="RBUF_CTRL"/> <reg32 offset="0x00020" name="VREG_CTRL_0"/>
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 99/154 drm/msm/dsi/phy: Do not overwite PHY_CMN_CLK_CFG1 when choosing bitclk source
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Kozlowski <[email protected]>
[ Upstream commit 73f69c6be2a9f22c31c775ec03c6c286bfe12cfa ]
PHY_CMN_CLK_CFG1 register has four fields being used in the driver: DSI clock divider, source of bitclk and two for enabling the DSI PHY PLL clocks.
dsi_7nm_set_usecase() sets only the source of bitclk, so should leave all other bits untouched. Use newly introduced dsi_pll_cmn_clk_cfg1_update() to update respective bits without overwriting the rest.
While shuffling the code, define and use PHY_CMN_CLK_CFG1 bitfields to make the code more readable and obvious.
Patchwork: https://patchwork.freedesktop.org/patch/637380/
--- drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 4 ++-- drivers/gpu/drm/msm/registers/display/dsi_phy_7nm.xml | 1 + 2 files changed, 3 insertions(+), 2 deletions(-)
drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c +2 -2
@@ -617,7 +617,6 @@ static int dsi_7nm_pll_restore_state(struct msm_dsi_phy *phy)static int dsi_7nm_set_usecase (struct msm_dsi_phy *phy) {struct dsi_pll_7nm *pll_7nm =to_pll_7nm (phy->vco_hw); -void __iomem *base = phy->base;u32 data =0x0 ;/* internal PLL */ DBG ("DSI PLL%d" , pll_7nm->phy->id);
@@ -636,7 +635,8 @@ static int dsi_7nm_set_usecase(struct msm_dsi_phy *phy) }/* set PLL src */ -writel (data <<2 , base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); +dsi_pll_cmn_clk_cfg1_update (pll_7nm, DSI_7nm_PHY_CMN_CLK_CFG1_BITCLK_SEL__MASK, +DSI_7nm_PHY_CMN_CLK_CFG1_BITCLK_SEL (data));return 0 ; }
drivers/gpu/drm/msm/registers/display/dsi_phy_7nm.xml +1 -0
@@ -16,6 +16,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd"> <reg32 offset="0x00014" name="CLK_CFG1"> <bitfield name="CLK_EN" pos="5" type="boolean"/> <bitfield name="CLK_EN_SEL" pos="4" type="boolean"/> + <bitfield name="BITCLK_SEL" low="2" high="3" type="uint"/> </reg32> <reg32 offset="0x00018" name="GLBL_CTRL"/> <reg32 offset="0x0001c" name="RBUF_CTRL"/>
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 100/154 nvme: tcp: Fix compilation warning with W=1
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Damien Le Moal <[email protected]>
[ Upstream commit cd513e0434c3e736c549bc99bf7982658b25114d ]
When compiling with W=1, a warning result for the function nvme_tcp_set_queue_io_cpu():
host/tcp.c:1578: warning: Function parameter or struct member 'queue' not described in 'nvme_tcp_set_queue_io_cpu' host/tcp.c:1578: warning: expecting prototype for Track the number of queues assigned to each cpu using a global per(). Prototype was for nvme_tcp_set_queue_io_cpu() instead
Avoid this warning by using the regular comment format for the function nvme_tcp_set_queue_io_cpu() instead of the kdoc comment format.
--- drivers/nvme/host/tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/nvme/host/tcp.c +1 -1
@@ -1565,7 +1565,7 @@ static bool nvme_tcp_poll_queue(struct nvme_tcp_queue *queue) ctrl->io_queues[HCTX_TYPE_POLL ]; } -/** +/* * Track the number of queues assigned to each cpu using a global per-cpu * counter and select the least used cpu from the mq_map. Our goal is to spread * different controllers I/O threads across different cpu cores.
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 101/154 nvme-tcp: fix connect failure on receiving partial ICResp PDU
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Caleb Sander Mateos <[email protected]>
[ Upstream commit 578539e0969028f711c34d9a4565931edfe1d730 ]
nvme_tcp_init_connection() attempts to receive an ICResp PDU but only checks that the return value from recvmsg() is non-negative. If the sender closes the TCP connection or sends fewer than 128 bytes, this check will pass even though the full PDU wasn't received.
Ensure the full ICResp PDU is received by checking that recvmsg() returns the expected 128 bytes.
Additionally set the MSG_WAITALL flag for recvmsg(), as a sender could split the ICResp over multiple TCP frames. Without MSG_WAITALL, recvmsg() could return prematurely with only part of the PDU.
--- drivers/nvme/host/tcp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/nvme/host/tcp.c +4 -1
@@ -1449,11 +1449,14 @@ static int nvme_tcp_init_connection(struct nvme_tcp_queue *queue) msg.msg_control = cbuf; msg.msg_controllen =sizeof (cbuf); } + msg.msg_flags =MSG_WAITALL ; ret =kernel_recvmsg (queue->sock, &msg, &iov,1 , iov.iov_len, msg.msg_flags); -if (ret <0 ) { +if (ret <sizeof (*icresp)) {pr_warn ("queue %d: failed to receive icresp, error %d\n" ,nvme_tcp_queue_id (queue), ret); +if (ret >=0 ) + ret = -ECONNRESET ; goto free_icresp; } ret = -ENOTCONN ;
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 102/154 nvme/ioctl: add missing space in err message
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Caleb Sander Mateos <[email protected]>
[ Upstream commit 487a3ea7b1b8ba2ca7d2c2bb3c3594dc360d6261 ]
nvme_validate_passthru_nsid() logs an err message whose format string is split over 2 lines. There is a missing space between the two pieces, resulting in log lines like "... does not match nsid (1)of namespace". Add the missing space between ")" and "of". Also combine the format string pieces onto a single line to make the err message easier to grep.
--- drivers/nvme/host/ioctl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/nvme/host/ioctl.c +1 -2
@@ -276,8 +276,7 @@ static bool nvme_validate_passthru_nsid(struct nvme_ctrl *ctrl, {if (ns && nsid != ns->head->ns_id) {dev_err (ctrl->device, -"%s: nsid (%u) in cmd does not match nsid (%u)" -"of namespace\n" , +"%s: nsid (%u) in cmd does not match nsid (%u) of namespace\n" , current->comm, nsid, ns->head->ns_id);return false; }
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 103/154 bpf: skip non exist keys in generic_map_lookup_batch
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yan Zhai <[email protected]>
[ Upstream commit 5644c6b50ffee0a56c1e01430a8c88e34decb120 ]
The generic_map_lookup_batch currently returns EINTR if it fails with ENOENT and retries several times on bpf_map_copy_value. The next batch would start from the same location, presuming it's a transient issue. This is incorrect if a map can actually have "holes", i.e. "get_next_key" can return a key that does not point to a valid value. At least the array of maps type may contain such holes legitly. Right now these holes show up, generic batch lookup cannot proceed any more. It will always fail with EINTR errors.
Rather, do not retry in generic_map_lookup_batch. If it finds a non existing element, skip to the next key. This simple solution comes with a price that transient errors may not be recovered, and the iteration might cycle back to the first key under parallel deletion. For example, Hou Tao <[email protected]> pointed out a following scenario:
For LPM trie map:
(1) ->map_get_next_key(map, prev_key, key) returns a valid key
(2) bpf_map_copy_value() return -ENOMENT
It means the key must be deleted concurrently.
(3) goto next_key
It swaps the prev_key and key
(4) ->map_get_next_key(map, prev_key, key) againprev_key points to a non-existing key, for LPM trie it will treat just like prev_key=NULL case, the returned key will be duplicated.
With the retry logic, the iteration can continue to the key next to the deleted one. But if we directly skip to the next key, the iteration loop would restart from the first key for the lpm_trie type.
However, not all races may be recovered. For example, if current key is deleted after instead of before bpf_map_copy_value, or if the prev_key also gets deleted, then the loop will still restart from the first key for lpm_tire anyway. For generic lookup it might be better to stay simple, i.e. just skip to the next key. To guarantee that the output keys are not duplicated, it is better to implement map type specific batch operations, which can properly lock the trie and synchronize with concurrent mutators.
--- kernel/bpf/syscall.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-)
kernel/bpf/syscall.c +5 -13
@@ -1872,8 +1872,6 @@ int generic_map_update_batch(struct bpf_map *map, struct file *map_file,return err; } -#define MAP_LOOKUP_RETRIES 3 -int generic_map_lookup_batch (struct bpf_map *map,const union bpf_attr *attr,union bpf_attr __user *uattr)
@@ -1883,8 +1881,8 @@ int generic_map_lookup_batch(struct bpf_map *map,void __user *values =u64_to_user_ptr (attr->batch.values);void __user *keys =u64_to_user_ptr (attr->batch.keys);void *buf, *buf_prevkey, *prev_key, *key, *value; -int err, retry =MAP_LOOKUP_RETRIES ;u32 value_size, cp, max_count; +int err;if (attr->batch.elem_flags & ~BPF_F_LOCK )return -EINVAL ;
@@ -1930,14 +1928,8 @@ int generic_map_lookup_batch(struct bpf_map *map, err =bpf_map_copy_value (map, key, value, attr->batch.elem_flags); -if (err == -ENOENT ) { -if (retry) { - retry--; -continue ; - } - err = -EINTR ; -break ; - } +if (err == -ENOENT ) + goto next_key;if (err) goto free_buf;
@@ -1952,12 +1944,12 @@ int generic_map_lookup_batch(struct bpf_map *map, goto free_buf; } + cp++; +next_key:if (!prev_key) prev_key = buf_prevkey;swap (prev_key, key); - retry =MAP_LOOKUP_RETRIES ; - cp++;cond_resched (); }
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 104/154 drm/nouveau/pmu: Fix gp10b firmware guard
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aaron Kling <[email protected]>
[ Upstream commit 3dbc0215e3c502a9f3221576da0fdc9847fb9721 ]
Most kernel configs enable multiple Tegra SoC generations, causing this typo to go unnoticed. But in the case where a kernel config is strictly for Tegra186, this is a problem.
--- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c +1 -1
@@ -75,7 +75,7 @@ gp10b_pmu_acr = { .bootstrap_multiple_falcons = gp10b_pmu_acr_bootstrap_multiple_falcons, }; -#if IS_ENABLED (CONFIG_ARCH_TEGRA_210_SOC ) +#if IS_ENABLED (CONFIG_ARCH_TEGRA_186_SOC )MODULE_FIRMWARE ("nvidia/gp10b/pmu/desc.bin" );MODULE_FIRMWARE ("nvidia/gp10b/pmu/image.bin" );MODULE_FIRMWARE ("nvidia/gp10b/pmu/sig.bin" );
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 105/154 irqchip/jcore-aic, clocksource/drivers/jcore: Fix jcore-pit interrupt request
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Artur Rojek <[email protected]>
[ Upstream commit d7e3fd658248f257006227285095d190e70ee73a ]
The jcore-aic irqchip does not have separate interrupt numbers reserved for cpu-local vs global interrupts. Therefore the device drivers need to request the given interrupt as per CPU interrupt.
69a9dcbd2d65 ("clocksource/drivers/jcore: Use request_percpu_irq()") converted the clocksource driver over to request_percpu_irq(), but failed to do add all the required changes, resulting in a failure to register PIT interrupts.
Fix this by:
1) Explicitly mark the interrupt via irq_set_percpu_devid() in
jcore_pit_init().
2) Enable and disable the per CPU interrupt in the CPU hotplug callbacks.
3) Pass the correct per-cpu cookie to the irq handler by using handle_percpu_devid_irq() instead of handle_percpu_irq() in handle_jcore_irq().
[ tglx: Massage change log ]
--- drivers/clocksource/jcore-pit.c | 15 ++++++++++++++- drivers/irqchip/irq-jcore-aic.c | 2 +- 2 files changed, 15 insertions(+), 2 deletions(-)
drivers/clocksource/jcore-pit.c +14 -1
@@ -114,6 +114,18 @@ static int jcore_pit_local_init(unsigned cpu) pit->periodic_delta =DIV_ROUND_CLOSEST (NSEC_PER_SEC ,HZ * buspd);clockevents_config_and_register (&pit->ced, freq,1 ,ULONG_MAX ); +enable_percpu_irq (pit->ced.irq,IRQ_TYPE_NONE ); + +return 0 ; +} + +static int jcore_pit_local_teardown (unsigned cpu) +{ +struct jcore_pit *pit =this_cpu_ptr (jcore_pit_percpu); + +pr_info ("Local J-Core PIT teardown on cpu %u\n" , cpu); + +disable_percpu_irq (pit->ced.irq);return 0 ; }
@@ -168,6 +180,7 @@ static int __init jcore_pit_init(struct device_node *node)return -ENOMEM ; } +irq_set_percpu_devid (pit_irq); err =request_percpu_irq (pit_irq, jcore_timer_interrupt,"jcore_pit" , jcore_pit_percpu);if (err) {
@@ -237,7 +250,7 @@ static int __init jcore_pit_init(struct device_node *node)cpuhp_setup_state (CPUHP_AP_JCORE_TIMER_STARTING ,"clockevents/jcore:starting" , - jcore_pit_local_init,NULL ); + jcore_pit_local_init, jcore_pit_local_teardown);return 0 ; }
drivers/irqchip/irq-jcore-aic.c +1 -1
@@ -38,7 +38,7 @@ static struct irq_chip jcore_aic;static void handle_jcore_irq (struct irq_desc *desc) {if (irqd_is_per_cpu (irq_desc_get_irq_data (desc))) -handle_percpu_irq (desc); +handle_percpu_devid_irq (desc);else handle_simple_irq (desc); }
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 106/154 drm: panel: jd9365da-h3: fix reset signal polarity
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hugo Villeneuve <[email protected]>
commit a8972d5a49b408248294b5ecbdd0a085e4726349 upstream.
In jadard_prepare() a reset pulse is generated with the following statements (delays ommited for clarity):
gpiod_set_value(jadard->reset, 1); --> Deassert reset
gpiod_set_value(jadard->reset, 0); --> Assert reset for 10ms
gpiod_set_value(jadard->reset, 1); --> Deassert resetHowever, specifying second argument of "0" to gpiod_set_value() means to deassert the GPIO, and "1" means to assert it. If the reset signal is defined as GPIO_ACTIVE_LOW in the DTS, the above statements will incorrectly generate the reset pulse (inverted) and leave it asserted (LOW) at the end of jadard_prepare().
Fix reset behavior by inverting gpiod_set_value() second argument in jadard_prepare(). Also modify second argument to devm_gpiod_get() in jadard_dsi_probe() to assert the reset when probing.
Do not modify it in jadard_unprepare() as it is already properly asserted with "1", which seems to be the intended behavior.
--- drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c +4 -4
@@ -109,13 +109,13 @@ static int jadard_prepare(struct drm_panif (jadard->desc->lp11_to_reset_delay_ms)msleep (jadard->desc->lp11_to_reset_delay_ms); -gpiod_set_value (jadard->reset,1 ); +gpiod_set_value (jadard->reset,0 );msleep (5 ); -gpiod_set_value (jadard->reset,0 ); +gpiod_set_value (jadard->reset,1 );msleep (10 ); -gpiod_set_value (jadard->reset,1 ); +gpiod_set_value (jadard->reset,0 );msleep (130 ); ret = jadard->desc->init (jadard);
@@ -1130,7 +1130,7 @@ static int jadard_dsi_probe(struct mipi_ dsi->format = desc->format; dsi->lanes = desc->lanes; - jadard->reset =devm_gpiod_get (dev,"reset" ,GPIOD_OUT_LOW ); + jadard->reset =devm_gpiod_get (dev,"reset" ,GPIOD_OUT_HIGH );if (IS_ERR (jadard->reset)) {DRM_DEV_ERROR (&dsi->dev,"failed to get our reset GPIO\n" );return PTR_ERR (jadard->reset);
Greg Kroah-Hartman
maintainerPATCH 107/154 drm/msm/dpu: Disable dither in phys encoder cleanup
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jessica Zhang <[email protected]>
commit f063ac6b55df03ed25996bdc84d9e1c50147cfa1 upstream.
Disable pingpong dither in dpu_encoder_helper_phys_cleanup().
This avoids the issue where an encoder unknowingly uses dither after reserving a pingpong block that was previously bound to an encoder that had enabled dither.
Patchwork: https://patchwork.freedesktop.org/patch/636517/
--- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +3 -0
@@ -2125,6 +2125,9 @@ void dpu_encoder_helper_phys_cleanup(str } } +if (phys_enc->hw_pp && phys_enc->hw_pp->ops.setup_dither) + phys_enc->hw_pp->ops.setup_dither (phys_enc->hw_pp,NULL ); +/* reset the merge 3D HW block */ if (phys_enc->hw_pp && phys_enc->hw_pp->merge_3d) { phys_enc->hw_pp->merge_3d->ops.setup_3d_mode(phys_enc->hw_pp->merge_3d,
Greg Kroah-Hartman
maintainerPATCH 90/154 firmware: imx: IMX_SCMI_MISC_DRV should depend on ARCH_MXC
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Geert Uytterhoeven <[email protected]>
[ Upstream commit be6686b823b30a69b1f71bde228ce042c78a1941 ]
The i.MX System Controller Management Interface firmware is only present on Freescale i.MX SoCs. Hence add a dependency on ARCH_MXC, to prevent asking the user about this driver when configuring a kernel without Freescale i.MX platform support.
--- drivers/firmware/imx/Kconfig | 1 + 1 file changed, 1 insertion(+)
drivers/firmware/imx/Kconfig +1 -0
@@ -25,6 +25,7 @@ config IMX_SCU config IMX_SCMI_MISC_DRV tristate "IMX SCMI MISC Protocol driver" + depends on ARCH_MXC || COMPILE_TEST default y if ARCH_MXC help The System Controller Management Interface firmware (SCMI FW) is
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 108/154 drm/i915: Make sure all planes in use by the joiner have their crtc included
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ville Syrjälä <[email protected]>
commit 07fb70d82e0df085980246bf17bc12537588795f upstream.
Any active plane needs to have its crtc included in the atomic state. For planes enabled via uapi that is all handler in the core. But when we use a plane for joiner the uapi code things the plane is disabled and therefore doesn't have a crtc. So we need to pull those in by hand. We do it first thing in intel_joiner_add_affected_crtcs() so that any newly added crtc will subsequently pull in all of its joined crtcs as well.
The symptoms from failing to do this are:
- duct tape in the form of commit 1d5b09f8daf8 ("drm/i915: Fix NULL ptr deref by checking new_crtc_state")
- the plane's hw state will get overwritten by the disabled uapi state if it can't find the uapi counterpart plane in the atomic state from where it should copy the correct state
--- drivers/gpu/drm/i915/display/intel_display.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
drivers/gpu/drm/i915/display/intel_display.c +18 -0
@@ -6369,12 +6369,30 @@ static int intel_async_flip_check_hw(strstatic int intel_joiner_add_affected_crtcs (struct intel_atomic_state *state) {struct drm_i915_private *i915 =to_i915 (state->base.dev); +const struct intel_plane_state *plane_state;struct intel_crtc_state *crtc_state; +struct intel_plane *plane;struct intel_crtc *crtc;u8 affected_pipes =0 ;u8 modeset_pipes =0 ;int i; +/* +* Any plane which is in use by the joiner needs its crtc. +* Pull those in first as this will not have happened yet +* if the plane remains disabled according to uapi. +*/ +for_each_new_intel_plane_in_state (state, plane, plane_state, i) { + crtc =to_intel_crtc (plane_state->hw.crtc); +if (!crtc) +continue ; + + crtc_state =intel_atomic_get_crtc_state (&state->base, crtc); +if (IS_ERR (crtc_state)) +return PTR_ERR (crtc_state); + } + +/* Now pull in all joined crtcs */ for_each_new_intel_crtc_in_state (state, crtc, crtc_state, i) { affected_pipes |= crtc_state->joiner_pipes;if (intel_crtc_needs_modeset (crtc_state))
Greg Kroah-Hartman
maintainerPATCH 109/154 drm/i915/dp: Fix error handling during 128b/132b link training
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Imre Deak <[email protected]>
commit b9275eabe31e6679ae12c46a4a0a18d622db4570 upstream.
At the end of a 128b/132b link training sequence, the HW expects the transcoder training pattern to be set to TPS2 and from that to normal mode (disabling the training pattern). Transitioning from TPS1 directly to normal mode leaves the transcoder in a stuck state, resulting in page-flip timeouts later in the modeset sequence.
Atm, in case of a failure during link training, the transcoder may be still set to output the TPS1 pattern. Later the transcoder is then set from TPS1 directly to normal mode in intel_dp_stop_link_train(), leading to modeset failures later as described above. Fix this by setting the training patter to TPS2, if the link training failed at any point.
The clue in the specification about the above HW behavior is the explicit mention that TPS2 must be set after the link training sequence (and there isn't a similar requirement specified for the 8b/10b link training), see the Bspec links below.
v2: Add bspec aspect/link to the commit log. (Jani)
Bspec: 54128, 65448, 68849
--- drivers/gpu/drm/i915/display/intel_dp_link_training.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
drivers/gpu/drm/i915/display/intel_dp_link_training.c +14 -1
@@ -1561,7 +1561,7 @@ intel_dp_128b132b_link_train(struct inteif (wait_for (intel_dp_128b132b_intra_hop (intel_dp, crtc_state) ==0 ,500 )) {lt_err (intel_dp,DP_PHY_DPRX ,"128b/132b intra-hop not clear\n" ); -return false; + goto out; } if (intel_dp_128b132b_lane_eq(intel_dp, crtc_state) &&
@@ -1573,6 +1573,19 @@ intel_dp_128b132b_link_train(struct inte passed ?"passed" :"failed" , crtc_state->port_clock, crtc_state->lane_count); +out: +/* +* Ensure that the training pattern does get set to TPS2 even in case +* of a failure, as is the case at the end of a passing link training +* and what is expected by the transcoder. Leaving TPS1 set (and +* disabling the link train mode in DP_TP_CTL later from TPS1 directly) +* would result in a stuck transcoder HW state and flip-done timeouts +* later in the modeset sequence. +*/ +if (!passed) +intel_dp_program_link_training_pattern (intel_dp, crtc_state, +DP_PHY_DPRX ,DP_TRAINING_PATTERN_2 ); +return passed; }
Greg Kroah-Hartman
maintainerPATCH 110/154 drm/i915/ddi: Fix HDMI port width programming in DDI_BUF_CTL
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Imre Deak <[email protected]>
commit 166ce267ae3f96e439d8ccc838e8ec4d8b4dab73 upstream.
Fix the port width programming in the DDI_BUF_CTL register on MTLP+, where this had an off-by-one error.
--- drivers/gpu/drm/i915/display/intel_ddi.c | 2 +- drivers/gpu/drm/i915/i915_reg.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/display/intel_ddi.c +1 -1
@@ -3363,7 +3363,7 @@ static void intel_enable_ddi_hdmi(structintel_de_rmw (dev_priv,XELPDP_PORT_BUF_CTL1 (dev_priv, port),XELPDP_PORT_WIDTH_MASK |XELPDP_PORT_REVERSAL , port_buf); - buf_ctl |=DDI_PORT_WIDTH (lane_count); + buf_ctl |=DDI_PORT_WIDTH (crtc_state->lane_count);if (DISPLAY_VER (dev_priv) >=20 ) buf_ctl |=XE2LPD_DDI_BUF_D2D_LINK_ENABLE ;
drivers/gpu/drm/i915/i915_reg.h +1 -1
@@ -3869,7 +3869,7 @@ enum skl_power_gate {#define DDI_BUF_IS_IDLE (1 << 7)#define DDI_BUF_CTL_TC_PHY_OWNERSHIP REG_BIT(6)#define DDI_A_4_LANES (1 << 4) -#define DDI_PORT_WIDTH (width) (((width) - 1) << 1) +#define DDI_PORT_WIDTH (width) (((width) == 3 ? 4 : ((width) - 1)) << 1)#define DDI_PORT_WIDTH_MASK (7 << 1)#define DDI_PORT_WIDTH_SHIFT 1#define DDI_INIT_DISPLAY_DETECTED (1 << 0)
Greg Kroah-Hartman
maintainerPATCH 111/154 drm/i915/gt: Use spin_lock_irqsave() in interruptible context
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Karas <[email protected]>
commit e49477f7f78598295551d486ecc7f020d796432e upstream.
spin_lock/unlock() functions used in interrupt contexts could result in a deadlock, as seen in GitLab issue #13399, which occurs when interrupt comes in while holding a lock.
Try to remedy the problem by saving irq state before spin lock acquisition.
v2: add irqs' state save/restore calls to all locks/unlocks in
signal_irq_work() execution (Maciej)
v3: use with spin_lock_irqsave() in guc_lrc_desc_unpin() instead
of other lock/unlock calls and add Fixes and Cc tags (Tvrtko); change title and commit message
--- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +2 -2
@@ -3425,10 +3425,10 @@ static inline int guc_lrc_desc_unpin(str*/ ret =deregister_context (ce, ce->guc_id.id);if (ret) { -spin_lock (&ce->guc_state.lock); +spin_lock_irqsave (&ce->guc_state.lock, flags);set_context_registered (ce);clr_context_destroyed (ce); -spin_unlock (&ce->guc_state.lock); +spin_unlock_irqrestore (&ce->guc_state.lock, flags);/* * As gt-pm is awake at function entry, intel_wakeref_put_async merely decrements * the wakeref immediately but per function spec usage call this after unlock.
Greg Kroah-Hartman
maintainerPATCH 112/154 io_uring/rw: forbid multishot async reads
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pavel Begunkov <[email protected]>
commit 67b0025d19f99fb9fbb8b62e6975553c183f3a16 upstream.
At the moment we can't sanely handle queuing an async request from a multishot context, so disable them. It shouldn't matter as pollable files / socekts don't normally do async.
Patching it in __io_read() is not the cleanest way, but it's simpler than other options, so let's fix it there and clean up on top.
--- io_uring/rw.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
io_uring/rw.c +11 -2
@@ -862,7 +862,15 @@ static int __io_read(struct io_kiocb *reif (unlikely (ret))return ret; - ret =io_iter_do_read (rw, &io->iter); +if (unlikely (req->opcode ==IORING_OP_READ_MULTISHOT )) { +void *cb_copy = rw->kiocb.ki_complete; + + rw->kiocb.ki_complete =NULL ; + ret =io_iter_do_read (rw, &io->iter); + rw->kiocb.ki_complete = cb_copy; + }else { + ret =io_iter_do_read (rw, &io->iter); + }/* * Some file systems like to return -EOPNOTSUPP for an IOCB_NOWAIT
@@ -887,7 +895,8 @@ static int __io_read(struct io_kiocb *re }else if (ret == -EIOCBQUEUED ) {return IOU_ISSUE_SKIP_COMPLETE ; }else if (ret == req->cqe.res || ret <=0 || !force_nonblock || - (req->flags &REQ_F_NOWAIT ) || !need_complete_io (req)) { + (req->flags &REQ_F_NOWAIT ) || !need_complete_io (req) || + (issue_flags &IO_URING_F_MULTISHOT )) {/* read all, failed, already did sync or don't want to retry */ goto done; }
Greg Kroah-Hartman
maintainerPATCH 113/154 io_uring: prevent opcode speculation
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pavel Begunkov <[email protected]>
commit 1e988c3fe1264708f4f92109203ac5b1d65de50b upstream.
sqe->opcode is used for different tables, make sure we santitise it against speculations.
--- io_uring/io_uring.c | 2 ++ 1 file changed, 2 insertions(+)
io_uring/io_uring.c +2 -0
@@ -2053,6 +2053,8 @@ static int io_init_req(struct io_ring_ct req->opcode =0 ;return io_init_fail_req (req, -EINVAL ); } + opcode =array_index_nospec (opcode,IORING_OP_LAST ); + def = &io_issue_defs[opcode];if (unlikely (sqe_flags & ~SQE_COMMON_FLAGS )) {/* enforce forwards compatibility on users */
Greg Kroah-Hartman
maintainerPATCH 114/154 gpiolib: check the return value of gpio_chip::get_direction()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bartosz Golaszewski <[email protected]>
commit 9d846b1aebbe488f245f1aa463802ff9c34cc078 upstream.
As per the API contract - gpio_chip::get_direction() may fail and return a negative error number. However, we treat it as if it always returned 0 or 1. Check the return value of the callback and propagate the error number up the stack.
--- drivers/gpio/gpiolib.c | 44 +++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-)
drivers/gpio/gpiolib.c +29 -15
@@ -1059,8 +1059,11 @@ int gpiochip_add_data_with_key(struct gpstruct gpio_desc *desc = &gdev->descs[desc_index];if (gc->get_direction &&gpiochip_line_is_valid (gc, desc_index)) { -assign_bit (FLAG_IS_OUT , - &desc->flags, !gc->get_direction (gc, desc_index)); + ret = gc->get_direction (gc, desc_index); +if (ret <0 ) + goto err_cleanup_desc_srcu; + +assign_bit (FLAG_IS_OUT , &desc->flags, !ret); }else {assign_bit (FLAG_IS_OUT , &desc->flags, !gc->direction_input);
@@ -2702,13 +2705,18 @@ int gpiod_direction_input(struct gpio_deif (guard.gc->direction_input) { ret = guard.gc->direction_input (guard.gc,gpio_chip_hwgpio (desc)); - }else if (guard.gc->get_direction && - (guard.gc->get_direction (guard.gc, -gpio_chip_hwgpio (desc)) !=1 )) { -gpiod_warn (desc, -"%s: missing direction_input() operation and line is output\n" , - __func__); -return -EIO ; + }else if (guard.gc->get_direction) { + ret = guard.gc->get_direction (guard.gc, +gpio_chip_hwgpio (desc)); +if (ret <0 ) +return ret; + +if (ret !=GPIO_LINE_DIRECTION_IN ) { +gpiod_warn (desc, +"%s: missing direction_input() operation and line is output\n" , + __func__); +return -EIO ; + } }if (ret ==0 ) {clear_bit (FLAG_IS_OUT , &desc->flags);
@@ -2746,12 +2754,18 @@ static int gpiod_direction_output_raw_co gpio_chip_hwgpio(desc), val); }else {/* Check that we are in output mode if we can */ -if (guard.gc->get_direction && - guard.gc->get_direction (guard.gc,gpio_chip_hwgpio (desc))) { -gpiod_warn (desc, -"%s: missing direction_output() operation\n" , - __func__); -return -EIO ; +if (guard.gc->get_direction) { + ret = guard.gc->get_direction (guard.gc, +gpio_chip_hwgpio (desc)); +if (ret <0 ) +return ret; + +if (ret !=GPIO_LINE_DIRECTION_OUT ) { +gpiod_warn (desc, +"%s: missing direction_output() operation\n" , + __func__); +return -EIO ; + } }/* * If we can't actively set the direction, we are some
Greg Kroah-Hartman
maintainerPATCH 115/154 gpiolib: protect gpio_chip with SRCU in array_info paths in multi get/set
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bartosz Golaszewski <[email protected]>
commit 81570d6a7ad37033c7895811551a5a9023706eda upstream.
During the locking rework in GPIOLIB, we omitted one important use-case,
namely: setting and getting values for GPIO descriptor arrays with array_info present.
This patch does two things: first it makes struct gpio_array store the address of the underlying GPIO device and not chip. Next: it protects the chip with SRCU from removal in gpiod_get_array_value_complex() and gpiod_set_array_value_complex().
--- drivers/gpio/gpiolib.c | 48 +++++++++++++++++++++++++++++++++--------------- drivers/gpio/gpiolib.h | 4 ++-- 2 files changed, 35 insertions(+), 17 deletions(-)
drivers/gpio/gpiolib.c +33 -15
@@ -3082,6 +3082,8 @@ static int gpiod_get_raw_value_commit(costatic int gpio_chip_get_multiple (struct gpio_chip *gc,unsigned long *mask,unsigned long *bits) { +lockdep_assert_held (&gc->gpiodev->srcu); +if (gc->get_multiple)return gc->get_multiple (gc, mask, bits);if (gc->get) {
@@ -3112,6 +3114,7 @@ int gpiod_get_array_value_complex(bool rstruct gpio_array *array_info, unsigned long *value_bitmap) { + struct gpio_chip *gc;int ret, i =0 ;/*
@@ -3123,10 +3126,15 @@ int gpiod_get_array_value_complex(bool r array_size <= array_info->size && (void *)array_info == desc_array + array_info->size) {if (!can_sleep) -WARN_ON (array_info->chip->can_sleep); +WARN_ON (array_info->gdev->can_sleep); - ret =gpio_chip_get_multiple (array_info->chip, - array_info->get_mask, +guard (srcu)(&array_info->gdev->srcu); + gc =srcu_dereference (array_info->gdev->chip, + &array_info->gdev->srcu); +if (!gc) +return -ENODEV ; + + ret =gpio_chip_get_multiple (gc, array_info->get_mask, value_bitmap);if (ret)return ret;
@@ -3407,6 +3415,8 @@ static void gpiod_set_raw_value_commit(sstatic void gpio_chip_set_multiple (struct gpio_chip *gc,unsigned long *mask,unsigned long *bits) { +lockdep_assert_held (&gc->gpiodev->srcu); +if (gc->set_multiple) { gc->set_multiple (gc, mask, bits); }else {
@@ -3424,6 +3434,7 @@ int gpiod_set_array_value_complex(bool rstruct gpio_array *array_info, unsigned long *value_bitmap) { + struct gpio_chip *gc;int i =0 ;/*
@@ -3435,14 +3446,19 @@ int gpiod_set_array_value_complex(bool r array_size <= array_info->size && (void *)array_info == desc_array + array_info->size) {if (!can_sleep) -WARN_ON (array_info->chip->can_sleep); +WARN_ON (array_info->gdev->can_sleep); + +guard (srcu)(&array_info->gdev->srcu); + gc =srcu_dereference (array_info->gdev->chip, + &array_info->gdev->srcu); +if (!gc) +return -ENODEV ;if (!raw && !bitmap_empty (array_info->invert_mask, array_size))bitmap_xor (value_bitmap, value_bitmap, array_info->invert_mask, array_size); -gpio_chip_set_multiple (array_info->chip, array_info->set_mask, - value_bitmap); +gpio_chip_set_multiple (gc, array_info->set_mask, value_bitmap); i =find_first_zero_bit (array_info->set_mask, array_size);if (i == array_size)
@@ -4698,9 +4714,10 @@ struct gpio_descs *__must_check gpiod_ge {struct gpio_desc *desc;struct gpio_descs *descs; +struct gpio_device *gdev;struct gpio_array *array_info =NULL ; -struct gpio_chip *gc;int count, bitmap_size; +unsigned long dflags;size_t descs_size; count =gpiod_count (dev, con_id);
@@ -4721,7 +4738,7 @@ struct gpio_descs *__must_check gpiod_ge descs->desc[descs->ndescs] = desc; - gc =gpiod_to_chip (desc); + gdev =gpiod_to_gpio_device (desc);/* * If pin hardware number of array member 0 is also 0, select * its chip as a candidate for fast bitmap processing path.
@@ -4729,8 +4746,8 @@ struct gpio_descs *__must_check gpiod_geif (descs->ndescs ==0 &&gpio_chip_hwgpio (desc) ==0 ) {struct gpio_descs *array; - bitmap_size =BITS_TO_LONGS (gc->ngpio > count ? - gc->ngpio : count); + bitmap_size =BITS_TO_LONGS (gdev->ngpio > count ? + gdev->ngpio : count); array = krealloc(descs, descs_size + struct_size(array_info, invert_mask, 3 * bitmap_size),
@@ -4750,7 +4767,7 @@ struct gpio_descs *__must_check gpiod_ge array_info->desc = descs->desc; array_info->size = count; - array_info->chip = gc; + array_info->gdev = gdev;bitmap_set (array_info->get_mask, descs->ndescs, count - descs->ndescs); bitmap_set(array_info->set_mask, descs->ndescs,
@@ -4763,7 +4780,7 @@ struct gpio_descs *__must_check gpiod_gecontinue ;/* Unmark array members which don't belong to the 'fast' chip */ -if (array_info->chip != gc) { +if (array_info->gdev != gdev) {__clear_bit (descs->ndescs, array_info->get_mask);__clear_bit (descs->ndescs, array_info->set_mask); }
@@ -4786,9 +4803,10 @@ struct gpio_descs *__must_check gpiod_ge array_info->set_mask); } }else { + dflags =READ_ONCE (desc->flags);/* Exclude open drain or open source from fast output */ -if (gpiochip_line_is_open_drain (gc, descs->ndescs) || -gpiochip_line_is_open_source (gc, descs->ndescs)) +if (test_bit (FLAG_OPEN_DRAIN , &dflags) || +test_bit (FLAG_OPEN_SOURCE , &dflags))__clear_bit (descs->ndescs, array_info->set_mask);/* Identify 'fast' pins which require invertion */
@@ -4800,7 +4818,7 @@ struct gpio_descs *__must_check gpiod_geif (array_info)dev_dbg (dev,"GPIO array info: chip=%s, size=%d, get_mask=%lx, set_mask=%lx, invert_mask=%lx\n" , - array_info->chip->label, array_info->size, + array_info->gdev->label, array_info->size, *array_info->get_mask, *array_info->set_mask, *array_info->invert_mask);return descs;
drivers/gpio/gpiolib.h +2 -2
@@ -110,7 +110,7 @@ extern const char *const gpio_suffixes[]* * @desc: Array of pointers to the GPIO descriptors * @size: Number of elements in desc -* @chip: Parent GPIO chip +* @gdev: Parent GPIO device * @get_mask: Get mask used in fastpath * @set_mask: Set mask used in fastpath * @invert_mask: Invert mask used in fastpath
@@ -122,7 +122,7 @@ extern const char *const gpio_suffixes[]struct gpio_array {struct gpio_desc **desc;unsigned int size; -struct gpio_chip *chip; +struct gpio_device *gdev;unsigned long *get_mask;unsigned long *set_mask;unsigned long invert_mask[];
Greg Kroah-Hartman
maintainerPATCH 116/154 tee: optee: Fix supplicant wait loop
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sumit Garg <[email protected]>
commit 70b0d6b0a199c5a3ee6c72f5e61681ed6f759612 upstream.
OP-TEE supplicant is a user-space daemon and it's possible for it be hung or crashed or killed in the middle of processing an OP-TEE RPC call. It becomes more complicated when there is incorrect shutdown ordering of the supplicant process vs the OP-TEE client application which can eventually lead to system hang-up waiting for the closure of the client application.
Allow the client process waiting in kernel for supplicant response to be killed rather than indefinitely waiting in an unkillable state. Also, a normal uninterruptible wait should not have resulted in the hung-task watchdog getting triggered, but the endless loop would.
This fixes issues observed during system reboot/shutdown when supplicant got hung for some reason or gets crashed/killed which lead to client getting hung in an unkillable state. It in turn lead to system being in hung up state requiring hard power off/on to recover.
--- drivers/tee/optee/supp.c | 35 ++++++++--------------------------- 1 file changed, 8 insertions(+), 27 deletions(-)
drivers/tee/optee/supp.c +8 -27
@@ -80,7 +80,6 @@ u32 optee_supp_thrd_req(struct tee_contestruct optee *optee =tee_get_drvdata (ctx->teedev);struct optee_supp *supp = &optee->supp;struct optee_supp_req *req; -bool interruptable;u32 ret;/*
@@ -111,36 +110,18 @@ u32 optee_supp_thrd_req(struct tee_conte/* * Wait for supplicant to process and return result, once we've * returned from wait_for_completion(&req->c) successfully we have -* exclusive access again. +* exclusive access again. Allow the wait to be killable such that +* the wait doesn't turn into an indefinite state if the supplicant +* gets hung for some reason. */ -while (wait_for_completion_interruptible (&req->c)) { +if (wait_for_completion_killable (&req->c)) {mutex_lock (&supp->mutex); - interruptable = !supp->ctx; -if (interruptable) { -/* -* There's no supplicant available and since the -* supp->mutex currently is held none can -* become available until the mutex released -* again. -* -* Interrupting an RPC to supplicant is only -* allowed as a way of slightly improving the user -* experience in case the supplicant hasn't been -* started yet. During normal operation the supplicant -* will serve all requests in a timely manner and -* interrupting then wouldn't make sense. -*/ -if (req->in_queue) { -list_del (&req->link); - req->in_queue = false; - } +if (req->in_queue) { +list_del (&req->link); + req->in_queue = false; }mutex_unlock (&supp->mutex); - -if (interruptable) { - req->ret =TEEC_ERROR_COMMUNICATION ; -break ; - } + req->ret =TEEC_ERROR_COMMUNICATION ; } ret = req->ret;
Greg Kroah-Hartman
maintainerPATCH 117/154 drop_monitor: fix incorrect initialization order
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gavrilov Ilia <[email protected]>
commit 07b598c0e6f06a0f254c88dafb4ad50f8a8c6eea upstream.
Syzkaller reports the following bug:
BUG: spinlock bad magic on CPU#1, syz-executor.0/7995 lock: 0xffff88805303f3e0, .magic: 00000000, .owner: <none>/-1, .owner_cpu: 0 CPU: 1 PID: 7995 Comm: syz-executor.0 Tainted: G E 5.10.209+ #1 Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 11/12/2020 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x119/0x179 lib/dump_stack.c:118 debug_spin_lock_before kernel/locking/spinlock_debug.c:83 [inline] do_raw_spin_lock+0x1f6/0x270 kernel/locking/spinlock_debug.c:112 __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:117 [inline] _raw_spin_lock_irqsave+0x50/0x70 kernel/locking/spinlock.c:159 reset_per_cpu_data+0xe6/0x240 [drop_monitor] net_dm_cmd_trace+0x43d/0x17a0 [drop_monitor] genl_family_rcv_msg_doit+0x22f/0x330 net/netlink/genetlink.c:739 genl_family_rcv_msg net/netlink/genetlink.c:783 [inline] genl_rcv_msg+0x341/0x5a0 net/netlink/genetlink.c:800 netlink_rcv_skb+0x14d/0x440 net/netlink/af_netlink.c:2497 genl_rcv+0x29/0x40 net/netlink/genetlink.c:811 netlink_unicast_kernel net/netlink/af_netlink.c:1322 [inline] netlink_unicast+0x54b/0x800 net/netlink/af_netlink.c:1348 netlink_sendmsg+0x914/0xe00 net/netlink/af_netlink.c:1916 sock_sendmsg_nosec net/socket.c:651 [inline] __sock_sendmsg+0x157/0x190 net/socket.c:663 ____sys_sendmsg+0x712/0x870 net/socket.c:2378 ___sys_sendmsg+0xf8/0x170 net/socket.c:2432 __sys_sendmsg+0xea/0x1b0 net/socket.c:2461 do_syscall_64+0x30/0x40 arch/x86/entry/common.c:46 entry_SYSCALL_64_after_hwframe+0x62/0xc7 RIP: 0033:0x7f3f9815aee9 Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007f3f972bf0c8 EFLAGS: 00000246 ORIG_RAX: 000000000000002e RAX: ffffffffffffffda RBX: 00007f3f9826d050 RCX: 00007f3f9815aee9 RDX: 0000000020000000 RSI: 0000000020001300 RDI: 0000000000000007 RBP: 00007f3f981b63bd R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 R13: 000000000000006e R14: 00007f3f9826d050 R15: 00007ffe01ee6768
If drop_monitor is built as a kernel module, syzkaller may have time to send a netlink NET_DM_CMD_START message during the module loading. This will call the net_dm_monitor_start() function that uses a spinlock that has not yet been initialized.
To fix this, let's place resource initialization above the registration of a generic netlink family.
Found by InfoTeCS on behalf of Linux Verification Center (linuxtesting.org) with Syzkaller.
--- net/core/drop_monitor.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-)
net/core/drop_monitor.c +14 -15
@@ -1734,30 +1734,30 @@ static int __init init_net_drop_monitor(return -ENOSPC ; } - rc =genl_register_family (&net_drop_monitor_family); -if (rc) { -pr_err ("Could not create drop monitor netlink family\n" ); -return rc; +for_each_possible_cpu (cpu) { +net_dm_cpu_data_init (cpu); +net_dm_hw_cpu_data_init (cpu); } -WARN_ON (net_drop_monitor_family.mcgrp_offset !=NET_DM_GRP_ALERT ); rc =register_netdevice_notifier (&dropmon_net_notifier);if (rc <0 ) {pr_crit ("Failed to register netdevice notifier\n" ); +return rc; + } + + rc =genl_register_family (&net_drop_monitor_family); +if (rc) { +pr_err ("Could not create drop monitor netlink family\n" ); goto out_unreg; } +WARN_ON (net_drop_monitor_family.mcgrp_offset !=NET_DM_GRP_ALERT ); rc =0 ; -for_each_possible_cpu (cpu) { -net_dm_cpu_data_init (cpu); -net_dm_hw_cpu_data_init (cpu); - } - goto out; out_unreg: -genl_unregister_family (&net_drop_monitor_family); +WARN_ON (unregister_netdevice_notifier (&dropmon_net_notifier)); out:return rc; }
@@ -1766,19 +1766,18 @@ static void exit_net_drop_monitor(void) {int cpu; -BUG_ON (unregister_netdevice_notifier (&dropmon_net_notifier)); -/* * Because of the module_get/put we do in the trace state change path * we are guaranteed not to have any current users when we get here */ +BUG_ON (genl_unregister_family (&net_drop_monitor_family)); + +BUG_ON (unregister_netdevice_notifier (&dropmon_net_notifier));for_each_possible_cpu (cpu) {net_dm_hw_cpu_data_fini (cpu);net_dm_cpu_data_fini (cpu); } - -BUG_ON (genl_unregister_family (&net_drop_monitor_family)); }module_init (init_net_drop_monitor);
Greg Kroah-Hartman
maintainerPATCH 91/154 platform: cznic: CZNIC_PLATFORMS should depend on ARCH_MVEBU
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Geert Uytterhoeven <[email protected]>
[ Upstream commit dd0f05b98925111f4530d7dab774398cdb32e9e3 ]
CZ.NIC's Turris devices are based on Marvell EBU SoCs. Hence add a dependency on ARCH_MVEBU, to prevent asking the user about these drivers when configuring a kernel that cannot run on an affected CZ.NIC Turris system.
--- drivers/platform/cznic/Kconfig | 1 + 1 file changed, 1 insertion(+)
drivers/platform/cznic/Kconfig +1 -0
@@ -6,6 +6,7 @@ menuconfig CZNIC_PLATFORMS bool "Platform support for CZ.NIC's Turris hardware" + depends on ARCH_MVEBU || COMPILE_TEST help Say Y here to be able to choose driver support for CZ.NIC's Turris devices. This option alone does not add any kernel code.
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 118/154 mm/migrate_device: dont add folio to be freed to LRU in migrate_device_finalize()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Hildenbrand <[email protected]>
commit 41cddf83d8b00f29fd105e7a0777366edc69a5cf upstream.
If migration succeeded, we called folio_migrate_flags()->mem_cgroup_migrate() to migrate the memcg from the old to the new folio. This will set memcg_data of the old folio to 0.
Similarly, if migration failed, memcg_data of the dst folio is left unset.
If we call folio_putback_lru() on such folios (memcg_data == 0), we will add the folio to be freed to the LRU, making memcg code unhappy. Running the hmm selftests:
# ./hmm-tests ... # RUN hmm.hmm_device_private.migrate ... [ 102.078007][T14893] page: refcount:1 mapcount:0 mapping:0000000000000000 index:0x7ff27d200 pfn:0x13cc00 [ 102.079974][T14893] anon flags: 0x17ff00000020018(uptodate|dirty|swapbacked|node=0|zone=2|lastcpupid=0x7ff) [ 102.082037][T14893] raw: 017ff00000020018 dead000000000100 dead000000000122 ffff8881353896c9 [ 102.083687][T14893] raw: 00000007ff27d200 0000000000000000 00000001ffffffff 0000000000000000 [ 102.085331][T14893] page dumped because: VM_WARN_ON_ONCE_FOLIO(!memcg && !mem_cgroup_disabled()) [ 102.087230][T14893] ------------[ cut here ]------------ [ 102.088279][T14893] WARNING: CPU: 0 PID: 14893 at ./include/linux/memcontrol.h:726 folio_lruvec_lock_irqsave+0x10e/0x170 [ 102.090478][T14893] Modules linked in: [ 102.091244][T14893] CPU: 0 UID: 0 PID: 14893 Comm: hmm-tests Not tainted 6.13.0-09623-g6c216bc522fd #151 [ 102.093089][T14893] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-2.fc40 04/01/2014 [ 102.094848][T14893] RIP: 0010:folio_lruvec_lock_irqsave+0x10e/0x170 [ 102.096104][T14893] Code: ... [ 102.099908][T14893] RSP: 0018:ffffc900236c37b0 EFLAGS: 00010293 [ 102.101152][T14893] RAX: 0000000000000000 RBX: ffffea0004f30000 RCX: ffffffff8183f426 [ 102.102684][T14893] RDX: ffff8881063cb880 RSI: ffffffff81b8117f RDI: ffff8881063cb880 [ 102.104227][T14893] RBP: 0000000000000000 R08: 0000000000000005 R09: 0000000000000000 [ 102.105757][T14893] R10: 0000000000000001 R11: 0000000000000002 R12: ffffc900236c37d8 [ 102.107296][T14893] R13: ffff888277a2bcb0 R14: 000000000000001f R15: 0000000000000000 [ 102.108830][T14893] FS: 00007ff27dbdd740(0000) GS:ffff888277a00000(0000) knlGS:0000000000000000 [ 102.110643][T14893] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 102.111924][T14893] CR2: 00007ff27d400000 CR3: 000000010866e000 CR4: 0000000000750ef0 [ 102.113478][T14893] PKRU: 55555554 [ 102.114172][T14893] Call Trace: [ 102.114805][T14893] <TASK> [ 102.115397][T14893] ? folio_lruvec_lock_irqsave+0x10e/0x170 [ 102.116547][T14893] ? __warn.cold+0x110/0x210 [ 102.117461][T14893] ? folio_lruvec_lock_irqsave+0x10e/0x170 [ 102.118667][T14893] ? report_bug+0x1b9/0x320 [ 102.119571][T14893] ? handle_bug+0x54/0x90 [ 102.120494][T14893] ? exc_invalid_op+0x17/0x50 [ 102.121433][T14893] ? asm_exc_invalid_op+0x1a/0x20 [ 102.122435][T14893] ? __wake_up_klogd.part.0+0x76/0xd0 [ 102.123506][T14893] ? dump_page+0x4f/0x60 [ 102.124352][T14893] ? folio_lruvec_lock_irqsave+0x10e/0x170 [ 102.125500][T14893] folio_batch_move_lru+0xd4/0x200 [ 102.126577][T14893] ? __pfx_lru_add+0x10/0x10 [ 102.127505][T14893] __folio_batch_add_and_move+0x391/0x720 [ 102.128633][T14893] ? __pfx_lru_add+0x10/0x10 [ 102.129550][T14893] folio_putback_lru+0x16/0x80 [ 102.130564][T14893] migrate_device_finalize+0x9b/0x530 [ 102.131640][T14893] dmirror_migrate_to_device.constprop.0+0x7c5/0xad0 [ 102.133047][T14893] dmirror_fops_unlocked_ioctl+0x89b/0xc80
Likely, nothing else goes wrong: putting the last folio reference will remove the folio from the LRU again. So besides memcg complaining, adding the folio to be freed to the LRU is just an unnecessary step.
The new flow resembles what we have in migrate_folio_move(): add the dst to the lru, remove migration ptes, unlock and unref dst.
--- mm/migrate_device.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-)
mm/migrate_device.c +4 -9
@@ -840,20 +840,15 @@ void migrate_device_finalize(unsigned lo dst = src; } +if (!folio_is_zone_device (dst)) +folio_add_lru (dst);remove_migration_ptes (src, dst,0 );folio_unlock (src); - -if (folio_is_zone_device (src)) -folio_put (src); -else -folio_putback_lru (src); +folio_put (src);if (dst != src) {folio_unlock (dst); -if (folio_is_zone_device (dst)) -folio_put (dst); -else -folio_putback_lru (dst); +folio_put (dst); } } }
Greg Kroah-Hartman
maintainerPATCH 119/154 arm64: dts: rockchip: Fix broken tsadc pinctrl names for rk3588
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Shiyan <[email protected]>
commit 5c8f9a05336cf5cadbd57ad461621b386aadb762 upstream.
The tsadc driver does not handle pinctrl "gpio" and "otpout". Let's use the correct pinctrl names "default" and "sleep". Additionally, Alexey Charkov's testing [1] has established that it is necessary for pinctrl state to reference the &tsadc_shut_org configuration rather than &tsadc_shut for the driver to function correctly.
[1] https://lkml.org/lkml/2025/1/24/966
--- arch/arm64/boot/dts/rockchip/rk3588-base.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
arch/arm64/boot/dts/rockchip/rk3588-base.dtsi +3 -3
@@ -2626,9 +2626,9 @@ rockchip,hw-tshut-temp = <120000>; rockchip,hw-tshut-mode = <0>; /* tshut mode 0:CRU 1:GPIO */ rockchip,hw-tshut-polarity = <0>; /* tshut polarity 0:LOW 1:HIGH */ - pinctrl-0 = <&tsadc_gpio_func>; - pinctrl-1 = <&tsadc_shut>; - pinctrl-names = "gpio", "otpout"; + pinctrl-0 = <&tsadc_shut_org>; + pinctrl-1 = <&tsadc_gpio_func>; + pinctrl-names = "default", "sleep"; #thermal-sensor-cells = <1>; status = "disabled"; };
Greg Kroah-Hartman
maintainerPATCH 120/154 arm64: dts: rockchip: Move uart5 pin configuration to px30 ringneck SoM
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lukasz Czechowski <[email protected]>
commit 4eee627ea59304cdd66c5d4194ef13486a6c44fc upstream.
In the PX30-uQ7 (Ringneck) SoM, the hardware CTS and RTS pins for uart5 cannot be used for the UART CTS/RTS, because they are already allocated for different purposes. CTS pin is routed to SUS_S3# signal, while RTS pin is used internally and is not available on Q7 connector. Move definition of the pinctrl-0 property from px30-ringneck-haikou.dts to px30-ringneck.dtsi.
This commit is a dependency to next commit in the patch series, that disables DMA for uart5.
--- arch/arm64/boot/dts/rockchip/px30-ringneck-haikou.dts | 1 - arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-)
arch/arm64/boot/dts/rockchip/px30-ringneck-haikou.dts +0 -1
@@ -226,7 +226,6 @@ }; &uart5 { - pinctrl-0 = <&uart5_xfer>; rts-gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>; status = "okay"; };
arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi +4 -0
@@ -373,6 +373,10 @@ status = "okay"; }; +&uart5 { + pinctrl-0 = <&uart5_xfer>; +}; + /* Mule UCAN */ &usb_host0_ehci { status = "okay";
Greg Kroah-Hartman
maintainerPATCH 121/154 arm64: dts: rockchip: Disable DMA for uart5 on px30-ringneck
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lukasz Czechowski <[email protected]>
commit 5ae4dca718eacd0a56173a687a3736eb7e627c77 upstream.
UART controllers without flow control seem to behave unstable in case DMA is enabled. The issues were indicated in the message:
https://lore.kernel.org/linux-arm-kernel/CAMdYzYpXtMocCtCpZLU_xuWmOp2Ja_v0Aj0e6YFNRA-yV7u14g@mail.gmail.com/
In case of PX30-uQ7 Ringneck SoM, it was noticed that after couple of hours of UART communication, the CPU stall was occurring, leading to the system becoming unresponsive.
After disabling the DMA, extensive UART communication tests for up to two weeks were performed, and no issues were further observed.
The flow control pins for uart5 are not available on PX30-uQ7 Ringneck, as configured by pinctrl-0, so the DMA nodes were removed on SoM dtsi.
--- arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi | 2 ++ 1 file changed, 2 insertions(+)
arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi +2 -0
@@ -374,6 +374,8 @@ }; &uart5 { + /delete-property/ dmas; + /delete-property/ dma-names; pinctrl-0 = <&uart5_xfer>; };
Greg Kroah-Hartman
maintainerPATCH 122/154 soc: loongson: loongson2_guts: Add check for devm_kstrdup()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haoxiang Li <[email protected]>
commit e31e3f6c0ce473f7ce1e70d54ac8e3ed190509f8 upstream.
Add check for the return value of devm_kstrdup() in loongson2_guts_probe() to catch potential exception.
--- drivers/soc/loongson/loongson2_guts.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/soc/loongson/loongson2_guts.c +4 -1
@@ -114,8 +114,11 @@ static int loongson2_guts_probe(struct pif (of_property_read_string (root,"model" , &machine))of_property_read_string_index (root,"compatible" ,0 , &machine);of_node_put (root); -if (machine) +if (machine) { soc_dev_attr.machine =devm_kstrdup (dev, machine,GFP_KERNEL ); +if (!soc_dev_attr.machine) +return -ENOMEM ; + } svr =loongson2_guts_get_svr (); soc_die =loongson2_soc_die_match (svr, loongson2_soc_die);
Greg Kroah-Hartman
maintainerPATCH 92/154 nouveau/svm: fix missing folio unlock + put after make_device_exclusive_range()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Hildenbrand <[email protected]>
[ Upstream commit b3fefbb30a1691533cb905006b69b2a474660744 ]
In case we have to retry the loop, we are missing to unlock+put the folio. In that case, we will keep failing make_device_exclusive_range() because we cannot grab the folio lock, and even return from the function with the folio locked and referenced, effectively never succeeding the make_device_exclusive_range().
While at it, convert the other unlock+put to use a folio as well.
This was found by code inspection.
--- drivers/gpu/drm/nouveau/nouveau_svm.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/gpu/drm/nouveau/nouveau_svm.c +7 -2
@@ -590,6 +590,7 @@ static int nouveau_atomic_range_fault(struct nouveau_svmm *svmm,unsigned long timeout = jiffies +msecs_to_jiffies (HMM_RANGE_DEFAULT_TIMEOUT );struct mm_struct *mm = svmm->notifier.mm; +struct folio *folio;struct page *page;unsigned long start = args->p.addr;unsigned long notifier_seq;
@@ -616,12 +617,16 @@ static int nouveau_atomic_range_fault(struct nouveau_svmm *svmm, ret = -EINVAL ; goto out; } + folio =page_folio (page);mutex_lock (&svmm->mutex);if (!mmu_interval_read_retry (¬ifier->notifier, notifier_seq))break ;mutex_unlock (&svmm->mutex); + +folio_unlock (folio); +folio_put (folio); }/* Map the page on the GPU. */
@@ -637,8 +642,8 @@ static int nouveau_atomic_range_fault(struct nouveau_svmm *svmm, ret =nvif_object_ioctl (&svmm->vmm->vmm.object, args, size,NULL );mutex_unlock (&svmm->mutex); -unlock_page (page); -put_page (page); +folio_unlock (folio); +folio_put (folio); out:mmu_interval_notifier_remove (¬ifier->notifier);
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 93/154 drm/msm: Avoid rounding up to one jiffy
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rob Clark <[email protected]>
[ Upstream commit 669c285620231786fffe9d87ab432e08a6ed922b ]
If userspace is trying to achieve a timeout of zero, let 'em have it. Only round up if the timeout is greater than zero.
Patchwork: https://patchwork.freedesktop.org/patch/632264/
--- drivers/gpu/drm/msm/msm_drv.h | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-)
drivers/gpu/drm/msm/msm_drv.h +4 -7
@@ -543,15 +543,12 @@ static inline int align_pitch(int width, int bpp)static inline unsigned long timeout_to_jiffies (const ktime_t *timeout) {ktime_t now =ktime_get (); -s64 remaining_jiffies; -if (ktime_compare (*timeout, now) <0 ) { - remaining_jiffies =0 ; - }else { -ktime_t rem =ktime_sub (*timeout, now); - remaining_jiffies =ktime_divns (rem,NSEC_PER_SEC /HZ ); - } +if (ktime_compare (*timeout, now) <=0 ) +return 0 ; +ktime_t rem =ktime_sub (*timeout, now); +s64 remaining_jiffies =ktime_divns (rem,NSEC_PER_SEC /HZ );return clamp (remaining_jiffies,1LL , (s64 )INT_MAX ); }
Signature · 1 line
2.39.5
Greg Kroah-Hartman
maintainerPATCH 94/154 drm/msm/dpu: skip watchdog timer programming through TOP on >= SM8450
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Baryshkov <[email protected]>
[ Upstream commit 2f69e54584475ac85ea0e3407c9198ac7c6ea8ad ]
The SM8450 and later chips have DPU_MDP_PERIPH_0_REMOVED feature bit set, which means that those platforms have dropped some of the registers, including the WD TIMER-related ones. Stop providing the callback to program WD timer on those platforms.
Patchwork: https://patchwork.freedesktop.org/patch/628874/
--- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c +1 -1
@@ -272,7 +272,7 @@ static void _setup_mdp_ops(struct dpu_hw_mdp_ops *ops,if (cap &BIT (DPU_MDP_VSYNC_SEL )) ops->setup_vsync_source = dpu_hw_setup_vsync_sel; -else +else if (!(cap &BIT (DPU_MDP_PERIPH_0_REMOVED ))) ops->setup_vsync_source = dpu_hw_setup_wd_timer; ops->get_safe_status = dpu_hw_get_safe_status;
Signature · 1 line
2.39.5