6.1.160-rc1 review
Subsystems (5)
Greg Kroah-Hartman
maintainerPATCH 552/634 f2fs: remove unused GC_FAILURE_PIN
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chao Yu <[email protected]>
[ Upstream commit 968c4f72b23c0c8f1e94e942eab89b8c5a3022e7 ]
After commit 3db1de0e582c ("f2fs: change the current atomic write way"), we removed all GC_FAILURE_ATOMIC usage, let's change i_gc_failures[] array to i_pin_failure for cleanup.
Meanwhile, let's define i_current_depth and i_gc_failures as union variable due to they won't be valid at the same time.
Stable-dep-of: 10b591e7fb7c ("f2fs: fix to avoid updating compression context during writeback")
--- fs/f2fs/f2fs.h | 14 +++++--------- fs/f2fs/file.c | 12 +++++------- fs/f2fs/inode.c | 6 ++---- fs/f2fs/recovery.c | 3 +-- 4 files changed, 13 insertions(+), 22 deletions(-)
fs/f2fs/f2fs.h +5 -9
@@ -747,11 +747,6 @@ enum {#define DEF_DIR_LEVEL 0 -enum { -GC_FAILURE_PIN , -MAX_GC_FAILURE -}; -/* used for f2fs_inode_info->flags */ enum {FI_NEW_INODE ,/* indicate newly allocated inode */
@@ -797,9 +792,10 @@ struct f2fs_inode_info {unsigned long i_flags;/* keep an inode flags for ioctl */ unsigned char i_advise;/* use to give file attribute hints */ unsigned char i_dir_level;/* use for dentry level for large dir */ -unsigned int i_current_depth;/* only for directory depth */ -/* for gc failure statistic */ -unsigned int i_gc_failures[MAX_GC_FAILURE ]; +union { +unsigned int i_current_depth;/* only for directory depth */ +unsigned int i_gc_failures;/* for gc failure statistic */ + };unsigned int i_pino;/* parent inode number */ umode_t i_acl_mode;/* keep file acl mode temporarily */
@@ -3100,7 +3096,7 @@ static inline void f2fs_i_depth_write(ststatic inline void f2fs_i_gc_failures_write (struct inode *inode,unsigned int count) { -F2FS_I (inode)->i_gc_failures[GC_FAILURE_PIN ] = count; +F2FS_I (inode)->i_gc_failures = count;f2fs_mark_inode_dirty_sync (inode, true); }
fs/f2fs/file.c +5 -7
@@ -3247,13 +3247,11 @@ int f2fs_pin_file_control(struct inode */* Use i_gc_failures for normal file as a risk signal. */ if (inc) -f2fs_i_gc_failures_write (inode, - fi->i_gc_failures[GC_FAILURE_PIN ] +1 ); +f2fs_i_gc_failures_write (inode, fi->i_gc_failures +1 ); -if (fi->i_gc_failures[GC_FAILURE_PIN ] > sbi->gc_pin_file_threshold) { +if (fi->i_gc_failures > sbi->gc_pin_file_threshold) {f2fs_warn (sbi,"%s: Enable GC = ino %lx after %x GC trials" , - __func__, inode->i_ino, - fi->i_gc_failures[GC_FAILURE_PIN ]); + __func__, inode->i_ino, fi->i_gc_failures);clear_inode_flag (inode,FI_PIN_FILE );return -EAGAIN ; }
@@ -3312,7 +3310,7 @@ static int f2fs_ioc_set_pin_file(struct }set_inode_flag (inode,FI_PIN_FILE ); - ret =F2FS_I (inode)->i_gc_failures[GC_FAILURE_PIN ]; + ret =F2FS_I (inode)->i_gc_failures; done:f2fs_update_time (F2FS_I_SB (inode),REQ_TIME ); out:
@@ -3327,7 +3325,7 @@ static int f2fs_ioc_get_pin_file(struct__u32 pin =0 ;if (is_inode_flag_set (inode,FI_PIN_FILE )) - pin =F2FS_I (inode)->i_gc_failures[GC_FAILURE_PIN ]; + pin =F2FS_I (inode)->i_gc_failures;return put_user (pin, (u32 __user *)arg); }
fs/f2fs/inode.c +2 -4
@@ -362,8 +362,7 @@ static int do_read_inode(struct inode *iif (S_ISDIR (inode->i_mode)) fi->i_current_depth =le32_to_cpu (ri->i_current_depth);else if (S_ISREG (inode->i_mode)) - fi->i_gc_failures[GC_FAILURE_PIN ] = -le16_to_cpu (ri->i_gc_failures); + fi->i_gc_failures =le16_to_cpu (ri->i_gc_failures); fi->i_xattr_nid =le32_to_cpu (ri->i_xattr_nid); fi->i_flags =le32_to_cpu (ri->i_flags);if (S_ISREG (inode->i_mode))
@@ -623,8 +622,7 @@ void f2fs_update_inode(struct inode *ino ri->i_current_depth =cpu_to_le32 (F2FS_I (inode)->i_current_depth); else if (S_ISREG(inode->i_mode)) - ri->i_gc_failures = -cpu_to_le16 (F2FS_I (inode)->i_gc_failures[GC_FAILURE_PIN ]); + ri->i_gc_failures = cpu_to_le16(F2FS_I(inode)->i_gc_failures); ri->i_xattr_nid =cpu_to_le32 (F2FS_I (inode)->i_xattr_nid); ri->i_flags =cpu_to_le32 (F2FS_I (inode)->i_flags); ri->i_pino =cpu_to_le32 (F2FS_I (inode)->i_pino);
fs/f2fs/recovery.c +1 -2
@@ -330,8 +330,7 @@ static int recover_inode(struct inode *iF2FS_I (inode)->i_advise = raw->i_advise;F2FS_I (inode)->i_flags =le32_to_cpu (raw->i_flags);f2fs_set_inode_flags (inode); -F2FS_I (inode)->i_gc_failures[GC_FAILURE_PIN ] = -le16_to_cpu (raw->i_gc_failures); +F2FS_I (inode)->i_gc_failures =le16_to_cpu (raw->i_gc_failures);recover_inline_flags (inode, raw);
Greg Kroah-Hartman
maintainerPATCH 553/634 f2fs: keep POSIX_FADV_NOREUSE ranges
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jaegeuk Kim <[email protected]>
[ Upstream commit ef0c333cad8d1940f132a7ce15f15920216a3bd5 ]
This patch records POSIX_FADV_NOREUSE ranges for users to reclaim the caches instantly off from LRU.
Stable-dep-of: 10b591e7fb7c ("f2fs: fix to avoid updating compression context during writeback")
--- fs/f2fs/debug.c | 3 ++ fs/f2fs/f2fs.h | 12 ++++++++++- fs/f2fs/file.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++----- fs/f2fs/inode.c | 14 +++++++++++++ fs/f2fs/super.c | 1 5 files changed, 84 insertions(+), 6 deletions(-)
fs/f2fs/debug.c +3 -0
@@ -97,6 +97,7 @@ static void update_general_status(struct si->ndirty_imeta =get_pages (sbi,F2FS_DIRTY_IMETA ); si->ndirty_dirs = sbi->ndirty_inode[DIR_INODE ]; si->ndirty_files = sbi->ndirty_inode[FILE_INODE ]; + si->ndonate_files = sbi->donate_files; si->nquota_files = sbi->nquota_files; si->ndirty_all = sbi->ndirty_inode[DIRTY_META ]; si->aw_cnt =atomic_read (&sbi->atomic_files);
@@ -402,6 +403,8 @@ static int stat_show(struct seq_file *s, si->compr_inode, si->compr_blocks);seq_printf (s," - Swapfile Inode: %u\n" , si->swapfile_inode); +seq_printf (s," - Donate Inode: %u\n" , + si->ndonate_files);seq_printf (s," - Orphan/Append/Update Inode: %u, %u, %u\n" , si->orphans, si->append, si->update); seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n",
fs/f2fs/f2fs.h +11 -1
@@ -820,6 +820,11 @@ struct f2fs_inode_info {#endif struct list_head dirty_list;/* dirty list for dirs and files */ struct list_head gdirty_list;/* linked in global dirty list */ + +/* linked in global inode list for cache donation */ +struct list_head gdonate_list; +pgoff_t donate_start, donate_end;/* inclusive */ +struct task_struct *atomic_write_task;/* store atomic write task */ struct extent_tree *extent_tree[NR_EXTENT_CACHES ];/* cached extent_tree entry */
@@ -1236,6 +1241,7 @@ enum inode_type {DIR_INODE ,/* for dirty dir inode */ FILE_INODE ,/* for dirty regular/symlink inode */ DIRTY_META ,/* for all dirtied inode metadata */ +DONATE_INODE ,/* for all inode to donate pages */ NR_INODE_TYPE, };
@@ -1650,6 +1656,9 @@ struct f2fs_sb_info {/* for extent tree cache */ struct extent_tree_info extent_tree[NR_EXTENT_CACHES ]; +/* control donate caches */ +unsigned int donate_files; +/* basic filesystem units */ unsigned int log_sectors_per_block;/* log2 sectors per block */ unsigned int log_blocksize;/* log2 block size */
@@ -3854,7 +3863,8 @@ struct f2fs_stat_info {unsigned long long hit_largest;int ndirty_node, ndirty_dent, ndirty_meta, ndirty_imeta;int ndirty_data, ndirty_qdata; -unsigned int ndirty_dirs, ndirty_files, nquota_files, ndirty_all; +unsigned int ndirty_dirs, ndirty_files, ndirty_all; +unsigned int nquota_files, ndonate_files;int nats, dirty_nats, sits, dirty_sits;int free_nids, avail_nids, alloc_nids;int total_count, utilization;
fs/f2fs/file.c +55 -5
73 lines not on this page · raw message
fs/f2fs/inode.c +14 -0
@@ -743,6 +743,19 @@ int f2fs_write_inode(struct inode *inodereturn 0 ; } +static void f2fs_remove_donate_inode (struct inode *inode) +{ +struct f2fs_sb_info *sbi =F2FS_I_SB (inode); + +if (list_empty (&F2FS_I (inode)->gdonate_list)) +return ; + +spin_lock (&sbi->inode_lock[DONATE_INODE ]); +list_del_init (&F2FS_I (inode)->gdonate_list); + sbi->donate_files--; +spin_unlock (&sbi->inode_lock[DONATE_INODE ]); +} +/* * Called at the last iput() if i_nlink is zero */
@@ -775,6 +788,7 @@ void f2fs_evict_inode(struct inode *inodf2fs_bug_on (sbi,get_dirty_pages (inode));f2fs_remove_dirty_inode (inode); +f2fs_remove_donate_inode (inode);f2fs_destroy_extent_tree (inode);
fs/f2fs/super.c +1 -0
@@ -1429,6 +1429,7 @@ static struct inode *f2fs_alloc_inode(stspin_lock_init (&fi->i_size_lock);INIT_LIST_HEAD (&fi->dirty_list);INIT_LIST_HEAD (&fi->gdirty_list); +INIT_LIST_HEAD (&fi->gdonate_list);init_f2fs_rwsem (&fi->i_gc_rwsem[READ ]);init_f2fs_rwsem (&fi->i_gc_rwsem[WRITE ]);init_f2fs_rwsem (&fi->i_xattr_sem);
Greg Kroah-Hartman
maintainerPATCH 554/634 f2fs: drop inode from the donation list when the last file is closed
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jaegeuk Kim <[email protected]>
[ Upstream commit 078cad8212ce4f4ebbafcc0936475b8215e1ca2a ]
Let's drop the inode from the donation list when there is no other open file.
Stable-dep-of: 10b591e7fb7c ("f2fs: fix to avoid updating compression context during writeback")
--- fs/f2fs/f2fs.h | 2 ++ fs/f2fs/file.c | 8 +++++++- fs/f2fs/inode.c | 2 +- fs/f2fs/super.c | 1 + 4 files changed, 11 insertions(+), 2 deletions(-)
fs/f2fs/f2fs.h +2 -0
@@ -824,6 +824,7 @@ struct f2fs_inode_info {/* linked in global inode list for cache donation */ struct list_head gdonate_list;pgoff_t donate_start, donate_end;/* inclusive */ +atomic_t open_count;/* # of open files */ struct task_struct *atomic_write_task;/* store atomic write task */ struct extent_tree *extent_tree[NR_EXTENT_CACHES ];
@@ -3473,6 +3474,7 @@ int f2fs_try_to_free_nats(struct f2fs_sbvoid f2fs_update_inode (struct inode *inode,struct page *node_page);void f2fs_update_inode_page (struct inode *inode);int f2fs_write_inode (struct inode *inode,struct writeback_control *wbc); +void f2fs_remove_donate_inode (struct inode *inode);void f2fs_evict_inode (struct inode *inode);void f2fs_handle_failed_inode (struct inode *inode);
fs/f2fs/file.c +7 -1
@@ -595,7 +595,10 @@ static int f2fs_file_open(struct inode *if (err)return err; -return finish_preallocate_blocks (inode); + err =finish_preallocate_blocks (inode); +if (!err) +atomic_inc (&F2FS_I (inode)->open_count); +return err; }void f2fs_truncate_data_blocks_range (struct dnode_of_data *dn,int count)
@@ -1923,6 +1926,9 @@ out:static int f2fs_release_file (struct inode *inode,struct file *filp) { +if (atomic_dec_and_test (&F2FS_I (inode)->open_count)) +f2fs_remove_donate_inode (inode); +/* * f2fs_release_file is called at every close calls. So we should * not drop any inmemory pages by close called by other process.
fs/f2fs/inode.c +1 -1
@@ -743,7 +743,7 @@ int f2fs_write_inode(struct inode *inodereturn 0 ; } -static void f2fs_remove_donate_inode (struct inode *inode) +void f2fs_remove_donate_inode (struct inode *inode) {struct f2fs_sb_info *sbi =F2FS_I_SB (inode);
fs/f2fs/super.c +1 -0
@@ -1425,6 +1425,7 @@ static struct inode *f2fs_alloc_inode(st/* Initialize f2fs-specific inode info */ atomic_set (&fi->dirty_pages,0 );atomic_set (&fi->i_compr_blocks,0 ); +atomic_set (&fi->open_count,0 );init_f2fs_rwsem (&fi->i_sem);spin_lock_init (&fi->i_size_lock);INIT_LIST_HEAD (&fi->dirty_list);
Greg Kroah-Hartman
maintainerPATCH 555/634 f2fs: fix to avoid updating compression context during writeback
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chao Yu <[email protected]>
[ Upstream commit 10b591e7fb7cdc8c1e53e9c000dc0ef7069aaa76 ]
Bai, Shuangpeng <[email protected]> reported a bug as below:
Oops: divide error: 0000 [#1] SMP KASAN PTI CPU: 0 UID: 0 PID: 11441 Comm: syz.0.46 Not tainted 6.17.0 #1 PREEMPT(full) Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014 RIP: 0010:f2fs_all_cluster_page_ready+0x106/0x550 fs/f2fs/compress.c:857 Call Trace: <TASK> f2fs_write_cache_pages fs/f2fs/data.c:3078 [inline] __f2fs_write_data_pages fs/f2fs/data.c:3290 [inline] f2fs_write_data_pages+0x1c19/0x3600 fs/f2fs/data.c:3317 do_writepages+0x38e/0x640 mm/page-writeback.c:2634 filemap_fdatawrite_wbc mm/filemap.c:386 [inline] __filemap_fdatawrite_range mm/filemap.c:419 [inline] file_write_and_wait_range+0x2ba/0x3e0 mm/filemap.c:794 f2fs_do_sync_file+0x6e6/0x1b00 fs/f2fs/file.c:294 generic_write_sync include/linux/fs.h:3043 [inline] f2fs_file_write_iter+0x76e/0x2700 fs/f2fs/file.c:5259 new_sync_write fs/read_write.c:593 [inline] vfs_write+0x7e9/0xe00 fs/read_write.c:686 ksys_write+0x19d/0x2d0 fs/read_write.c:738 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xf7/0x470 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f
The bug was triggered w/ below race condition:
fsync setattr ioctl
- f2fs_do_sync_file
- file_write_and_wait_range
- f2fs_write_cache_pages
: inode is non-compressed
: cc.cluster_size =
F2FS_I(inode)->i_cluster_size = 0
- tag_pages_for_writeback
- f2fs_setattr
- truncate_setsize
- f2fs_truncate
- f2fs_fileattr_set
- f2fs_setflags_common
- set_compress_context
: F2FS_I(inode)->i_cluster_size = 4 : set_inode_flag(inode, FI_COMPRESSED_FILE)
- f2fs_compressed_file
: return true
- f2fs_all_cluster_page_ready
: "pgidx % cc->cluster_size" trigger dividing 0 issue
Let's change as below to fix this issue:
- introduce a new atomic type variable .writeback in structure f2fs_inode_info to track the number of threads which calling f2fs_write_cache_pages().
- use .i_sem lock to protect .writeback update.
- check .writeback before update compression context in f2fs_setflags_common() to avoid race w/ ->writepages.
--- fs/f2fs/data.c | 17 +++++++++++++++++ fs/f2fs/f2fs.h | 3 ++- fs/f2fs/file.c | 5 +++-- fs/f2fs/super.c | 1 + 4 files changed, 23 insertions(+), 3 deletions(-)
fs/f2fs/data.c +17 -0
@@ -3262,6 +3262,19 @@ static inline bool __should_serialize_ioreturn false; } +static inline void account_writeback (struct inode *inode,bool inc) +{ +if (!f2fs_sb_has_compression (F2FS_I_SB (inode))) +return ; + +f2fs_down_read (&F2FS_I (inode)->i_sem); +if (inc) +atomic_inc (&F2FS_I (inode)->writeback); +else +atomic_dec (&F2FS_I (inode)->writeback); +f2fs_up_read (&F2FS_I (inode)->i_sem); +} +static int __f2fs_write_data_pages (struct address_space *mapping,struct writeback_control *wbc,enum iostat_type io_type)
@@ -3311,10 +3324,14 @@ static int __f2fs_write_data_pages(struc locked = true; } +account_writeback (inode, true); +blk_start_plug (&plug); ret =f2fs_write_cache_pages (mapping, wbc, io_type);blk_finish_plug (&plug); +account_writeback (inode, false); +if (locked)mutex_unlock (&sbi->writepages);
fs/f2fs/f2fs.h +2 -1
@@ -848,6 +848,7 @@ struct f2fs_inode_info {unsigned char i_compress_level;/* compress level (lz4hc,zstd) */ unsigned char i_compress_flag;/* compress flag */ unsigned int i_cluster_size;/* cluster size */ +atomic_t writeback;/* count # of writeback thread */ unsigned int atomic_write_cnt;loff_t original_i_size;/* original i_size before atomic write */
@@ -4375,7 +4376,7 @@ static inline bool f2fs_disable_compressf2fs_up_write (&F2FS_I (inode)->i_sem);return true; } -if (f2fs_is_mmap_file (inode) || +if (f2fs_is_mmap_file (inode) ||atomic_read (&fi->writeback) || (S_ISREG (inode->i_mode) &&F2FS_HAS_BLOCKS (inode))) {f2fs_up_write (&F2FS_I (inode)->i_sem);return false;
fs/f2fs/file.c +3 -2
@@ -2002,8 +2002,9 @@ static int f2fs_setflags_common(struct if2fs_down_write (&F2FS_I (inode)->i_sem);if (!f2fs_may_compress (inode) || - (S_ISREG (inode->i_mode) && -F2FS_HAS_BLOCKS (inode))) { +atomic_read (&fi->writeback) || + (S_ISREG (inode->i_mode) && +F2FS_HAS_BLOCKS (inode))) {f2fs_up_write (&F2FS_I (inode)->i_sem);return -EINVAL ; }
fs/f2fs/super.c +1 -0
@@ -1426,6 +1426,7 @@ static struct inode *f2fs_alloc_inode(statomic_set (&fi->dirty_pages,0 );atomic_set (&fi->i_compr_blocks,0 );atomic_set (&fi->open_count,0 ); +atomic_set (&fi->writeback,0 );init_f2fs_rwsem (&fi->i_sem);spin_lock_init (&fi->i_size_lock);INIT_LIST_HEAD (&fi->dirty_list);
Greg Kroah-Hartman
maintainerPATCH 556/634 f2fs: fix to propagate error from f2fs_enable_checkpoint()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chao Yu <[email protected]>
[ Upstream commit be112e7449a6e1b54aa9feac618825d154b3a5c7 ]
In order to let userspace detect such error rather than suffering silent failure.
--- fs/f2fs/super.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-)
fs/f2fs/super.c +15 -9
@@ -2222,9 +2222,10 @@ restore_flag:return err; } -static void f2fs_enable_checkpoint (struct f2fs_sb_info *sbi) +static int f2fs_enable_checkpoint (struct f2fs_sb_info *sbi) {int retry =DEFAULT_RETRY_IO_COUNT ; +int ret;/* we should flush all the data to keep data consistency */ do {
@@ -2242,10 +2243,14 @@ static void f2fs_enable_checkpoint(strucset_sbi_flag (sbi,SBI_IS_DIRTY );f2fs_up_write (&sbi->gc_lock); -f2fs_sync_fs (sbi->sb,1 ); + ret =f2fs_sync_fs (sbi->sb,1 ); +if (ret) +f2fs_err (sbi,"%s sync_fs failed, ret: %d" , __func__, ret);/* Let's ensure there's no pending checkpoint anymore */ f2fs_flush_ckpt_thread (sbi); + +return ret; }static int f2fs_remount (struct super_block *sb,int *flags,char *data)
@@ -2460,7 +2465,9 @@ static int f2fs_remount(struct super_bloif (err) goto restore_discard; }else { -f2fs_enable_checkpoint (sbi); + err =f2fs_enable_checkpoint (sbi); +if (err) + goto restore_discard; } }
@@ -4528,13 +4535,12 @@ reset_checkpoint:/* f2fs_recover_fsync_data() cleared this already */ clear_sbi_flag (sbi,SBI_POR_DOING ); -if (test_opt (sbi,DISABLE_CHECKPOINT )) { +if (test_opt (sbi,DISABLE_CHECKPOINT )) err =f2fs_disable_checkpoint (sbi); -if (err) - goto sync_free_meta; - }else if (is_set_ckpt_flags (sbi,CP_DISABLED_FLAG )) { -f2fs_enable_checkpoint (sbi); - } +else if (is_set_ckpt_flags (sbi,CP_DISABLED_FLAG )) + err =f2fs_enable_checkpoint (sbi); +if (err) + goto sync_free_meta;/* * If filesystem is not mounted as read-only then
Greg Kroah-Hartman
maintainerPATCH 557/634 f2fs: use global inline_xattr_slab instead of per-sb slab cache
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chao Yu <[email protected]>
[ Upstream commit 1f27ef42bb0b7c0740c5616ec577ec188b8a1d05 ]
As Hong Yun reported in mailing list:
loop7: detected capacity change from 0 to 131072
------------[ cut here ]------------ kmem_cache of name 'f2fs_xattr_entry-7:7' already exists WARNING: CPU: 0 PID: 24426 at mm/slab_common.c:110 kmem_cache_sanity_check mm/slab_common.c:109 [inline] WARNING: CPU: 0 PID: 24426 at mm/slab_common.c:110 __kmem_cache_create_args+0xa6/0x320 mm/slab_common.c:307 CPU: 0 UID: 0 PID: 24426 Comm: syz.7.1370 Not tainted 6.17.0-rc4 #1 PREEMPT(full) Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014 RIP: 0010:kmem_cache_sanity_check mm/slab_common.c:109 [inline] RIP: 0010:__kmem_cache_create_args+0xa6/0x320 mm/slab_common.c:307 Call Trace: __kmem_cache_create include/linux/slab.h:353 [inline] f2fs_kmem_cache_create fs/f2fs/f2fs.h:2943 [inline] f2fs_init_xattr_caches+0xa5/0xe0 fs/f2fs/xattr.c:843 f2fs_fill_super+0x1645/0x2620 fs/f2fs/super.c:4918 get_tree_bdev_flags+0x1fb/0x260 fs/super.c:1692 vfs_get_tree+0x43/0x140 fs/super.c:1815 do_new_mount+0x201/0x550 fs/namespace.c:3808 do_mount fs/namespace.c:4136 [inline] __do_sys_mount fs/namespace.c:4347 [inline] __se_sys_mount+0x298/0x2f0 fs/namespace.c:4324 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0x8e/0x3a0 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x76/0x7e
The bug can be reproduced w/ below scripts:
- mount /dev/vdb /mnt1
- mount /dev/vdc /mnt2
- umount /mnt1
- mounnt /dev/vdb /mnt1
The reason is if we created two slab caches, named f2fs_xattr_entry-7:3 and f2fs_xattr_entry-7:7, and they have the same slab size. Actually, slab system will only create one slab cache core structure which has slab name of "f2fs_xattr_entry-7:3", and two slab caches share the same structure and cache address.
So, if we destroy f2fs_xattr_entry-7:3 cache w/ cache address, it will decrease reference count of slab cache, rather than release slab cache entirely, since there is one more user has referenced the cache.
Then, if we try to create slab cache w/ name "f2fs_xattr_entry-7:3" again, slab system will find that there is existed cache which has the same name and trigger the warning.
Let's changes to use global inline_xattr_slab instead of per-sb slab cache for fixing.
--- fs/f2fs/f2fs.h | 3 --- fs/f2fs/super.c | 15 +++++++-------- fs/f2fs/xattr.c | 30 ++++++++++-------------------- fs/f2fs/xattr.h | 10 ++++++---- 4 files changed, 23 insertions(+), 35 deletions(-)
fs/f2fs/f2fs.h +0 -3
@@ -1807,9 +1807,6 @@ struct f2fs_sb_info {spinlock_t error_lock;/* protect errors array */ bool error_dirty;/* errors of sb is dirty */ -struct kmem_cache *inline_xattr_slab;/* inline xattr entry */ -unsigned int inline_xattr_slab_size;/* default inline xattr slab size */ -/* For reclaimed segs statistics per each GC mode */ unsigned int gc_segment_mode;/* GC state for reclaimed segments */ unsigned int gc_reclaimed_segs[MAX_GC_MODE ];/* Reclaimed segs for each mode */
fs/f2fs/super.c +7 -8
@@ -1674,7 +1674,6 @@ static void f2fs_put_super(struct super_destroy_device_list (sbi);f2fs_destroy_page_array_cache (sbi); -f2fs_destroy_xattr_caches (sbi);mempool_destroy (sbi->write_io_dummy);#ifdef CONFIG_QUOTA for (i =0 ; i <MAXQUOTAS ; i++)
@@ -4305,13 +4304,9 @@ try_onemore: } } -/* init per sbi slab cache */ - err =f2fs_init_xattr_caches (sbi); -if (err) - goto free_io_dummy; err =f2fs_init_page_array_cache (sbi);if (err) - goto free_xattr_cache; + goto free_io_dummy;/* get an inode for meta space */ sbi->meta_inode =f2fs_iget (sb,F2FS_META_INO (sbi));
@@ -4624,8 +4619,6 @@ free_meta_inode: sbi->meta_inode =NULL ; free_page_array_cache:f2fs_destroy_page_array_cache (sbi); -free_xattr_cache: -f2fs_destroy_xattr_caches (sbi); free_io_dummy:mempool_destroy (sbi->write_io_dummy); free_percpu:
@@ -4792,7 +4785,12 @@ static int __init init_f2fs_fs(void) err =f2fs_create_casefold_cache ();if (err) goto free_compress_cache; + err =f2fs_init_xattr_cache (); +if (err) + goto free_casefold_cache;return 0 ; +free_casefold_cache: +f2fs_destroy_casefold_cache (); free_compress_cache:f2fs_destroy_compress_cache (); free_compress_mempool:
@@ -4832,6 +4830,7 @@ fail: static void __exit exit_f2fs_fs(void) { +f2fs_destroy_xattr_cache ();f2fs_destroy_casefold_cache ();f2fs_destroy_compress_cache ();f2fs_destroy_compress_mempool ();
fs/f2fs/xattr.c +10 -20
@@ -23,11 +23,12 @@#include "xattr.h" #include "segment.h" +static struct kmem_cache *inline_xattr_slab;static void *xattr_alloc (struct f2fs_sb_info *sbi,int size,bool *is_inline) { -if (likely (size == sbi->inline_xattr_slab_size)) { +if (likely (size ==DEFAULT_XATTR_SLAB_SIZE )) { *is_inline = true; -return f2fs_kmem_cache_alloc (sbi->inline_xattr_slab, +return f2fs_kmem_cache_alloc (inline_xattr_slab,GFP_F2FS_ZERO , false, sbi); } *is_inline = false;
@@ -38,7 +39,7 @@ static void xattr_free(struct f2fs_sb_in bool is_inline) {if (is_inline) -kmem_cache_free (sbi->inline_xattr_slab, xattr_addr); +kmem_cache_free (inline_xattr_slab, xattr_addr);else kfree (xattr_addr); }
@@ -830,25 +831,14 @@ int f2fs_setxattr(struct inode *inode, ireturn err; } -int f2fs_init_xattr_caches (struct f2fs_sb_info *sbi) +int __init f2fs_init_xattr_cache (void ) { -dev_t dev = sbi->sb->s_bdev->bd_dev; -char slab_name[32 ]; - -sprintf (slab_name,"f2fs_xattr_entry-%u:%u" ,MAJOR (dev),MINOR (dev)); - - sbi->inline_xattr_slab_size =F2FS_OPTION (sbi).inline_xattr_size * -sizeof (__le32) +XATTR_PADDING_SIZE ; - - sbi->inline_xattr_slab =f2fs_kmem_cache_create (slab_name, - sbi->inline_xattr_slab_size); -if (!sbi->inline_xattr_slab) -return -ENOMEM ; - -return 0 ; + inline_xattr_slab =f2fs_kmem_cache_create ("f2fs_xattr_entry" , +DEFAULT_XATTR_SLAB_SIZE ); +return inline_xattr_slab ?0 : -ENOMEM ; } -void f2fs_destroy_xattr_caches (struct f2fs_sb_info *sbi) +void f2fs_destroy_xattr_cache (void ) { -kmem_cache_destroy (sbi->inline_xattr_slab); +kmem_cache_destroy (inline_xattr_slab); }
fs/f2fs/xattr.h +6 -4
@@ -88,6 +88,8 @@ struct f2fs_xattr_entry { F2FS_TOTAL_EXTRA_ATTR_SIZE / sizeof(__le32) - \ DEF_INLINE_RESERVED_SIZE - \ MIN_INLINE_DENTRY_SIZE / sizeof(__le32)) +#define DEFAULT_XATTR_SLAB_SIZE (DEFAULT_INLINE_XATTR_ADDRS * \ + sizeof(__le32) + XATTR_PADDING_SIZE)/* * On-disk structure of f2fs_xattr
@@ -131,8 +133,8 @@ extern int f2fs_setxattr(struct inode *,extern int f2fs_getxattr (struct inode *,int ,const char *,void *,size_t ,struct page *);extern ssize_t f2fs_listxattr (struct dentry *,char *,size_t ); -extern int f2fs_init_xattr_caches (struct f2fs_sb_info *); -extern void f2fs_destroy_xattr_caches (struct f2fs_sb_info *); +int __init f2fs_init_xattr_cache (void ); +void f2fs_destroy_xattr_cache (void );#else #define f2fs_xattr_handlers NULL
@@ -149,8 +151,8 @@ static inline int f2fs_getxattr(struct i {return -EOPNOTSUPP ; } -static inline int f2fs_init_xattr_caches (struct f2fs_sb_info *sbi) {return 0 ; } -static inline void f2fs_destroy_xattr_caches (struct f2fs_sb_info *sbi) { } +static inline int __init f2fs_init_xattr_cache (void ) {return 0 ; } +static inline void f2fs_destroy_xattr_cache (void ) { }#endif #ifdef CONFIG_F2FS_FS_SECURITY
Greg Kroah-Hartman
maintainerPATCH 558/634 f2fs: fix to detect recoverable inode during dryrun of find_fsync_dnodes()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chao Yu <[email protected]>
[ Upstream commit 68d05693f8c031257a0822464366e1c2a239a512 ]
mkfs.f2fs -f /dev/vdd
mount /dev/vdd /mnt/f2fs
touch /mnt/f2fs/foo
sync # avoid CP_UMOUNT_FLAG in last f2fs_checkpoint.ckpt_flags
touch /mnt/f2fs/barf2fs_io fsync /mnt/f2fs/barf2fs_io shutdown 2 /mnt/f2fs
umount /mnt/f2fs
blockdev --setro /dev/vdd
mount /dev/vdd /mnt/f2fs
mount: /mnt/f2fs: WARNING: source write-protected, mounted read-only.
For the case if we create and fsync a new inode before sudden power-cut, without norecovery or disable_roll_forward mount option, the following mount will succeed w/o recovering last fsynced inode.
The problem here is that we only check inode_list list after find_fsync_dnodes() in f2fs_recover_fsync_data() to find out whether there is recoverable data in the iamge, but there is a missed case, if last fsynced inode is not existing in last checkpoint, then, we will fail to get its inode due to nat of inode node is not existing in last checkpoint, so the inode won't be linked in inode_list.
Let's detect such case in dyrun mode to fix this issue.
After this change, mount will fail as expected below:
mount: /mnt/f2fs: cannot mount /dev/vdd read-only.
dmesg(1) may have more information after failed mount system call.
demsg:
F2FS-fs (vdd): Need to recover fsync data, but write access unavailable, please try mount w/ disable_roll_forward or norecovery
--- fs/f2fs/recovery.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
fs/f2fs/recovery.c +6 -3
@@ -360,7 +360,7 @@ static unsigned int adjust_por_ra_blocks }static int find_fsync_dnodes (struct f2fs_sb_info *sbi,struct list_head *head, -bool check_only) +bool check_only,bool *new_inode) {struct curseg_info *curseg;struct page *page =NULL ;
@@ -418,6 +418,8 @@ static int find_fsync_dnodes(struct f2fsif (IS_ERR (entry)) { err =PTR_ERR (entry);if (err == -ENOENT ) { +if (check_only) + *new_inode = true; err =0 ; goto next; }
@@ -834,6 +836,7 @@ int f2fs_recover_fsync_data(struct f2fs_unsigned long s_flags = sbi->sb->s_flags;bool need_writecp = false;bool fix_curseg_write_pointer = false; +bool new_inode = false;#ifdef CONFIG_QUOTA int quota_enabled;#endif
@@ -856,8 +859,8 @@ int f2fs_recover_fsync_data(struct f2fs_f2fs_down_write (&sbi->cp_global_sem);/* step #1: find fsynced inode numbers */ - err =find_fsync_dnodes (sbi, &inode_list, check_only); -if (err ||list_empty (&inode_list)) + err =find_fsync_dnodes (sbi, &inode_list, check_only, &new_inode); +if (err <0 || (list_empty (&inode_list) && (!check_only || !new_inode))) goto skip;if (check_only) {
Greg Kroah-Hartman
maintainerPATCH 559/634 NFSD: Clear SECLABEL in the suppattr_exclcreat bitmap
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 27d17641cacfedd816789b75d342430f6b912bd2 ]
Quoted 1 line
Quoted 1 line
From RFC 8881:
5.8.1.14. Attribute 75: suppattr_exclcreat
Quoted 4 lines
The bit vector that would set all REQUIRED and RECOMMENDED attributes that are supported by the
EXCLUSIVE4_1method of file creation via the OPEN operation. The scope of this attribute applies to all objects with a matching fsid.
There's nothing in RFC 8881 that states that suppattr_exclcreat is or is not allowed to contain bits for attributes that are clear in the reported supported_attrs bitmask. But it doesn't make sense for an NFS server to indicate that it /doesn't/ implement an attribute, but then also indicate that clients /are/ allowed to set that attribute using OPEN(create) with EXCLUSIVE4_1.
Ensure that the SECURITY_LABEL and ACL bits are not set in the suppattr_exclcreat bitmask when they are also not set in the supported_attrs bitmask.
--- fs/nfsd/nfs4xdr.c | 5 +++++ 1 file changed, 5 insertions(+)
fs/nfsd/nfs4xdr.c +5 -0
@@ -3408,6 +3408,11 @@ out_acl:u32 supp[3 ];memcpy (supp, nfsd_suppattrs[minorversion],sizeof (supp)); +if (!IS_POSIXACL (d_inode (dentry))) + supp[0 ] &= ~FATTR4_WORD0_ACL ; +if (!contextsupport) + supp[2 ] &= ~FATTR4_WORD2_SECURITY_LABEL ; + supp[0 ] &=NFSD_SUPPATTR_EXCLCREAT_WORD0 ; supp[1 ] &=NFSD_SUPPATTR_EXCLCREAT_WORD1 ; supp[2 ] &=NFSD_SUPPATTR_EXCLCREAT_WORD2 ;
Greg Kroah-Hartman
maintainerPATCH 560/634 SUNRPC: svcauth_gss: avoid NULL deref on zero length gss_token in gss_read_proxy_verf
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joshua Rogers <[email protected]>
[ Upstream commit d4b69a6186b215d2dc1ebcab965ed88e8d41768d ]
A zero length gss_token results in pages == 0 and in_token->pages[0] is NULL. The code unconditionally evaluates page_address(in_token->pages[0]) for the initial memcpy, which can dereference NULL even when the copy length is 0. Guard the first memcpy so it only runs when length > 0.
--- net/sunrpc/auth_gss/svcauth_gss.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/sunrpc/auth_gss/svcauth_gss.c +2 -1
@@ -1179,7 +1179,8 @@ static int gss_read_proxy_verf(struct sv } length = min_t(unsigned int, inlen, argv->iov_len); -memcpy (page_address (in_token->pages[0 ]), argv->iov_base, length); +if (length) +memcpy (page_address (in_token->pages[0 ]), argv->iov_base, length); inlen -= length; to_offs = length;
Greg Kroah-Hartman
maintainerPATCH 561/634 btrfs: dont log conflicting inode if its a dir moved in the current transaction
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana <[email protected]>
[ Upstream commit 266273eaf4d99475f1ae57f687b3e42bc71ec6f0 ]
We can't log a conflicting inode if it's a directory and it was moved from one parent directory to another parent directory in the current transaction, as this can result an attempt to have a directory with two hard links during log replay, one for the old parent directory and another for the new parent directory.
The following scenario triggers that issue:
1) We have directories "dir1" and "dir2" created in a past transaction. Directory "dir1" has inode A as its parent directory;
2) We move "dir1" to some other directory;
3) We create a file with the name "dir1" in directory inode A;
4) We fsync the new file. This results in logging the inode of the new file and the inode for the directory "dir1" that was previously moved in the current transaction. So the log tree has the INODE_REF item for the new location of "dir1";
5) We move the new file to some other directory. This results in updating the log tree to included the new INODE_REF for the new location of the file and removes the INODE_REF for the old location. This happens during the rename when we call btrfs_log_new_name();
6) We fsync the file, and that persists the log tree changes done in the previous step (btrfs_log_new_name() only updates the log tree in memory);
7) We have a power failure;
8) Next time the fs is mounted, log replay happens and when processing the inode for directory "dir1" we find a new INODE_REF and add that link, but we don't remove the old link of the inode since we have not logged the old parent directory of the directory inode "dir1".
As a result after log replay finishes when we trigger writeback of the subvolume tree's extent buffers, the tree check will detect that we have a directory a hard link count of 2 and we get a mount failure. The errors and stack traces reported in dmesg/syslog are like this:
[ 3845.729764] BTRFS info (device dm-0): start tree-log replay [ 3845.730304] page: refcount:3 mapcount:0 mapping:000000005c8a3027 index:0x1d00 pfn:0x11510c [ 3845.731236] memcg:ffff9264c02f4e00 [ 3845.731751] aops:btree_aops [btrfs] ino:1 [ 3845.732300] flags: 0x17fffc00000400a(uptodate|private|writeback|node=0|zone=2|lastcpupid=0x1ffff) [ 3845.733346] raw: 017fffc00000400a 0000000000000000 dead000000000122 ffff9264d978aea8 [ 3845.734265] raw: 0000000000001d00 ffff92650e6d4738 00000003ffffffff ffff9264c02f4e00 [ 3845.735305] page dumped because: eb page dump [ 3845.735981] BTRFS critical (device dm-0): corrupt leaf: root=5 block=30408704 slot=6 ino=257, invalid nlink: has 2 expect no more than 1 for dir [ 3845.737786] BTRFS info (device dm-0): leaf 30408704 gen 10 total ptrs 17 free space 14881 owner 5 [ 3845.737789] BTRFS info (device dm-0): refs 4 lock_owner 0 current 30701 [ 3845.737792] item 0 key (256 INODE_ITEM 0) itemoff 16123 itemsize 160 [ 3845.737794] inode generation 3 transid 9 size 16 nbytes 16384 [ 3845.737795] block group 0 mode 40755 links 1 uid 0 gid 0 [ 3845.737797] rdev 0 sequence 2 flags 0x0 [ 3845.737798] atime 1764259517.0 [ 3845.737800] ctime 1764259517.572889464 [ 3845.737801] mtime 1764259517.572889464 [ 3845.737802] otime 1764259517.0 [ 3845.737803] item 1 key (256 INODE_REF 256) itemoff 16111 itemsize 12 [ 3845.737805] index 0 name_len 2 [ 3845.737807] item 2 key (256 DIR_ITEM 2363071922) itemoff 16077 itemsize 34 [ 3845.737808] location key (257 1 0) type 2 [ 3845.737810] transid 9 data_len 0 name_len 4 [ 3845.737811] item 3 key (256 DIR_ITEM 2676584006) itemoff 16043 itemsize 34 [ 3845.737813] location key (258 1 0) type 2 [ 3845.737814] transid 9 data_len 0 name_len 4 [ 3845.737815] item 4 key (256 DIR_INDEX 2) itemoff 16009 itemsize 34 [ 3845.737816] location key (257 1 0) type 2 [ 3845.737818] transid 9 data_len 0 name_len 4 [ 3845.737819] item 5 key (256 DIR_INDEX 3) itemoff 15975 itemsize 34 [ 3845.737820] location key (258 1 0) type 2 [ 3845.737821] transid 9 data_len 0 name_len 4 [ 3845.737822] item 6 key (257 INODE_ITEM 0) itemoff 15815 itemsize 160 [ 3845.737824] inode generation 9 transid 10 size 6 nbytes 0 [ 3845.737825] block group 0 mode 40755 links 2 uid 0 gid 0 [ 3845.737826] rdev 0 sequence 1 flags 0x0 [ 3845.737827] atime 1764259517.572889464 [ 3845.737828] ctime 1764259517.572889464 [ 3845.737830] mtime 1764259517.572889464 [ 3845.737831] otime 1764259517.572889464 [ 3845.737832] item 7 key (257 INODE_REF 256) itemoff 15801 itemsize 14 [ 3845.737833] index 2 name_len 4 [ 3845.737834] item 8 key (257 INODE_REF 258) itemoff 15787 itemsize 14 [ 3845.737836] index 2 name_len 4 [ 3845.737837] item 9 key (257 DIR_ITEM 2507850652) itemoff 15754 itemsize 33 [ 3845.737838] location key (259 1 0) type 1 [ 3845.737839] transid 10 data_len 0 name_len 3 [ 3845.737840] item 10 key (257 DIR_INDEX 2) itemoff 15721 itemsize 33 [ 3845.737842] location key (259 1 0) type 1 [ 3845.737843] transid 10 data_len 0 name_len 3 [ 3845.737844] item 11 key (258 INODE_ITEM 0) itemoff 15561 itemsize 160 [ 3845.737846] inode generation 9 transid 10 size 8 nbytes 0 [ 3845.737847] block group 0 mode 40755 links 1 uid 0 gid 0 [ 3845.737848] rdev 0 sequence 1 flags 0x0 [ 3845.737849] atime 1764259517.572889464 [ 3845.737850] ctime 1764259517.572889464 [ 3845.737851] mtime 1764259517.572889464 [ 3845.737852] otime 1764259517.572889464 [ 3845.737853] item 12 key (258 INODE_REF 256) itemoff 15547 itemsize 14 [ 3845.737855] index 3 name_len 4 [ 3845.737856] item 13 key (258 DIR_ITEM 1843588421) itemoff 15513 itemsize 34 [ 3845.737857] location key (257 1 0) type 2 [ 3845.737858] transid 10 data_len 0 name_len 4 [ 3845.737860] item 14 key (258 DIR_INDEX 2) itemoff 15479 itemsize 34 [ 3845.737861] location key (257 1 0) type 2 [ 3845.737862] transid 10 data_len 0 name_len 4 [ 3845.737863] item 15 key (259 INODE_ITEM 0) itemoff 15319 itemsize 160 [ 3845.737865] inode generation 10 transid 10 size 0 nbytes 0 [ 3845.737866] block group 0 mode 100600 links 1 uid 0 gid 0 [ 3845.737867] rdev 0 sequence 2 flags 0x0 [ 3845.737868] atime 1764259517.580874966 [ 3845.737869] ctime 1764259517.586121869 [ 3845.737870] mtime 1764259517.580874966 [ 3845.737872] otime 1764259517.580874966 [ 3845.737873] item 16 key (259 INODE_REF 257) itemoff 15306 itemsize 13 [ 3845.737874] index 2 name_len 3 [ 3845.737875] BTRFS error (device dm-0): block=30408704 write time tree block corruption detected [ 3845.739448] ------------[ cut here ]------------ [ 3845.740092] WARNING: CPU: 5 PID: 30701 at fs/btrfs/disk-io.c:335 btree_csum_one_bio+0x25a/0x270 [btrfs] [ 3845.741439] Modules linked in: btrfs dm_flakey crc32c_cryptoapi (...) [ 3845.750626] CPU: 5 UID: 0 PID: 30701 Comm: mount Tainted: G W 6.18.0-rc6-btrfs-next-218+ #1 PREEMPT(full) [ 3845.752414] Tainted: [W]=WARN [ 3845.752828] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.2-0-gea1b7a073390-prebuilt.qemu.org 04/01/2014 [ 3845.754499] RIP: 0010:btree_csum_one_bio+0x25a/0x270 [btrfs] [ 3845.755460] Code: 31 f6 48 89 (...) [ 3845.758685] RSP: 0018:ffffa8d9c5677678 EFLAGS: 00010246 [ 3845.759450] RAX: 0000000000000000 RBX: ffff92650e6d4738 RCX: 0000000000000000 [ 3845.760309] RDX: 0000000000000000 RSI: ffffffff9aab45b9 RDI: ffff9264c4748000 [ 3845.761239] RBP: ffff9264d4324000 R08: 0000000000000000 R09: ffffa8d9c5677468 [ 3845.762607] R10: ffff926bdc1fffa8 R11: 0000000000000003 R12: ffffa8d9c5677680 [ 3845.764099] R13: 0000000000004000 R14: ffff9264dd624000 R15: ffff9264d978aba8 [ 3845.765094] FS: 00007f751fa5a840(0000) GS:ffff926c42a82000(0000) knlGS:0000000000000000 [ 3845.766226] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 3845.766970] CR2: 0000558df1815380 CR3: 000000010ed88003 CR4: 0000000000370ef0 [ 3845.768009] Call Trace: [ 3845.768392] <TASK> [ 3845.768714] btrfs_submit_bbio+0x6ee/0x7f0 [btrfs] [ 3845.769640] ? write_one_eb+0x28e/0x340 [btrfs] [ 3845.770588] btree_write_cache_pages+0x2f0/0x550 [btrfs] [ 3845.771286] ? alloc_extent_state+0x19/0x100 [btrfs] [ 3845.771967] ? merge_next_state+0x1a/0x90 [btrfs] [ 3845.772586] ? set_extent_bit+0x233/0x8b0 [btrfs] [ 3845.773198] ? xas_load+0x9/0xc0 [ 3845.773589] ? xas_find+0x14d/0x1a0 [ 3845.773969] do_writepages+0xc6/0x160 [ 3845.774367] filemap_fdatawrite_wbc+0x48/0x60 [ 3845.775003] __filemap_fdatawrite_range+0x5b/0x80 [ 3845.775902] btrfs_write_marked_extents+0x61/0x170 [btrfs] [ 3845.776707] btrfs_write_and_wait_transaction+0x4e/0xc0 [btrfs] [ 3845.777379] ? _raw_spin_unlock_irqrestore+0x23/0x40 [ 3845.777923] btrfs_commit_transaction+0x5ea/0xd20 [btrfs] [ 3845.778551] ? _raw_spin_unlock+0x15/0x30 [ 3845.778986] ? release_extent_buffer+0x34/0x160 [btrfs] [ 3845.779659] btrfs_recover_log_trees+0x7a3/0x7c0 [btrfs] [ 3845.780416] ? __pfx_replay_one_buffer+0x10/0x10 [btrfs] [ 3845.781499] open_ctree+0x10bb/0x15f0 [btrfs] [ 3845.782194] btrfs_get_tree.cold+0xb/0x16c [btrfs] [ 3845.782764] ? fscontext_read+0x15c/0x180 [ 3845.783202] ? rw_verify_area+0x50/0x180 [ 3845.783667] vfs_get_tree+0x25/0xd0 [ 3845.784047] vfs_cmd_create+0x59/0xe0 [ 3845.784458] __do_sys_fsconfig+0x4f6/0x6b0 [ 3845.784914] do_syscall_64+0x50/0x1220 [ 3845.785340] entry_SYSCALL_64_after_hwframe+0x76/0x7e [ 3845.785980] RIP: 0033:0x7f751fc7f4aa [ 3845.786759] Code: 73 01 c3 48 (...) [ 3845.789951] RSP: 002b:00007ffcdba45dc8 EFLAGS: 00000246 ORIG_RAX: 00000000000001af [ 3845.791402] RAX: ffffffffffffffda RBX: 000055ccc8291c20 RCX: 00007f751fc7f4aa [ 3845.792688] RDX: 0000000000000000 RSI: 0000000000000006 RDI: 0000000000000003 [ 3845.794308] RBP: 000055ccc8292120 R08: 0000000000000000 R09: 0000000000000000 [ 3845.795829] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 [ 3845.797183] R13: 00007f751fe11580 R14: 00007f751fe1326c R15: 00007f751fdf8a23 [ 3845.798633] </TASK> [ 3845.799067] ---[ end trace 0000000000000000 ]--- [ 3845.800215] BTRFS: error (device dm-0) in btrfs_commit_transaction:2553: errno=-5 IO failure (Error while writing out transaction) [ 3845.801860] BTRFS warning (device dm-0 state E): Skipping commit of aborted transaction. [ 3845.802815] BTRFS error (device dm-0 state EA): Transaction aborted (error -5) [ 3845.803728] BTRFS: error (device dm-0 state EA) in cleanup_transaction:2036: errno=-5 IO failure [ 3845.805374] BTRFS: error (device dm-0 state EA) in btrfs_replay_log:2083: errno=-5 IO failure (Failed to recover log tree) [ 3845.807919] BTRFS error (device dm-0 state EA): open_ctree failed: -5
Fix this by never logging a conflicting inode that is a directory and was moved in the current transaction (its last_unlink_trans equals the current transaction) and instead fallback to a transaction commit.
A test case for fstests will follow soon.
--- fs/btrfs/tree-log.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+)
fs/btrfs/tree-log.c +38 -0
@@ -5638,6 +5638,33 @@ static int conflicting_inode_is_dir(strureturn ret; } +static bool can_log_conflicting_inode (const struct btrfs_trans_handle *trans, +const struct btrfs_inode *inode) +{ +if (!S_ISDIR (inode->vfs_inode.i_mode)) +return true; + +if (inode->last_unlink_trans < trans->transid) +return true; + +/* +* If this is a directory and its unlink_trans is not from a past +* transaction then we must fallback to a transaction commit in order +* to avoid getting a directory with 2 hard links after log replay. +* +* This happens if a directory A is renamed, moved from one parent +* directory to another one, a new file is created in the old parent +* directory with the old name of our directory A, the new file is +* fsynced, then we moved the new file to some other parent directory +* and fsync again the new file. This results in a log tree where we +* logged that directory A existed, with the INODE_REF item for the +* new location but without having logged its old parent inode, so +* that on log replay we add a new link for the new location but the +* old link remains, resulting in a link count of 2. +*/ +return false; +} + static int add_conflicting_inode(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path,
@@ -5743,6 +5770,11 @@ static int add_conflicting_inode(structreturn 0 ; } +if (!can_log_conflicting_inode (trans,BTRFS_I (inode))) { +btrfs_add_delayed_iput (inode); +return BTRFS_LOG_FORCE_COMMIT ; + } +btrfs_add_delayed_iput (inode); ino_elem =kmalloc (sizeof (*ino_elem),GFP_NOFS );
@@ -5808,6 +5840,12 @@ static int log_conflicting_inodes(structbreak ; } +if (!can_log_conflicting_inode (trans,BTRFS_I (inode))) { +btrfs_add_delayed_iput (inode); + ret =BTRFS_LOG_FORCE_COMMIT ; +break ; + } +/* * Always log the directory, we cannot make this * conditional on need_log_inode() because the directory
Greg Kroah-Hartman
maintainerPATCH 562/634 crypto: af_alg - zero initialize memory allocated via sock_kmalloc
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shivani Agarwal <[email protected]>
[ Upstream commit 6f6e309328d53a10c0fe1f77dec2db73373179b6 ]
Several crypto user API contexts and requests allocated with sock_kmalloc() were left uninitialized, relying on callers to set fields explicitly. This resulted in the use of uninitialized data in certain error paths or when new fields are added in the future.
The ACVP patches also contain two user-space interface files:algif_kpp.c and algif_akcipher.c. These too rely on proper initialization of their context structures.
A particular issue has been observed with the newly added 'inflight' variable introduced in af_alg_ctx by commit:
67b164a871af ("crypto: af_alg - Disallow multiple in-flight AIO requests")
Because the context is not memset to zero after allocation, the inflight variable has contained garbage values. As a result, af_alg_alloc_areq() has incorrectly returned -EBUSY randomly when the garbage value was interpreted as true:
https://github.com/gregkh/linux/blame/master/crypto/af_alg.c#L1209
The check directly tests ctx->inflight without explicitly comparing against true/false. Since inflight is only ever set to true or false later, an uninitialized value has triggered -EBUSY failures. Zero-initializing memory allocated with sock_kmalloc() ensures inflight and other fields start in a known state, removing random issues caused by uninitialized data.
--- crypto/af_alg.c | 5 ++--- crypto/algif_hash.c | 3 +-- crypto/algif_rng.c | 3 +-- 3 files changed, 4 insertions(+), 7 deletions(-)
crypto/af_alg.c +2 -3
@@ -1108,14 +1108,13 @@ struct af_alg_async_req *af_alg_alloc_arif (unlikely (!areq))return ERR_PTR (-ENOMEM ); +memset (areq,0 , areqlen); + ctx->inflight = true; areq->areqlen = areqlen; areq->sk = sk; - areq->last_rsgl =NULL ;INIT_LIST_HEAD (&areq->rsgl_list); - areq->tsgl =NULL ; - areq->tsgl_entries =0 ;return areq; }
crypto/algif_hash.c +1 -2
@@ -424,9 +424,8 @@ static int hash_accept_parent_nokey(voidif (!ctx)return -ENOMEM ; - ctx->result =NULL ; +memset (ctx,0 , len); ctx->len = len; - ctx->more = false;crypto_init_wait (&ctx->wait); ask->private = ctx;
crypto/algif_rng.c +1 -2
@@ -250,9 +250,8 @@ static int rng_accept_parent(void *privaif (!ctx)return -ENOMEM ; +memset (ctx,0 , len); ctx->len = len; - ctx->addtl =NULL ; - ctx->addtl_len =0 ;/* * No seeding done at that point -- if multiple accepts are
Greg Kroah-Hartman
maintainerPATCH 563/634 ARM: dts: microchip: sama5d2: fix spi flexcom fifo size to 32
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolas Ferre <[email protected]>
[ Upstream commit 7d5864dc5d5ea6a35983dd05295fb17f2f2f44ce ]
Unlike standalone spi peripherals, on sama5d2, the flexcom spi have fifo size of 32 data. Fix flexcom/spi nodes where this property is wrong.
--- arch/arm/boot/dts/sama5d2.dtsi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
arch/arm/boot/dts/sama5d2.dtsi +5 -5
@@ -568,7 +568,7 @@ AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(12))>; dma-names = "tx", "rx"; - atmel,fifo-size = <16>; + atmel,fifo-size = <32>; status = "disabled"; };
@@ -639,7 +639,7 @@ AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(14))>; dma-names = "tx", "rx"; - atmel,fifo-size = <16>; + atmel,fifo-size = <32>; status = "disabled"; };
@@ -852,7 +852,7 @@ AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(16))>; dma-names = "tx", "rx"; - atmel,fifo-size = <16>; + atmel,fifo-size = <32>; status = "disabled"; };
@@ -923,7 +923,7 @@ AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(18))>; dma-names = "tx", "rx"; - atmel,fifo-size = <16>; + atmel,fifo-size = <32>; status = "disabled"; };
@@ -995,7 +995,7 @@ AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(20))>; dma-names = "tx", "rx"; - atmel,fifo-size = <16>; + atmel,fifo-size = <32>; status = "disabled"; };
Greg Kroah-Hartman
maintainerPATCH 564/634 ARM: dts: microchip: sama7g5: fix uart fifo size to 32
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolas Ferre <[email protected]>
[ Upstream commit 5654889a94b0de5ad6ceae3793e7f5e0b61b50b6 ]
On some flexcom nodes related to uart, the fifo sizes were wrong: fix them to 32 data.
--- arch/arm/boot/dts/sama7g5.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm/boot/dts/sama7g5.dtsi +2 -2
@@ -706,7 +706,7 @@ dma-names = "tx", "rx"; atmel,use-dma-rx; atmel,use-dma-tx; - atmel,fifo-size = <16>; + atmel,fifo-size = <32>; status = "disabled"; }; };
@@ -732,7 +732,7 @@ dma-names = "tx", "rx"; atmel,use-dma-rx; atmel,use-dma-tx; - atmel,fifo-size = <16>; + atmel,fifo-size = <32>; status = "disabled"; }; };
Greg Kroah-Hartman
maintainerPATCH 565/634 iommu/mediatek: Improve safety for mediatek,smi property in larb nodes
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yong Wu <[email protected]>
[ Upstream commit 6cde583d5352818a51985b32a960cdde85ab3821 ]
No functional change. Just improve safety from dts.
All the larbs that connect to one IOMMU must connect with the same smi-common. This patch checks all the mediatek,smi property for each larb, If their mediatek,smi are different, it will return fails. Also avoid there is no available smi-larb nodes.
Stable-dep-of: de83d4617f9f ("iommu/mediatek: fix use-after-free on probe deferral")
--- drivers/iommu/mtk_iommu.c | 53 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 16 deletions(-)
drivers/iommu/mtk_iommu.c +37 -16
@@ -1048,7 +1048,7 @@ static const struct component_master_opsstatic int mtk_iommu_mm_dts_parse (struct device *dev,struct component_match **match,struct mtk_iommu_data *data) { -struct device_node *larbnode, *smicomm_node, *smi_subcomm_node; +struct device_node *larbnode, *frst_avail_smicomm_node =NULL ;struct platform_device *plarbdev, *pcommdev;struct device_link *link;int i, larb_nr, ret;
@@ -1060,6 +1060,7 @@ static int mtk_iommu_mm_dts_parse(structreturn -EINVAL ;for (i =0 ; i < larb_nr; i++) { +struct device_node *smicomm_node, *smi_subcomm_node;u32 id; larbnode =of_parse_phandle (dev->of_node,"mediatek,larbs" , i);
@@ -1100,27 +1101,47 @@ static int mtk_iommu_mm_dts_parse(struct goto err_larbdev_put; } +/* Get smi-(sub)-common dev from the last larb. */ + smi_subcomm_node =of_parse_phandle (larbnode,"mediatek,smi" ,0 ); +if (!smi_subcomm_node) { + ret = -EINVAL ; + goto err_larbdev_put; + } + +/* +* It may have two level smi-common. the node is smi-sub-common if it +* has a new mediatek,smi property. otherwise it is smi-commmon. +*/ + smicomm_node =of_parse_phandle (smi_subcomm_node,"mediatek,smi" ,0 ); +if (smicomm_node) +of_node_put (smi_subcomm_node); +else + smicomm_node = smi_subcomm_node; + +/* +* All the larbs that connect to one IOMMU must connect with the same +* smi-common. +*/ +if (!frst_avail_smicomm_node) { + frst_avail_smicomm_node = smicomm_node; + }else if (frst_avail_smicomm_node != smicomm_node) { +dev_err (dev,"mediatek,smi property is not right @larb%d." , id); +of_node_put (smicomm_node); + ret = -EINVAL ; + goto err_larbdev_put; + }else { +of_node_put (smicomm_node); + } +component_match_add (dev, match, component_compare_dev, &plarbdev->dev);platform_device_put (plarbdev); } -/* Get smi-(sub)-common dev from the last larb. */ - smi_subcomm_node =of_parse_phandle (larbnode,"mediatek,smi" ,0 ); -if (!smi_subcomm_node) +if (!frst_avail_smicomm_node)return -EINVAL ; -/* -* It may have two level smi-common. the node is smi-sub-common if it -* has a new mediatek,smi property. otherwise it is smi-commmon. -*/ - smicomm_node =of_parse_phandle (smi_subcomm_node,"mediatek,smi" ,0 ); -if (smicomm_node) -of_node_put (smi_subcomm_node); -else - smicomm_node = smi_subcomm_node; - - pcommdev =of_find_device_by_node (smicomm_node); -of_node_put (smicomm_node); + pcommdev =of_find_device_by_node (frst_avail_smicomm_node); +of_node_put (frst_avail_smicomm_node);if (!pcommdev)return -ENODEV ; data->smicomm_dev = &pcommdev->dev;
Greg Kroah-Hartman
maintainerPATCH 566/634 iommu/mediatek: fix use-after-free on probe deferral
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
[ Upstream commit de83d4617f9fe059623e97acf7e1e10d209625b5 ]
The driver is dropping the references taken to the larb devices during probe after successful lookup as well as on errors. This can potentially lead to a use-after-free in case a larb device has not yet been bound to its driver so that the iommu driver probe defers.
Fix this by keeping the references as expected while the iommu driver is bound.
--- drivers/iommu/mtk_iommu.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-)
drivers/iommu/mtk_iommu.c +18 -7
@@ -1134,16 +1134,19 @@ static int mtk_iommu_mm_dts_parse(struct }component_match_add (dev, match, component_compare_dev, &plarbdev->dev); -platform_device_put (plarbdev); } -if (!frst_avail_smicomm_node) -return -EINVAL ; +if (!frst_avail_smicomm_node) { + ret = -EINVAL ; + goto err_larbdev_put; + } pcommdev =of_find_device_by_node (frst_avail_smicomm_node);of_node_put (frst_avail_smicomm_node); -if (!pcommdev) -return -ENODEV ; +if (!pcommdev) { + ret = -ENODEV ; + goto err_larbdev_put; + } data->smicomm_dev = &pcommdev->dev; link = device_link_add(data->smicomm_dev, dev,
@@ -1151,7 +1154,8 @@ static int mtk_iommu_mm_dts_parse(structplatform_device_put (pcommdev);if (!link) {dev_err (dev,"Unable to link %s.\n" ,dev_name (data->smicomm_dev)); -return -EINVAL ; + ret = -EINVAL ; + goto err_larbdev_put; }return 0 ;
@@ -1322,8 +1326,12 @@ out_sysfs_remove:iommu_device_sysfs_remove (&data->iommu); out_list_del:list_del (&data->list); -if (MTK_IOMMU_IS_TYPE (data->plat_data,MTK_IOMMU_TYPE_MM )) +if (MTK_IOMMU_IS_TYPE (data->plat_data,MTK_IOMMU_TYPE_MM )) {device_link_remove (data->smicomm_dev, dev); + +for (i =0 ; i <MTK_LARB_NR_MAX ; i++) +put_device (data->larb_imu[i].dev); + } out_runtime_disable:pm_runtime_disable (dev);return ret;
@@ -1343,6 +1351,9 @@ static int mtk_iommu_remove(struct platfif (MTK_IOMMU_IS_TYPE (data->plat_data,MTK_IOMMU_TYPE_MM )) {device_link_remove (data->smicomm_dev, &pdev->dev);component_master_del (&pdev->dev, &mtk_iommu_com_ops); + +for (i =0 ; i <MTK_LARB_NR_MAX ; i++) +put_device (data->larb_imu[i].dev); }pm_runtime_disable (&pdev->dev);for (i =0 ; i < data->plat_data->banks_num; i++) {
Greg Kroah-Hartman
maintainerPATCH 567/634 iommu/mtk_iommu_v1: Convert to platform remove callback returning void
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uwe Kleine-König <[email protected]>
[ Upstream commit 85e1049e50da9409678fc247ebad4c019d68041f ]
The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void.
Trivially convert this driver from always returning zero in the remove callback to the void returning variant.
Stable-dep-of: 46207625c9f3 ("iommu/mediatek-v1: fix device leaks on probe()")
--- drivers/iommu/mtk_iommu_v1.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/iommu/mtk_iommu_v1.c +2 -3
@@ -708,7 +708,7 @@ out_clk_unprepare:return ret; } -static int mtk_iommu_v1_remove (struct platform_device *pdev) +static void mtk_iommu_v1_remove (struct platform_device *pdev) {struct mtk_iommu_v1_data *data =platform_get_drvdata (pdev);
@@ -718,7 +718,6 @@ static int mtk_iommu_v1_remove(struct plclk_disable_unprepare (data->bclk);devm_free_irq (&pdev->dev, data->irq, data);component_master_del (&pdev->dev, &mtk_iommu_v1_com_ops); -return 0 ; }static int __maybe_unused mtk_iommu_v1_suspend (struct device *dev)
@@ -757,7 +756,7 @@ static const struct dev_pm_ops mtk_iommustatic struct platform_driver mtk_iommu_v1_driver = { .probe = mtk_iommu_v1_probe, - .remove = mtk_iommu_v1_remove, + .remove_new = mtk_iommu_v1_remove, .driver = { .name ="mtk-iommu-v1" , .of_match_table = mtk_iommu_v1_of_ids,
Greg Kroah-Hartman
maintainerPATCH 568/634 iommu/mediatek-v1: fix device leaks on probe()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
[ Upstream commit 46207625c9f33da0e43bb4ae1e91f0791b6ed633 ]
Make sure to drop the references taken to the larb devices during probe on probe failure (e.g. probe deferral) and on driver unbind.
--- drivers/iommu/mtk_iommu_v1.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-)
drivers/iommu/mtk_iommu_v1.c +18 -5
@@ -656,8 +656,10 @@ static int mtk_iommu_v1_probe(struct plastruct platform_device *plarbdev; larbnode =of_parse_phandle (dev->of_node,"mediatek,larbs" , i); -if (!larbnode) -return -EINVAL ; +if (!larbnode) { + ret = -EINVAL ; + goto out_put_larbs; + }if (!of_device_is_available (larbnode)) {of_node_put (larbnode);
@@ -667,11 +669,14 @@ static int mtk_iommu_v1_probe(struct pla plarbdev =of_find_device_by_node (larbnode);if (!plarbdev) {of_node_put (larbnode); -return -ENODEV ; + ret = -ENODEV ; + goto out_put_larbs; }if (!plarbdev->dev.driver) {of_node_put (larbnode); -return -EPROBE_DEFER ; +put_device (&plarbdev->dev); + ret = -EPROBE_DEFER ; + goto out_put_larbs; } data->larb_imu[i].dev = &plarbdev->dev;
@@ -683,7 +688,7 @@ static int mtk_iommu_v1_probe(struct pla ret =mtk_iommu_v1_hw_init (data);if (ret) -return ret; + goto out_put_larbs; ret =iommu_device_sysfs_add (&data->iommu, &pdev->dev,NULL ,dev_name (&pdev->dev));
@@ -705,12 +710,17 @@ out_sysfs_remove:iommu_device_sysfs_remove (&data->iommu); out_clk_unprepare:clk_disable_unprepare (data->bclk); +out_put_larbs: +for (i =0 ; i <MTK_LARB_NR_MAX ; i++) +put_device (data->larb_imu[i].dev); +return ret; }static void mtk_iommu_v1_remove (struct platform_device *pdev) {struct mtk_iommu_v1_data *data =platform_get_drvdata (pdev); +int i;iommu_device_sysfs_remove (&data->iommu);iommu_device_unregister (&data->iommu);
@@ -718,6 +728,9 @@ static void mtk_iommu_v1_remove(struct pclk_disable_unprepare (data->bclk);devm_free_irq (&pdev->dev, data->irq, data);component_master_del (&pdev->dev, &mtk_iommu_v1_com_ops); + +for (i =0 ; i <MTK_LARB_NR_MAX ; i++) +put_device (data->larb_imu[i].dev); }static int __maybe_unused mtk_iommu_v1_suspend (struct device *dev)
Greg Kroah-Hartman
maintainerPATCH 569/634 ASoC: stm32: sai: Use the devm_clk_get_optional() helper
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christophe JAILLET <[email protected]>
[ Upstream commit 374628fb668e50b42fe81f2a63af616182415bcd ]
Use devm_clk_get_optional() instead of hand writing it. This saves some LoC and improves the semantic.
Stable-dep-of: 312ec2f0d9d1 ("ASoC: stm32: sai: fix clk prepare imbalance on probe failure")
--- sound/soc/stm/stm32_sai_sub.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
sound/soc/stm/stm32_sai_sub.c +3 -6
@@ -1485,12 +1485,9 @@ static int stm32_sai_sub_parse_of(structif (ret <0 )return ret; }else { - sai->sai_mclk =devm_clk_get (&pdev->dev,"MCLK" ); -if (IS_ERR (sai->sai_mclk)) { -if (PTR_ERR (sai->sai_mclk) != -ENOENT ) -return PTR_ERR (sai->sai_mclk); - sai->sai_mclk =NULL ; - } + sai->sai_mclk =devm_clk_get_optional (&pdev->dev,"MCLK" ); +if (IS_ERR (sai->sai_mclk)) +return PTR_ERR (sai->sai_mclk); }return 0 ;
Greg Kroah-Hartman
maintainerPATCH 570/634 ASoC: stm32: sai: fix clk prepare imbalance on probe failure
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
[ Upstream commit 312ec2f0d9d1a5656f76d770bbf1d967e9289aa7 ]
Make sure to unprepare the parent clock also on probe failures (e.g. probe deferral).
--- sound/soc/stm/stm32_sai_sub.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-)
sound/soc/stm/stm32_sai_sub.c +21 -7
@@ -1483,14 +1483,21 @@ static int stm32_sai_sub_parse_of(structif (of_find_property (np,"#clock-cells" ,NULL )) { ret =stm32_sai_add_mclk_provider (sai);if (ret <0 ) -return ret; + goto err_unprepare_pclk; }else { sai->sai_mclk =devm_clk_get_optional (&pdev->dev,"MCLK" ); -if (IS_ERR (sai->sai_mclk)) -return PTR_ERR (sai->sai_mclk); +if (IS_ERR (sai->sai_mclk)) { + ret =PTR_ERR (sai->sai_mclk); + goto err_unprepare_pclk; + } }return 0 ; + +err_unprepare_pclk: +clk_unprepare (sai->pdata->pclk); + +return ret; }static int stm32_sai_sub_probe (struct platform_device *pdev)
@@ -1534,26 +1541,33 @@ static int stm32_sai_sub_probe(struct pl IRQF_SHARED, dev_name(&pdev->dev), sai);if (ret) {dev_err (&pdev->dev,"IRQ request returned %d\n" , ret); -return ret; + goto err_unprepare_pclk; }if (STM_SAI_PROTOCOL_IS_SPDIF (sai)) conf = &stm32_sai_pcm_config_spdif; ret =snd_dmaengine_pcm_register (&pdev->dev, conf,0 ); -if (ret) -return dev_err_probe (&pdev->dev, ret,"Could not register pcm dma\n" ); +if (ret) { + ret =dev_err_probe (&pdev->dev, ret,"Could not register pcm dma\n" ); + goto err_unprepare_pclk; + } ret =snd_soc_register_component (&pdev->dev, &stm32_component, &sai->cpu_dai_drv,1 );if (ret) {snd_dmaengine_pcm_unregister (&pdev->dev); -return ret; + goto err_unprepare_pclk; }pm_runtime_enable (&pdev->dev);return 0 ; + +err_unprepare_pclk: +clk_unprepare (sai->pdata->pclk); + +return ret; }static int stm32_sai_sub_remove (struct platform_device *pdev)
Greg Kroah-Hartman
maintainerPATCH 571/634 fuse: fix readahead reclaim deadlock
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joanne Koong <[email protected]>
[ Upstream commit bd5603eaae0aabf527bfb3ce1bb07e979ce5bd50 ]
Commit e26ee4efbc79 ("fuse: allocate ff->release_args only if release is needed") skips allocating ff->release_args if the server does not implement open. However in doing so, fuse_prepare_release() now skips grabbing the reference on the inode, which makes it possible for an inode to be evicted from the dcache while there are inflight readahead requests. This causes a deadlock if the server triggers reclaim while servicing the readahead request and reclaim attempts to evict the inode of the file being read ahead. Since the folio is locked during readahead, when reclaim evicts the fuse inode and fuse_evict_inode() attempts to remove all folios associated with the inode from the page cache (truncate_inode_pages_range()), reclaim will block forever waiting for the lock since readahead cannot relinquish the lock because it is itself blocked in reclaim:
Quoted 1 line
Quoted 1 line
Quoted 1 line
stack_trace(1504735)
folio_wait_bit_common (mm/filemap.c:1308:4) folio_lock (./include/linux/pagemap.h:1052:3) truncate_inode_pages_range (mm/truncate.c:336:10) fuse_evict_inode (fs/fuse/inode.c:161:2) evict (fs/inode.c:704:3) dentry_unlink_inode (fs/dcache.c:412:3) __dentry_kill (fs/dcache.c:615:3) shrink_kill (fs/dcache.c:1060:12) shrink_dentry_list (fs/dcache.c:1087:3) prune_dcache_sb (fs/dcache.c:1168:2) super_cache_scan (fs/super.c:221:10) do_shrink_slab (mm/shrinker.c:435:9) shrink_slab (mm/shrinker.c:626:10) shrink_node (mm/vmscan.c:5951:2) shrink_zones (mm/vmscan.c:6195:3) do_try_to_free_pages (mm/vmscan.c:6257:3) do_swap_page (mm/memory.c:4136:11) handle_pte_fault (mm/memory.c:5562:10) handle_mm_fault (mm/memory.c:5870:9) do_user_addr_fault (arch/x86/mm/fault.c:1338:10) handle_page_fault (arch/x86/mm/fault.c:1481:3) exc_page_fault (arch/x86/mm/fault.c:1539:2) asm_exc_page_fault+0x22/0x27
Fix this deadlock by allocating ff->release_args and grabbing the reference on the inode when preparing the file for release even if the server does not implement open. The inode reference will be dropped when the last reference on the fuse file is dropped (see fuse_file_put() -> fuse_release_end()).
--- fs/fuse/file.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-)
fs/fuse/file.c +19 -7
@@ -112,7 +112,9 @@ static void fuse_file_put(struct fuse_fistruct fuse_args *args = (ra ? &ra->args :NULL );if (!args) { -/* Do nothing when server does not implement 'open' */ +/* Do nothing when server does not implement 'opendir' */ + }else if (args->opcode ==FUSE_RELEASE && ff->fm->fc->no_open) { +fuse_release_end (ff->fm, args,0 ); }else if (sync) {fuse_simple_request (ff->fm, args);fuse_release_end (ff->fm, args,0 );
@@ -133,8 +135,17 @@ struct fuse_file *fuse_file_open(structstruct fuse_file *ff;int opcode = isdir ?FUSE_OPENDIR :FUSE_OPEN ;bool open = isdir ? !fc->no_opendir : !fc->no_open; +bool release = !isdir || open; - ff =fuse_file_alloc (fm, open); +/* +* ff->args->release_args still needs to be allocated (so we can hold an +* inode reference while there are pending inflight file operations when +* ->release() is called, see fuse_prepare_release()) even if +* fc->no_open is set else it becomes possible for reclaim to deadlock +* if while servicing the readahead request the server triggers reclaim +* and reclaim evicts the inode of the file being read ahead. +*/ + ff =fuse_file_alloc (fm, release);if (!ff)return ERR_PTR (-ENOMEM );
@@ -153,13 +164,14 @@ struct fuse_file *fuse_file_open(structfuse_file_free (ff);return ERR_PTR (err); }else { -/* No release needed */ -kfree (ff->release_args); - ff->release_args =NULL ; -if (isdir) +if (isdir) { +/* No release needed */ +kfree (ff->release_args); + ff->release_args =NULL ; fc->no_opendir =1 ; -else + }else { fc->no_open =1 ; + } } }
Greg Kroah-Hartman
maintainerPATCH 572/634 ASoC: stm: stm32_sai_sub: Convert to platform remove callback returning void
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uwe Kleine-König <[email protected]>
[ Upstream commit a3bd37e2e2bce4fb1757a940fa985d556662ba80 ]
The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void.
Trivially convert this driver from always returning zero in the remove callback to the void returning variant.
Stable-dep-of: 23261f0de094 ("ASoC: stm32: sai: fix OF node leak on probe")
--- sound/soc/stm/stm32_sai_sub.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
sound/soc/stm/stm32_sai_sub.c +2 -4
@@ -1570,7 +1570,7 @@ err_unprepare_pclk:return ret; } -static int stm32_sai_sub_remove (struct platform_device *pdev) +static void stm32_sai_sub_remove (struct platform_device *pdev) {struct stm32_sai_sub_data *sai =dev_get_drvdata (&pdev->dev);
@@ -1578,8 +1578,6 @@ static int stm32_sai_sub_remove(struct psnd_dmaengine_pcm_unregister (&pdev->dev);snd_soc_unregister_component (&pdev->dev);pm_runtime_disable (&pdev->dev); - -return 0 ; }#ifdef CONFIG_PM_SLEEP
@@ -1629,7 +1627,7 @@ static struct platform_driver stm32_sai_ .pm = &stm32_sai_sub_pm_ops, }, .probe = stm32_sai_sub_probe, - .remove = stm32_sai_sub_remove, + .remove_new = stm32_sai_sub_remove, };module_platform_driver (stm32_sai_sub_driver);
Greg Kroah-Hartman
maintainerPATCH 573/634 ASoC: stm32: sai: fix OF node leak on probe
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
[ Upstream commit 23261f0de09427367e99f39f588e31e2856a690e ]
The reference taken to the sync provider OF node when probing the platform device is currently only dropped if the set_sync() callback fails during DAI probe.
Make sure to drop the reference on platform probe failures (e.g. probe deferral) and on driver unbind.
This also avoids a potential use-after-free in case the DAI is ever reprobed without first rebinding the platform driver.
--- sound/soc/stm/stm32_sai.c | 12 +++--------- sound/soc/stm/stm32_sai_sub.c | 23 ++++++++++++++++------- 2 files changed, 19 insertions(+), 16 deletions(-)
sound/soc/stm/stm32_sai.c +3 -9
@@ -122,7 +122,6 @@ static int stm32_sai_set_sync(struct stmif (!pdev) {dev_err (&sai_client->pdev->dev,"Device not found for node %pOFn\n" , np_provider); -of_node_put (np_provider);return -ENODEV ; }
@@ -131,21 +130,16 @@ static int stm32_sai_set_sync(struct stmif (!sai_provider) {dev_err (&sai_client->pdev->dev,"SAI sync provider data not found\n" ); - ret = -EINVAL ; - goto error; +return -EINVAL ; }/* Configure sync client */ ret =stm32_sai_sync_conf_client (sai_client, synci);if (ret <0 ) - goto error; +return ret;/* Configure sync provider */ - ret =stm32_sai_sync_conf_provider (sai_provider, synco); - -error: -of_node_put (np_provider); -return ret; +return stm32_sai_sync_conf_provider (sai_provider, synco); }static int stm32_sai_probe (struct platform_device *pdev)
sound/soc/stm/stm32_sai_sub.c +16 -7
@@ -1435,7 +1435,8 @@ static int stm32_sai_sub_parse_of(structdev_err (&pdev->dev,"External synchro not supported\n" );of_node_put (args.np); -return -EINVAL ; + ret = -EINVAL ; + goto err_put_sync_provider; } sai->sync =SAI_SYNC_EXTERNAL ;
@@ -1444,7 +1445,8 @@ static int stm32_sai_sub_parse_of(struct (sai->synci > (SAI_GCR_SYNCIN_MAX + 1))) {dev_err (&pdev->dev,"Wrong SAI index\n" );of_node_put (args.np); -return -EINVAL ; + ret = -EINVAL ; + goto err_put_sync_provider; } if (of_property_match_string(args.np, "compatible",
@@ -1458,7 +1460,8 @@ static int stm32_sai_sub_parse_of(structif (!sai->synco) {dev_err (&pdev->dev,"Unknown SAI sub-block\n" );of_node_put (args.np); -return -EINVAL ; + ret = -EINVAL ; + goto err_put_sync_provider; } }
@@ -1468,13 +1471,15 @@ static int stm32_sai_sub_parse_of(structof_node_put (args.np); sai->sai_ck =devm_clk_get (&pdev->dev,"sai_ck" ); -if (IS_ERR (sai->sai_ck)) -return dev_err_probe (&pdev->dev,PTR_ERR (sai->sai_ck), -"Missing kernel clock sai_ck\n" ); +if (IS_ERR (sai->sai_ck)) { + ret =dev_err_probe (&pdev->dev,PTR_ERR (sai->sai_ck), +"Missing kernel clock sai_ck\n" ); + goto err_put_sync_provider; + } ret =clk_prepare (sai->pdata->pclk);if (ret <0 ) -return ret; + goto err_put_sync_provider;if (STM_SAI_IS_F4 (sai->pdata))return 0 ;
@@ -1496,6 +1501,8 @@ static int stm32_sai_sub_parse_of(struct err_unprepare_pclk:clk_unprepare (sai->pdata->pclk); +err_put_sync_provider: +of_node_put (sai->np_sync_provider);return ret; }
@@ -1566,6 +1573,7 @@ static int stm32_sai_sub_probe(struct pl err_unprepare_pclk:clk_unprepare (sai->pdata->pclk); +of_node_put (sai->np_sync_provider);return ret; }
@@ -1578,6 +1586,7 @@ static void stm32_sai_sub_remove(structsnd_dmaengine_pcm_unregister (&pdev->dev);snd_soc_unregister_component (&pdev->dev);pm_runtime_disable (&pdev->dev); +of_node_put (sai->np_sync_provider); }#ifdef CONFIG_PM_SLEEP
Greg Kroah-Hartman
maintainerPATCH 574/634 media: verisilicon: Fix CPU stalls on G2 bus error
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolas Dufresne <[email protected]>
[ Upstream commit 19c286b755072a22a063052f530a6b1fac8a1f63 ]
In some seek stress tests, we are getting IRQ from the G2 decoder where the dec_bus_int and the dec_e bits are high, meaning the decoder is still running despite the error.
Fix this by reworking the IRQ handler to only finish the job once we have reached completion and move the software reset to when our software watchdog triggers.
This way, we let the hardware continue on errors when it did not self reset and in worse case scenario the hardware timeout will automatically stop it. The actual error will be fixed in a follow up patch.
--- drivers/media/platform/verisilicon/hantro_g2.c | 84 ++++++++++++---- drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c | 2 drivers/media/platform/verisilicon/hantro_g2_regs.h | 13 ++ drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c | 2 drivers/media/platform/verisilicon/hantro_hw.h | 1 drivers/media/platform/verisilicon/imx8m_vpu_hw.c | 2 6 files changed, 83 insertions(+), 21 deletions(-)
drivers/media/platform/verisilicon/hantro_g2.c +67 -17
@@ -5,40 +5,90 @@* Copyright (C) 2021 Collabora Ltd, Andrzej Pietrasiewicz <[email protected]> */ +#include <linux/delay.h> #include "hantro_hw.h" #include "hantro_g2_regs.h" -void hantro_g2_check_idle (struct hantro_dev *vpu) +static bool hantro_g2_active (struct hantro_ctx *ctx) { -int i; +struct hantro_dev *vpu = ctx->dev; +u32 status; + + status =vdpu_read (vpu,G2_REG_INTERRUPT ); + +return (status &G2_REG_INTERRUPT_DEC_E ); +} -for (i =0 ; i <3 ; i++) { -u32 status; +/** +* hantro_g2_reset: +* @ctx: the hantro context +* +* Emulates a reset using Hantro abort function. Failing this procedure would +* results in programming a running IP which leads to CPU hang. +* +* Using a hard reset procedure instead is prefferred. +*/ +void hantro_g2_reset (struct hantro_ctx *ctx) +{ +struct hantro_dev *vpu = ctx->dev; +u32 status; -/* Make sure the VPU is idle */ - status =vdpu_read (vpu,G2_REG_INTERRUPT ); -if (status &G2_REG_INTERRUPT_DEC_E ) { -dev_warn (vpu->dev,"device still running, aborting" ); - status |=G2_REG_INTERRUPT_DEC_ABORT_E |G2_REG_INTERRUPT_DEC_IRQ_DIS ; -vdpu_write (vpu, status,G2_REG_INTERRUPT ); - } + status =vdpu_read (vpu,G2_REG_INTERRUPT ); +if (status &G2_REG_INTERRUPT_DEC_E ) { +dev_warn_ratelimited (vpu->dev,"device still running, aborting" ); + status |=G2_REG_INTERRUPT_DEC_ABORT_E |G2_REG_INTERRUPT_DEC_IRQ_DIS ; +vdpu_write (vpu, status,G2_REG_INTERRUPT ); + +do { +mdelay (1 ); + }while (hantro_g2_active (ctx)); } }irqreturn_t hantro_g2_irq (int irq,void *dev_id) {struct hantro_dev *vpu = dev_id; -enum vb2_buffer_state state;u32 status; status =vdpu_read (vpu,G2_REG_INTERRUPT ); - state = (status &G2_REG_INTERRUPT_DEC_RDY_INT ) ? -VB2_BUF_STATE_DONE :VB2_BUF_STATE_ERROR ; -vdpu_write (vpu,0 ,G2_REG_INTERRUPT ); -vdpu_write (vpu,G2_REG_CONFIG_DEC_CLK_GATE_E ,G2_REG_CONFIG ); +if (!(status &G2_REG_INTERRUPT_DEC_IRQ )) +return IRQ_NONE ; + +hantro_reg_write (vpu, &g2_dec_irq,0 ); +hantro_reg_write (vpu, &g2_dec_int_stat,0 ); +hantro_reg_write (vpu, &g2_clk_gate_e,1 ); + +if (status &G2_REG_INTERRUPT_DEC_RDY_INT ) { +hantro_irq_done (vpu,VB2_BUF_STATE_DONE ); +return IRQ_HANDLED ; + } + +if (status &G2_REG_INTERRUPT_DEC_ABORT_INT ) { +/* disabled on abort, though lets be safe and handle it */ +dev_warn_ratelimited (vpu->dev,"decode operation aborted." ); +return IRQ_HANDLED ; + } + +if (status &G2_REG_INTERRUPT_DEC_LAST_SLICE_INT ) +dev_warn_ratelimited (vpu->dev,"not all macroblocks were decoded." ); + +if (status &G2_REG_INTERRUPT_DEC_BUS_INT ) +dev_warn_ratelimited (vpu->dev,"bus error detected." ); + +if (status &G2_REG_INTERRUPT_DEC_ERROR_INT ) +dev_warn_ratelimited (vpu->dev,"decode error detected." ); -hantro_irq_done (vpu, state); +if (status &G2_REG_INTERRUPT_DEC_TIMEOUT ) +dev_warn_ratelimited (vpu->dev,"frame decode timed out." ); + +/** +* If the decoding haven't stopped, let it continue. The hardware timeout +* will trigger if it is trully stuck. +*/ +if (status &G2_REG_INTERRUPT_DEC_E ) +return IRQ_HANDLED ; +hantro_irq_done (vpu,VB2_BUF_STATE_ERROR );return IRQ_HANDLED ; }
drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c +0 -2
@@ -592,8 +592,6 @@ int hantro_g2_hevc_dec_run(struct hantrostruct hantro_dev *vpu = ctx->dev;int ret; -hantro_g2_check_idle (vpu); -/* Prepare HEVC decoder context. */ ret =hantro_hevc_dec_prepare_run (ctx);if (ret)
drivers/media/platform/verisilicon/hantro_g2_regs.h +13 -0
@@ -22,7 +22,14 @@#define G2_REG_VERSION G2_SWREG(0)#define G2_REG_INTERRUPT G2_SWREG(1) +#define G2_REG_INTERRUPT_DEC_LAST_SLICE_INT BIT(19) +#define G2_REG_INTERRUPT_DEC_TIMEOUT BIT(18) +#define G2_REG_INTERRUPT_DEC_ERROR_INT BIT(16) +#define G2_REG_INTERRUPT_DEC_BUF_INT BIT(14) +#define G2_REG_INTERRUPT_DEC_BUS_INT BIT(13)#define G2_REG_INTERRUPT_DEC_RDY_INT BIT(12) +#define G2_REG_INTERRUPT_DEC_ABORT_INT BIT(11) +#define G2_REG_INTERRUPT_DEC_IRQ BIT(8)#define G2_REG_INTERRUPT_DEC_ABORT_E BIT(5)#define G2_REG_INTERRUPT_DEC_IRQ_DIS BIT(4)#define G2_REG_INTERRUPT_DEC_E BIT(0)
@@ -35,6 +42,9 @@#define BUS_WIDTH_128 2#define BUS_WIDTH_256 3 +#define g2_dec_int_stat G2_DEC_REG(1, 11, 0xf) +#define g2_dec_irq G2_DEC_REG(1, 8, 0x1) +#define g2_strm_swap G2_DEC_REG(2, 28, 0xf)#define g2_strm_swap_old G2_DEC_REG(2, 27, 0x1f)#define g2_pic_swap G2_DEC_REG(2, 22, 0x1f)
@@ -225,6 +235,9 @@#define vp9_filt_level_seg5 G2_DEC_REG(19, 8, 0x3f)#define vp9_quant_seg5 G2_DEC_REG(19, 0, 0xff) +#define g2_timemout_override_e G2_DEC_REG(45, 31, 0x1) +#define g2_timemout_cycles G2_DEC_REG(45, 0, 0x7fffffff) +#define hevc_cur_poc_00 G2_DEC_REG(46, 24, 0xff)#define hevc_cur_poc_01 G2_DEC_REG(46, 16, 0xff)#define hevc_cur_poc_02 G2_DEC_REG(46, 8, 0xff)
drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c +0 -2
@@ -909,8 +909,6 @@ int hantro_g2_vp9_dec_run(struct hantro_struct vb2_v4l2_buffer *dst;int ret; -hantro_g2_check_idle (ctx->dev); - ret =start_prepare_run (ctx, &decode_params);if (ret) {hantro_end_prepare_run (ctx);
drivers/media/platform/verisilicon/hantro_hw.h +1 -0
@@ -436,6 +436,7 @@ void hantro_g2_vp9_dec_done(struct hantrint hantro_vp9_dec_init (struct hantro_ctx *ctx);void hantro_vp9_dec_exit (struct hantro_ctx *ctx);void hantro_g2_check_idle (struct hantro_dev *vpu); +void hantro_g2_reset (struct hantro_ctx *ctx);irqreturn_t hantro_g2_irq (int irq,void *dev_id);#endif /* HANTRO_HW_H_ */
drivers/media/platform/verisilicon/imx8m_vpu_hw.c +2 -0
@@ -310,11 +310,13 @@ static const struct hantro_codec_ops imxstatic const struct hantro_codec_ops imx8mq_vpu_g2_codec_ops[] = { [HANTRO_MODE_HEVC_DEC ] = { .run = hantro_g2_hevc_dec_run, + .reset = hantro_g2_reset, .init = hantro_hevc_dec_init, .exit = hantro_hevc_dec_exit, }, [HANTRO_MODE_VP9_DEC ] = { .run = hantro_g2_vp9_dec_run, + .reset = hantro_g2_reset, .done = hantro_g2_vp9_dec_done, .init = hantro_vp9_dec_init, .exit = hantro_vp9_dec_exit,
Greg Kroah-Hartman
maintainerPATCH 575/634 arm64: dts: ti: k3-j721e-sk: Fix pinmux for pin Y1 used by power regulator
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Siddharth Vadapalli <[email protected]>
[ Upstream commit 51f89c488f2ecc020f82bfedd77482584ce8027a ]
The SoC pin Y1 is incorrectly defined in the WKUP Pinmux device-tree node (pinctrl@4301c000) leading to the following silent failure:
pinctrl-single 4301c000.pinctrl: mux offset out of range: 0x1dc (0x178)
According to the datasheet for the J721E SoC [0], the pin Y1 belongs to the MAIN Pinmux device-tree node (pinctrl@11c000). This is confirmed by the address of the pinmux register for it on page 142 of the datasheet which is 0x00011C1DC.
Hence fix it.
[0]: https://www.ti.com/lit/ds/symlink/tda4vm.pdf
--- arch/arm64/boot/dts/ti/k3-j721e-sk.dts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
arch/arm64/boot/dts/ti/k3-j721e-sk.dts +6 -6
@@ -425,6 +425,12 @@ J721E_IOPAD(0x124, PIN_INPUT, 7) /* (Y24) PRG0_PRU1_GPO9.GPIO0_72 */ >; }; + + vdd_sd_dv_pins_default: vdd-sd-dv-default-pins { + pinctrl-single,pins = < + J721E_IOPAD(0x1dc, PIN_OUTPUT, 7) /* (Y1) SPI1_CLK.GPIO0_118 */ + >; + }; }; &wkup_pmx0 {
@@ -480,12 +486,6 @@ >; }; - vdd_sd_dv_pins_default: vdd-sd-dv-default-pins { - pinctrl-single,pins = < - J721E_IOPAD(0x1dc, PIN_OUTPUT, 7) /* (Y1) SPI1_CLK.GPIO0_118 */ - >; - }; - wkup_i2c0_pins_default: wkup-i2c0-pins-default { pinctrl-single,pins = < J721E_WKUP_IOPAD(0xf8, PIN_INPUT_PULLUP, 0) /* (J25) WKUP_I2C0_SCL */
Greg Kroah-Hartman
maintainerPATCH 576/634 PCI: brcmstb: Fix disabling L0s capability
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jim Quinlan <[email protected]>
[ Upstream commit 9583f9d22991d2cfb5cc59a2552040c4ae98d998 ]
caab002d5069 ("PCI: brcmstb: Disable L0s component of ASPM if requested") set PCI_EXP_LNKCAP_ASPM_L1 and (optionally) PCI_EXP_LNKCAP_ASPM_L0S in PCI_EXP_LNKCAP (aka PCIE_RC_CFG_PRIV1_LINK_CAPABILITY in brcmstb).
But instead of using PCI_EXP_LNKCAP_ASPM_L1 and PCI_EXP_LNKCAP_ASPM_L0S directly, it used PCIE_LINK_STATE_L1 and PCIE_LINK_STATE_L0S, which are Linux-created values that only coincidentally matched the PCIe spec. b478e162f227 ("PCI/ASPM: Consolidate link state defines") later changed them so they no longer matched the PCIe spec, so the bits ended up in the wrong place in PCI_EXP_LNKCAP.
Use PCI_EXP_LNKCAP_ASPM_L0S to clear L0s support when there's an 'aspm-no-l0s' property. Rely on brcmstb hardware to advertise L0s and/or L1 support otherwise.
--- drivers/pci/controller/pcie-brcmstb.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-)
drivers/pci/controller/pcie-brcmstb.c +3 -7
@@ -45,7 +45,6 @@#define PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK 0xffffff#define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY 0x04dc -#define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK 0xc00#define PCIE_RC_DL_MDIO_ADDR 0x1100#define PCIE_RC_DL_MDIO_WR_DATA 0x1104
@@ -869,7 +868,7 @@ static int brcm_pcie_setup(struct brcm_pvoid __iomem *base = pcie->base;struct pci_host_bridge *bridge;struct resource_entry *entry; -u32 tmp, burst, aspm_support; +u32 tmp, burst;int num_out_wins =0 ;int ret, memc;
@@ -963,12 +962,9 @@ static int brcm_pcie_setup(struct brcm_pwritel (tmp, base +PCIE_MISC_RC_BAR3_CONFIG_LO );/* Don't advertise L0s capability if 'aspm-no-l0s' */ - aspm_support =PCIE_LINK_STATE_L1 ; -if (!of_property_read_bool (pcie->np,"aspm-no-l0s" )) - aspm_support |=PCIE_LINK_STATE_L0S ; tmp =readl (base +PCIE_RC_CFG_PRIV1_LINK_CAPABILITY ); -u32p_replace_bits (&tmp, aspm_support, -PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK ); +if (of_property_read_bool (pcie->np,"aspm-no-l0s" )) + tmp &= ~PCI_EXP_LNKCAP_ASPM_L0S ;writel (tmp, base +PCIE_RC_CFG_PRIV1_LINK_CAPABILITY );/*
Greg Kroah-Hartman
maintainerPATCH 577/634 mm/balloon_compaction: we cannot have isolated pages in the balloon list
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Hildenbrand <[email protected]>
[ Upstream commit fb05f992b6bbb4702307d96f00703ee637b24dbf ]
Patch series "mm/migration: rework movable_ops page migration (part 1)", v2.
In the future, as we decouple "struct page" from "struct folio", pages that support "non-lru page migration" -- movable_ops page migration such as memory balloons and zsmalloc -- will no longer be folios. They will not have ->mapping, ->lru, and likely no refcount and no page lock. But they will have a type and flags 🙂
This is the first part (other parts not written yet) of decoupling movable_ops page migration from folio migration.
In this series, we get rid of the ->mapping usage, and start cleaning up the code + separating it from folio migration.
Migration core will have to be further reworked to not treat movable_ops pages like folios. This is the first step into that direction.
This patch (of 29):
The core will set PG_isolated only after mops->isolate_page() was called. In case of the balloon, that is where we will remove it from the balloon list. So we cannot have isolated pages in the balloon list.
Let's drop this unnecessary check.
Stable-dep-of: 0da2ba35c0d5 ("powerpc/pseries/cmm: adjust BALLOON_MIGRATE when migrating pages")
--- mm/balloon_compaction.c | 6 ------ 1 file changed, 6 deletions(-)
mm/balloon_compaction.c +0 -6
@@ -93,12 +93,6 @@ size_t balloon_page_list_dequeue(structif (!trylock_page (page))continue ; -if (IS_ENABLED (CONFIG_BALLOON_COMPACTION ) && -PageIsolated (page)) { -/* raced with isolation */ -unlock_page (page); -continue ; - }balloon_page_delete (page);__count_vm_event (BALLOON_DEFLATE );list_add (&page->lru, pages);
Greg Kroah-Hartman
maintainerPATCH 578/634 mm/balloon_compaction: convert balloon_page_delete() to balloon_page_finalize()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Hildenbrand <[email protected]>
[ Upstream commit 15504b1163007bbfbd9a63460d5c14737c16e96d ]
Let's move the removal of the page from the balloon list into the single caller, to remove the dependency on the PG_isolated flag and clarify locking requirements.
Note that for now, balloon_page_delete() was used on two paths:
(1) Removing a page from the balloon for deflation through balloon_page_list_dequeue()
(2) Removing an isolated page from the balloon for migration in the per-driver migration handlers. Isolated pages were already removed from the balloon list during isolation.
So instead of relying on the flag, we can just distinguish both cases directly and handle it accordingly in the caller.
We'll shuffle the operations a bit such that they logically make more sense (e.g., remove from the list before clearing flags).
In balloon migration functions we can now move the balloon_page_finalize() out of the balloon lock and perform the finalization just before dropping the balloon reference.
Document that the page lock is currently required when modifying the movability aspects of a page; hopefully we can soon decouple this from the page lock.
Stable-dep-of: 0da2ba35c0d5 ("powerpc/pseries/cmm: adjust BALLOON_MIGRATE when migrating pages")
--- arch/powerpc/platforms/pseries/cmm.c | 2 - drivers/misc/vmw_balloon.c | 3 -- drivers/virtio/virtio_balloon.c | 4 --- include/linux/balloon_compaction.h | 43 +++++++++++++---------------------- mm/balloon_compaction.c | 3 +- 5 files changed, 21 insertions(+), 34 deletions(-)
arch/powerpc/platforms/pseries/cmm.c +1 -1
@@ -532,7 +532,6 @@ static int cmm_migratepage(struct balloospin_lock_irqsave (&b_dev_info->pages_lock, flags);balloon_page_insert (b_dev_info, newpage); -balloon_page_delete (page); b_dev_info->isolated_pages--;spin_unlock_irqrestore (&b_dev_info->pages_lock, flags);
@@ -542,6 +541,7 @@ static int cmm_migratepage(struct balloo*/ plpar_page_set_active (page); +balloon_page_finalize (page);/* balloon page list reference */ put_page (page);
drivers/misc/vmw_balloon.c +1 -2
@@ -1789,8 +1789,7 @@ static int vmballoon_migratepage(struct* @pages_lock . We keep holding @comm_lock since we will need it in a * second. */ -balloon_page_delete (page); - +balloon_page_finalize (page);put_page (page);/* Inflate */
drivers/virtio/virtio_balloon.c +1 -3
@@ -789,15 +789,13 @@ static int virtballoon_migratepage(structell_host (vb, vb->inflate_vq);/* balloon's page migration 2nd step -- deflate "page" */ -spin_lock_irqsave (&vb_dev_info->pages_lock, flags); -balloon_page_delete (page); -spin_unlock_irqrestore (&vb_dev_info->pages_lock, flags); vb->num_pfns =VIRTIO_BALLOON_PAGES_PER_PAGE ;set_page_pfns (vb, vb->pfns, page);tell_host (vb, vb->deflate_vq);mutex_unlock (&vb->balloon_lock); +balloon_page_finalize (page);put_page (page);/* balloon reference */ return MIGRATEPAGE_SUCCESS ;
include/linux/balloon_compaction.h +16 -27
61 lines not on this page · raw message
mm/balloon_compaction.c +2 -1
@@ -93,7 +93,8 @@ size_t balloon_page_list_dequeue(structif (!trylock_page (page))continue ; -balloon_page_delete (page); +list_del (&page->lru); +balloon_page_finalize (page);__count_vm_event (BALLOON_DEFLATE );list_add (&page->lru, pages);unlock_page (page);
Greg Kroah-Hartman
maintainerPATCH 579/634 powerpc/pseries/cmm: adjust BALLOON_MIGRATE when migrating pages
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Hildenbrand <[email protected]>
[ Upstream commit 0da2ba35c0d532ca0fe7af698b17d74c4d084b9a ]
Let's properly adjust BALLOON_MIGRATE like the other drivers.
Note that the INFLATE/DEFLATE events are triggered from the core when enqueueing/dequeueing pages.
This was found by code inspection.
--- arch/powerpc/platforms/pseries/cmm.c | 1 + 1 file changed, 1 insertion(+)
arch/powerpc/platforms/pseries/cmm.c +1 -0
@@ -532,6 +532,7 @@ static int cmm_migratepage(struct balloospin_lock_irqsave (&b_dev_info->pages_lock, flags);balloon_page_insert (b_dev_info, newpage); +__count_vm_event (BALLOON_MIGRATE ); b_dev_info->isolated_pages--;spin_unlock_irqrestore (&b_dev_info->pages_lock, flags);
Greg Kroah-Hartman
maintainerPATCH 580/634 KVM: nVMX: Immediately refresh APICv controls as needed on nested VM-Exit
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dongli Zhang <[email protected]>
[ Upstream commit 29763138830916f46daaa50e83e7f4f907a3236b ]
If an APICv status updated was pended while L2 was active, immediately refresh vmcs01's controls instead of pending KVM_REQ_APICV_UPDATE as kvm_vcpu_update_apicv() only calls into vendor code if a change is necessary.
E.g. if APICv is inhibited, and then activated while L2 is running:
kvm_vcpu_update_apicv()
|
-> __kvm_vcpu_update_apicv()
|
-> apic->apicv_active = true
|
-> vmx_refresh_apicv_exec_ctrl()
|
-> vmx->nested.update_vmcs01_apicv_status = true
|
-> returnThen L2 exits to L1:
__nested_vmx_vmexit()
|
-> kvm_make_request(KVM_REQ_APICV_UPDATE)
vcpu_enter_guest(): KVM_REQ_APICV_UPDATE
-> kvm_vcpu_update_apicv()
|
-> __kvm_vcpu_update_apicv()
|
-> return // because if (apic->apicv_active == activate)--- arch/x86/kvm/vmx/nested.c | 2 +- arch/x86/kvm/vmx/vmx.c | 2 +- arch/x86/kvm/vmx/vmx.h | 1 + 3 files changed, 3 insertions(+), 2 deletions(-)
arch/x86/kvm/vmx/nested.c +1 -1
@@ -4847,7 +4847,7 @@ void nested_vmx_vmexit(struct kvm_vcpu *if (vmx->nested.update_vmcs01_apicv_status) { vmx->nested.update_vmcs01_apicv_status = false; -kvm_make_request (KVM_REQ_APICV_UPDATE , vcpu); +vmx_refresh_apicv_exec_ctrl (vcpu); }if (vmx->nested.update_vmcs01_hwapic_isr) {
arch/x86/kvm/vmx/vmx.c +1 -1
@@ -4387,7 +4387,7 @@ static u32 vmx_vmexit_ctrl(void) ~(VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL |VM_EXIT_LOAD_IA32_EFER ); } -static void vmx_refresh_apicv_exec_ctrl (struct kvm_vcpu *vcpu) +void vmx_refresh_apicv_exec_ctrl (struct kvm_vcpu *vcpu) {struct vcpu_vmx *vmx =to_vmx (vcpu);
arch/x86/kvm/vmx/vmx.h +1 -0
@@ -408,6 +408,7 @@ void __vmx_set_segment(struct kvm_vcpu *u64 construct_eptp (struct kvm_vcpu *vcpu,hpa_t root_hpa,int root_level);bool vmx_guest_inject_ac (struct kvm_vcpu *vcpu); +void vmx_refresh_apicv_exec_ctrl (struct kvm_vcpu *vcpu);void vmx_update_exception_bitmap (struct kvm_vcpu *vcpu);bool vmx_nmi_blocked (struct kvm_vcpu *vcpu);bool __vmx_interrupt_blocked (struct kvm_vcpu *vcpu);
Greg Kroah-Hartman
maintainerPATCH 581/634 media: amphion: Add a frame flush mode for decoder
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Qian <[email protected]>
[ Upstream commit 9ea16ba6eaf93f25f61855751f71e2e701709ddf ]
By default the amphion decoder will pre-parse 3 frames before starting to decode the first frame. Alternatively, a block of flush padding data can be appended to the frame, which will ensure that the decoder can start decoding immediately after parsing the flush padding data, thus potentially reducing decoding latency.
This mode was previously only enabled, when the display delay was set to
0. Allow the user to manually toggle the use of that mode via a module parameter called low_latency, which enables the mode without changing the display order.
Stable-dep-of: 634c2cd17bd0 ("media: amphion: Remove vpu_vb_is_codecconfig")
--- drivers/media/platform/amphion/vpu_malone.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
drivers/media/platform/amphion/vpu_malone.c +13 -1
@@ -27,6 +27,10 @@#include "vpu_imx8q.h" #include "vpu_malone.h" +static bool low_latency; +module_param (low_latency, bool,0644 ); +MODULE_PARM_DESC (low_latency,"Set low latency frame flush mode: 0 (disable) or 1 (enable)" ); +#define CMD_SIZE 25600#define MSG_SIZE 25600#define CODEC_SIZE 0x1000
@@ -1527,7 +1531,15 @@ static int vpu_malone_input_frame_data(svpu_malone_update_wptr (str_buf, wptr); -if (disp_imm && !vpu_vb_is_codecconfig (vbuf)) { +/* +* Enable the low latency flush mode if display delay is set to 0 +* or the low latency frame flush mode if it is set to 1. +* The low latency flush mode requires some padding data to be appended to each frame, +* but there must not be any padding data between the sequence header and the frame. +* This module is currently only supported for the H264 and HEVC formats, +* for other formats, vpu_malone_add_scode() will return 0. +*/ +if ((disp_imm || low_latency) && !vpu_vb_is_codecconfig (vbuf)) { ret = vpu_malone_add_scode(inst->core->iface, inst->id, &inst->stream_buffer,
Greg Kroah-Hartman
maintainerPATCH 582/634 media: amphion: Make some vpu_v4l2 functions static
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Laurent Pinchart <[email protected]>
[ Upstream commit 5d1e54bb4dc6741284a3ed587e994308ddee2f16 ]
Some functions defined in vpu_v4l2.c are never used outside of that compilation unit. Make them static.
Stable-dep-of: 634c2cd17bd0 ("media: amphion: Remove vpu_vb_is_codecconfig")
--- drivers/media/platform/amphion/vpu_v4l2.c | 12 +++++++++--- drivers/media/platform/amphion/vpu_v4l2.h | 8 -------- 2 files changed, 9 insertions(+), 11 deletions(-)
drivers/media/platform/amphion/vpu_v4l2.c +9 -3
@@ -24,6 +24,11 @@#include "vpu_msgs.h" #include "vpu_helpers.h" +static char *vpu_type_name (u32 type) +{ +return V4L2_TYPE_IS_OUTPUT (type) ?"output" :"capture" ; +} +void vpu_inst_lock (struct vpu_inst *inst) {mutex_lock (&inst->lock);
@@ -42,7 +47,7 @@ dma_addr_t vpu_get_vb_phy_addr(struct vb vb->planes[plane_no].data_offset; } -unsigned int vpu_get_vb_length (struct vb2_buffer *vb,u32 plane_no) +static unsigned int vpu_get_vb_length (struct vb2_buffer *vb,u32 plane_no) {if (plane_no >= vb->num_planes)return 0 ;
@@ -74,7 +79,7 @@ void vpu_v4l2_set_error(struct vpu_instvpu_inst_unlock (inst); } -int vpu_notify_eos (struct vpu_inst *inst) +static int vpu_notify_eos (struct vpu_inst *inst) {static const struct v4l2_event ev = { .id =0 ,
@@ -461,7 +466,8 @@ static void vpu_vb2_buf_finish(struct vbcall_void_vop (inst, on_queue_empty, q->type); } -void vpu_vb2_buffers_return (struct vpu_inst *inst,unsigned int type,enum vb2_buffer_state state) +static void vpu_vb2_buffers_return (struct vpu_inst *inst,unsigned int type, +enum vb2_buffer_state state) {struct vb2_v4l2_buffer *buf;
drivers/media/platform/amphion/vpu_v4l2.h +0 -8
@@ -24,15 +24,12 @@ void vpu_skip_frame(struct vpu_inst *insstruct vb2_v4l2_buffer *vpu_find_buf_by_sequence (struct vpu_inst *inst,u32 type,u32 sequence);struct vb2_v4l2_buffer *vpu_find_buf_by_idx (struct vpu_inst *inst,u32 type,u32 idx);void vpu_v4l2_set_error (struct vpu_inst *inst); -int vpu_notify_eos (struct vpu_inst *inst);int vpu_notify_source_change (struct vpu_inst *inst);int vpu_set_last_buffer_dequeued (struct vpu_inst *inst,bool eos); -void vpu_vb2_buffers_return (struct vpu_inst *inst,unsigned int type,enum vb2_buffer_state state);int vpu_get_num_buffers (struct vpu_inst *inst,u32 type);bool vpu_is_source_empty (struct vpu_inst *inst);dma_addr_t vpu_get_vb_phy_addr (struct vb2_buffer *vb,u32 plane_no); -unsigned int vpu_get_vb_length (struct vb2_buffer *vb,u32 plane_no);static inline struct vpu_format *vpu_get_format (struct vpu_inst *inst,u32 type) {if (V4L2_TYPE_IS_OUTPUT (type))
@@ -41,11 +38,6 @@ static inline struct vpu_format *vpu_getreturn &inst->cap_format; } -static inline char *vpu_type_name (u32 type) -{ -return V4L2_TYPE_IS_OUTPUT (type) ?"output" :"capture" ; -} -static inline int vpu_vb_is_codecconfig (struct vb2_v4l2_buffer *vbuf) {#ifdef V4L2_BUF_FLAG_CODECCONFIG
Greg Kroah-Hartman
maintainerPATCH 583/634 media: amphion: Remove vpu_vb_is_codecconfig
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Qian <[email protected]>
[ Upstream commit 634c2cd17bd021487c57b95973bddb14be8002ff ]
Currently the function vpu_vb_is_codecconfig() always returns 0. Delete it and its related code.
--- drivers/media/platform/amphion/vpu_malone.c | 23 +++-------------------- drivers/media/platform/amphion/vpu_v4l2.c | 10 ---------- drivers/media/platform/amphion/vpu_v4l2.h | 10 ---------- 3 files changed, 3 insertions(+), 40 deletions(-)
drivers/media/platform/amphion/vpu_malone.c +3 -20
@@ -1295,22 +1295,18 @@ static int vpu_malone_insert_scode_vc1_g {if (!scode->inst->total_input_count)return 0 ; -if (vpu_vb_is_codecconfig (to_vb2_v4l2_buffer (scode->vb))) - scode->need_data =0 ;return 0 ; }static int vpu_malone_insert_scode_vc1_g_pic (struct malone_scode_t *scode) { -struct vb2_v4l2_buffer *vbuf;u8 nal_hdr[MALONE_VC1_NAL_HEADER_LEN ];u32 *data =NULL ;int ret; - vbuf =to_vb2_v4l2_buffer (scode->vb); data =vb2_plane_vaddr (scode->vb,0 ); -if (scode->inst->total_input_count ==0 ||vpu_vb_is_codecconfig (vbuf)) +if (scode->inst->total_input_count ==0 )return 0 ;if (MALONE_VC1_CONTAIN_NAL (*data))return 0 ;
@@ -1331,8 +1327,6 @@ static int vpu_malone_insert_scode_vc1_lint size =0 ;u8 rcv_seqhdr[MALONE_VC1_RCV_SEQ_HEADER_LEN ]; -if (vpu_vb_is_codecconfig (to_vb2_v4l2_buffer (scode->vb))) - scode->need_data =0 ;if (scode->inst->total_input_count)return 0 ; scode->need_data =0 ;
@@ -1503,7 +1497,7 @@ static int vpu_malone_input_frame_data(s scode.vb = vb; scode.wptr = wptr; scode.need_data =1 ; -if (vbuf->sequence ==0 ||vpu_vb_is_codecconfig (vbuf)) +if (vbuf->sequence ==0 ) ret =vpu_malone_insert_scode (&scode,SCODE_SEQUENCE );if (ret <0 )
@@ -1539,7 +1533,7 @@ static int vpu_malone_input_frame_data(s* This module is currently only supported for the H264 and HEVC formats, * for other formats, vpu_malone_add_scode() will return 0. */ -if ((disp_imm || low_latency) && !vpu_vb_is_codecconfig (vbuf)) { +if (disp_imm || low_latency) { ret = vpu_malone_add_scode(inst->core->iface, inst->id, &inst->stream_buffer,
@@ -1586,7 +1580,6 @@ int vpu_malone_input_frame(struct vpu_sh struct vpu_inst *inst, struct vb2_buffer *vb) { struct vpu_dec_ctrl *hc = shared->priv; -struct vb2_v4l2_buffer *vbuf;struct vpu_malone_str_buffer __iomem *str_buf = hc->str_buf[inst->id];u32 disp_imm = hc->codec_param[inst->id].disp_imm;u32 size;
@@ -1600,16 +1593,6 @@ int vpu_malone_input_frame(struct vpu_shreturn ret; size = ret; -/* -* if buffer only contain codec data, and the timestamp is invalid, -* don't put the invalid timestamp to resync -* merge the data to next frame -*/ - vbuf =to_vb2_v4l2_buffer (vb); -if (vpu_vb_is_codecconfig (vbuf)) { - inst->extra_size += size; -return 0 ; - }if (inst->extra_size) { size += inst->extra_size; inst->extra_size =0 ;
drivers/media/platform/amphion/vpu_v4l2.c +0 -10
@@ -257,16 +257,6 @@ struct vb2_v4l2_buffer *vpu_next_src_bufif (!src_buf ||vpu_get_buffer_state (src_buf) ==VPU_BUF_STATE_IDLE )return NULL ; -while (vpu_vb_is_codecconfig (src_buf)) { -v4l2_m2m_src_buf_remove (inst->fh.m2m_ctx); -vpu_set_buffer_state (src_buf,VPU_BUF_STATE_IDLE ); -v4l2_m2m_buf_done (src_buf,VB2_BUF_STATE_DONE ); - - src_buf =v4l2_m2m_next_src_buf (inst->fh.m2m_ctx); -if (!src_buf ||vpu_get_buffer_state (src_buf) ==VPU_BUF_STATE_IDLE ) -return NULL ; - } -return src_buf; }
drivers/media/platform/amphion/vpu_v4l2.h +0 -10
@@ -37,14 +37,4 @@ static inline struct vpu_format *vpu_get else return &inst->cap_format; } - -static inline int vpu_vb_is_codecconfig (struct vb2_v4l2_buffer *vbuf) -{ -#ifdef V4L2_BUF_FLAG_CODECCONFIG -return (vbuf->flags &V4L2_BUF_FLAG_CODECCONFIG ) ?1 :0 ; -#else -return 0 ; -#endif -} -#endif
Greg Kroah-Hartman
maintainerPATCH 584/634 media: mediatek: vcodec: Fix a reference leak in mtk_vcodec_fw_vpu_init()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haoxiang Li <[email protected]>
[ Upstream commit cdd0f118ef87db8a664fb5ea366fd1766d2df1cd ]
vpu_get_plat_device() increases the reference count of the returned platform device. However, when devm_kzalloc() fails, the reference is not released, causing a reference leak.
Fix this by calling put_device() on fw_pdev->dev before returning on the error path.
--- drivers/media/platform/mediatek/vcodec/mtk_vcodec_fw_vpu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/media/platform/mediatek/vcodec/mtk_vcodec_fw_vpu.c +3 -1
@@ -94,8 +94,10 @@ struct mtk_vcodec_fw *mtk_vcodec_fw_vpu_vpu_wdt_reg_handler (fw_pdev, mtk_vcodec_vpu_reset_handler, dev, rst_id); fw =devm_kzalloc (&dev->plat_dev->dev,sizeof (*fw),GFP_KERNEL ); -if (!fw) +if (!fw) { +put_device (&fw_pdev->dev);return ERR_PTR (-ENOMEM ); + } fw->type =VPU ; fw->ops = &mtk_vcodec_vpu_msg; fw->pdev = fw_pdev;
Greg Kroah-Hartman
maintainerPATCH 585/634 pmdomain: Use device_get_match_data()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rob Herring <[email protected]>
[ Upstream commit 3ba9fdfaa550936837b50b73d6c27ac401fde875 ]
Use preferred device_get_match_data() instead of of_match_device() to get the driver match data. With this, adjust the includes to explicitly include the correct headers.
Stable-dep-of: 73cb5f6eafb0 ("pmdomain: imx: Fix reference count leak in imx_gpc_probe()")
--- drivers/soc/actions/owl-sps.c | 16 +++++----------- drivers/soc/imx/gpc.c | 7 +++---- drivers/soc/rockchip/pm_domains.c | 13 ++++--------- 3 files changed, 12 insertions(+), 24 deletions(-)
drivers/soc/actions/owl-sps.c +5 -11
@@ -8,8 +8,10 @@* Copyright (c) 2017 Andreas Färber */ +#include <linux/mod_devicetable.h> #include <linux/of_address.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> +#include <linux/property.h> #include <linux/pm_domain.h> #include <linux/soc/actions/owl-sps.h> #include <dt-bindings/power/owl-s500-powergate.h>
@@ -96,24 +98,16 @@ static int owl_sps_init_domain(struct owstatic int owl_sps_probe (struct platform_device *pdev) { -const struct of_device_id *match;const struct owl_sps_info *sps_info;struct owl_sps *sps;int i, ret; -if (!pdev->dev.of_node) { -dev_err (&pdev->dev,"no device node\n" ); -return -ENODEV ; - } - - match =of_match_device (pdev->dev.driver->of_match_table, &pdev->dev); -if (!match || !match->data) { + sps_info =device_get_match_data (&pdev->dev); +if (!sps_info) {dev_err (&pdev->dev,"unknown compatible or missing data\n" );return -EINVAL ; } - sps_info = match->data; - sps =devm_kzalloc (&pdev->dev,struct_size (sps, domains, sps_info->num_domains),GFP_KERNEL );
drivers/soc/imx/gpc.c +3 -4
@@ -7,9 +7,10 @@#include <linux/clk.h> #include <linux/delay.h> #include <linux/io.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_domain.h> +#include <linux/property.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h>
@@ -403,9 +404,7 @@ clk_err:static int imx_gpc_probe (struct platform_device *pdev) { -const struct of_device_id *of_id = -of_match_device (imx_gpc_dt_ids, &pdev->dev); -const struct imx_gpc_dt_data *of_id_data = of_id->data; +const struct imx_gpc_dt_data *of_id_data =device_get_match_data (&pdev->dev);struct device_node *pgc_node;struct regmap *regmap;void __iomem *base;
drivers/soc/rockchip/pm_domains.c +4 -9
@@ -9,11 +9,13 @@#include <linux/iopoll.h> #include <linux/err.h> #include <linux/mutex.h> +#include <linux/platform_device.h> #include <linux/pm_clock.h> #include <linux/pm_domain.h> +#include <linux/property.h> +#include <linux/of.h> #include <linux/of_address.h> #include <linux/of_clk.h> -#include <linux/of_platform.h> #include <linux/clk.h> #include <linux/regmap.h> #include <linux/mfd/syscon.h>
@@ -770,7 +772,6 @@ static int rockchip_pm_domain_probe(strustruct device_node *node;struct device *parent;struct rockchip_pmu *pmu; -const struct of_device_id *match;const struct rockchip_pmu_info *pmu_info;int error;
@@ -779,13 +780,7 @@ static int rockchip_pm_domain_probe(strureturn -ENODEV ; } - match =of_match_device (dev->driver->of_match_table, dev); -if (!match || !match->data) { -dev_err (dev,"missing pmu data\n" ); -return -EINVAL ; - } - - pmu_info = match->data; + pmu_info =device_get_match_data (dev); pmu = devm_kzalloc(dev, struct_size(pmu, domains, pmu_info->num_domains),
Greg Kroah-Hartman
maintainerPATCH 586/634 pmdomain: imx: Fix reference count leak in imx_gpc_probe()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wentao Liang <[email protected]>
[ Upstream commit 73cb5f6eafb0ac7aea8cdeb8ff12981aa741d8fb ]
of_get_child_by_name() returns a node pointer with refcount incremented. Use the __free() attribute to manage the pgc_node reference, ensuring automatic of_node_put() cleanup when pgc_node goes out of scope.
This eliminates the need for explicit error handling paths and avoids reference count leaks.
--- drivers/soc/imx/gpc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/soc/imx/gpc.c +2 -3
@@ -405,13 +405,12 @@ clk_err:static int imx_gpc_probe (struct platform_device *pdev) {const struct imx_gpc_dt_data *of_id_data =device_get_match_data (&pdev->dev); -struct device_node *pgc_node; + struct device_node *pgc_node __free(device_node) + =of_get_child_by_name (pdev->dev.of_node,"pgc" );struct regmap *regmap;void __iomem *base;int ret; - pgc_node =of_get_child_by_name (pdev->dev.of_node,"pgc" ); -/* bail out if DT too old and doesn't provide the necessary info */ if (!of_property_read_bool (pdev->dev.of_node,"#power-domain-cells" ) && !pgc_node)
Greg Kroah-Hartman
maintainerPATCH 587/634 mptcp: fallback earlier on simult connection
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paolo Abeni <[email protected]>
[ Upstream commit 71154bbe49423128c1c8577b6576de1ed6836830 ]
Syzkaller reports a simult-connect race leading to inconsistent fallback status:
WARNING: CPU: 3 PID: 33 at net/mptcp/subflow.c:1515 subflow_data_ready+0x40b/0x7c0 net/mptcp/subflow.c:1515 Modules linked in: CPU: 3 UID: 0 PID: 33 Comm: ksoftirqd/3 Not tainted syzkaller #0 PREEMPT(full) Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 RIP: 0010:subflow_data_ready+0x40b/0x7c0 net/mptcp/subflow.c:1515 Code: 89 ee e8 78 61 3c f6 40 84 ed 75 21 e8 8e 66 3c f6 44 89 fe bf 07 00 00 00 e8 c1 61 3c f6 41 83 ff 07 74 09 e8 76 66 3c f6 90 <0f> 0b 90 e8 6d 66 3c f6 48 89 df e8 e5 ad ff ff 31 ff 89 c5 89 c6 RSP: 0018:ffffc900006cf338 EFLAGS: 00010246 RAX: 0000000000000000 RBX: ffff888031acd100 RCX: ffffffff8b7f2abf RDX: ffff88801e6ea440 RSI: ffffffff8b7f2aca RDI: 0000000000000005 RBP: 0000000000000000 R08: 0000000000000005 R09: 0000000000000007 R10: 0000000000000004 R11: 0000000000002c10 R12: ffff88802ba69900 R13: 1ffff920000d9e67 R14: ffff888046f81800 R15: 0000000000000004 FS: 0000000000000000(0000) GS:ffff8880d69bc000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000560fc0ca1670 CR3: 0000000032c3a000 CR4: 0000000000352ef0 Call Trace: <TASK> tcp_data_queue+0x13b0/0x4f90 net/ipv4/tcp_input.c:5197 tcp_rcv_state_process+0xfdf/0x4ec0 net/ipv4/tcp_input.c:6922 tcp_v6_do_rcv+0x492/0x1740 net/ipv6/tcp_ipv6.c:1672 tcp_v6_rcv+0x2976/0x41e0 net/ipv6/tcp_ipv6.c:1918 ip6_protocol_deliver_rcu+0x188/0x1520 net/ipv6/ip6_input.c:438 ip6_input_finish+0x1e4/0x4b0 net/ipv6/ip6_input.c:489 NF_HOOK include/linux/netfilter.h:318 [inline] NF_HOOK include/linux/netfilter.h:312 [inline] ip6_input+0x105/0x2f0 net/ipv6/ip6_input.c:500 dst_input include/net/dst.h:471 [inline] ip6_rcv_finish net/ipv6/ip6_input.c:79 [inline] NF_HOOK include/linux/netfilter.h:318 [inline] NF_HOOK include/linux/netfilter.h:312 [inline] ipv6_rcv+0x264/0x650 net/ipv6/ip6_input.c:311 __netif_receive_skb_one_core+0x12d/0x1e0 net/core/dev.c:5979 __netif_receive_skb+0x1d/0x160 net/core/dev.c:6092 process_backlog+0x442/0x15e0 net/core/dev.c:6444 __napi_poll.constprop.0+0xba/0x550 net/core/dev.c:7494 napi_poll net/core/dev.c:7557 [inline] net_rx_action+0xa9f/0xfe0 net/core/dev.c:7684 handle_softirqs+0x216/0x8e0 kernel/softirq.c:579 run_ksoftirqd kernel/softirq.c:968 [inline] run_ksoftirqd+0x3a/0x60 kernel/softirq.c:960 smpboot_thread_fn+0x3f7/0xae0 kernel/smpboot.c:160 kthread+0x3c2/0x780 kernel/kthread.c:463 ret_from_fork+0x5d7/0x6f0 arch/x86/kernel/process.c:148 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 </TASK>
The TCP subflow can process the simult-connect syn-ack packet after transitioning to TCP_FIN1 state, bypassing the MPTCP fallback check, as the sk_state_change() callback is not invoked for * -> FIN_WAIT1 transitions.
That will move the msk socket to an inconsistent status and the next incoming data will hit the reported splat.
Close the race moving the simult-fallback check at the earliest possible stage - that is at syn-ack generation time.
About the fixes tags: [2] was supposed to also fix this issue introduced by [3]. [1] is required as a dependence: it was not explicitly marked as a fix, but it is one and it has already been backported before [3]. In other words, this commit should be backported up to [3], including [2] and [1] if that's not already there.
--- net/mptcp/options.c | 10 ++++++++++ net/mptcp/protocol.h | 5 ++--- net/mptcp/subflow.c | 9 --------- 3 files changed, 12 insertions(+), 12 deletions(-)
net/mptcp/options.c +10 -0
@@ -403,6 +403,16 @@ bool mptcp_syn_options(struct sock *sk,*/ subflow->snd_isn =TCP_SKB_CB (skb)->end_seq;if (subflow->request_mptcp) { +if (unlikely (subflow_simultaneous_connect (sk))) { +WARN_ON_ONCE (!mptcp_try_fallback (sk)); + +/* Ensure mptcp_finish_connect() will not process the +* MPC handshake. +*/ + subflow->request_mptcp =0 ; +return false; + } + opts->suboptions =OPTION_MPTCP_MPC_SYN ; opts->csum_reqd =mptcp_is_checksum_enabled (sock_net (sk)); opts->allow_join_id0 =mptcp_allow_join_id0 (sock_net (sk));
net/mptcp/protocol.h +2 -3
@@ -1053,9 +1053,8 @@ static inline bool subflow_simultaneous_ {struct mptcp_subflow_context *subflow =mptcp_subflow_ctx (sk); -return sk->sk_state ==TCP_ESTABLISHED && -is_active_ssk (subflow) && - !subflow->conn_finished; +/* Note that the sk state implies !subflow->conn_finished. */ +return sk->sk_state ==TCP_SYN_RECV &&is_active_ssk (subflow); }#ifdef CONFIG_SYN_COOKIES
net/mptcp/subflow.c +0 -9
@@ -1700,15 +1700,6 @@ static void subflow_state_change(struct__subflow_state_change (sk); msk =mptcp_sk (parent); -if (subflow_simultaneous_connect (sk)) { -mptcp_propagate_sndbuf (parent, sk); -WARN_ON_ONCE (!mptcp_try_fallback (sk)); -mptcp_rcv_space_init (msk, sk); -pr_fallback (msk); - subflow->conn_finished =1 ; -mptcp_set_connected (parent); - } -/* as recvmsg() does not acquire the subflow socket for ssk selection * a fin packet carrying a DSS can be unnoticed if we don't trigger * the data available machinery here.
Greg Kroah-Hartman
maintainerPATCH 588/634 lockd: fix vfs_test_lock() calls
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: NeilBrown <[email protected]>
[ Upstream commit a49a2a1baa0c553c3548a1c414b6a3c005a8deba ]
Usage of vfs_test_lock() is somewhat confused. Documentation suggests it is given a "lock" but this is not the case. It is given a struct file_lock which contains some details of the sort of lock it should be looking for.
In particular passing a "file_lock" containing fl_lmops or fl_ops is meaningless and possibly confusing.
This is particularly problematic in lockd. nlmsvc_testlock() receives an initialised "file_lock" from xdr-decode, including manager ops and an owner. It then mistakenly passes this to vfs_test_lock() which might replace the owner and the ops. This can lead to confusion when freeing the lock.
The primary role of the 'struct file_lock' passed to vfs_test_lock() is to report a conflicting lock that was found, so it makes more sense for nlmsvc_testlock() to pass "conflock", which it uses for returning the conflicting lock.
With this change, freeing of the lock is not confused and code in __nlm4svc_proc_test() and __nlmsvc_proc_test() can be simplified.
Documentation for vfs_test_lock() is improved to reflect its real purpose, and a WARN_ON_ONCE() is added to avoid a similar problem in the future.
--- fs/lockd/svc4proc.c | 4 +--- fs/lockd/svclock.c | 21 ++++++++++++--------- fs/lockd/svcproc.c | 5 +---- fs/locks.c | 13 +++++++++++-- 4 files changed, 25 insertions(+), 18 deletions(-)
fs/lockd/svc4proc.c +1 -3
@@ -96,7 +96,6 @@ __nlm4svc_proc_test(struct svc_rqst *rqsstruct nlm_args *argp = rqstp->rq_argp;struct nlm_host *host;struct nlm_file *file; -struct nlm_lockowner *test_owner;__be32 rc = rpc_success;dprintk ("lockd: TEST4 called\n" );
@@ -106,7 +105,6 @@ __nlm4svc_proc_test(struct svc_rqst *rqsif ((resp->status =nlm4svc_retrieve_args (rqstp, argp, &host, &file)))return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; - test_owner = argp->lock.fl.fl_owner;/* Now check for conflicting locks */ resp->status =nlmsvc_testlock (rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie);if (resp->status == nlm_drop_reply)
@@ -114,7 +112,7 @@ __nlm4svc_proc_test(struct svc_rqst *rqselse dprintk ("lockd: TEST4 status %d\n" ,ntohl (resp->status)); -nlmsvc_put_lockowner (test_owner); +nlmsvc_release_lockowner (&argp->lock);nlmsvc_release_host (host);nlm_release_file (file);return rc;
fs/lockd/svclock.c +12 -9
@@ -604,7 +604,13 @@ nlmsvc_testlock(struct svc_rqst *rqstp, } mode =lock_to_openmode (&lock->fl); - error =vfs_test_lock (file->f_file[mode], &lock->fl); +locks_init_lock (&conflock->fl); +/* vfs_test_lock only uses start, end, and owner, but tests fl_file */ + conflock->fl.fl_file = lock->fl.fl_file; + conflock->fl.fl_start = lock->fl.fl_start; + conflock->fl.fl_end = lock->fl.fl_end; + conflock->fl.fl_owner = lock->fl.fl_owner; + error =vfs_test_lock (file->f_file[mode], &conflock->fl);if (error) {/* We can't currently deal with deferred test requests */ if (error ==FILE_LOCK_DEFERRED )
@@ -614,22 +620,19 @@ nlmsvc_testlock(struct svc_rqst *rqstp, goto out; } -if (lock->fl.fl_type ==F_UNLCK ) { +if (conflock->fl.fl_type ==F_UNLCK ) { ret = nlm_granted; goto out; }dprintk ("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n" , - lock->fl.fl_type, (long long )lock->fl.fl_start, - (long long )lock->fl.fl_end); + conflock->fl.fl_type, (long long )conflock->fl.fl_start, + (long long )conflock->fl.fl_end); conflock->caller ="somehost" ;/* FIXME */ conflock->len =strlen (conflock->caller); conflock->oh.len =0 ;/* don't return OH info */ - conflock->svid = lock->fl.fl_pid; - conflock->fl.fl_type = lock->fl.fl_type; - conflock->fl.fl_start = lock->fl.fl_start; - conflock->fl.fl_end = lock->fl.fl_end; -locks_release_private (&lock->fl); + conflock->svid = conflock->fl.fl_pid; +locks_release_private (&conflock->fl); ret = nlm_lck_denied; out:
fs/lockd/svcproc.c +1 -4
@@ -117,7 +117,6 @@ __nlmsvc_proc_test(struct svc_rqst *rqststruct nlm_args *argp = rqstp->rq_argp;struct nlm_host *host;struct nlm_file *file; -struct nlm_lockowner *test_owner;__be32 rc = rpc_success;dprintk ("lockd: TEST called\n" );
@@ -127,8 +126,6 @@ __nlmsvc_proc_test(struct svc_rqst *rqstif ((resp->status =nlmsvc_retrieve_args (rqstp, argp, &host, &file)))return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; - test_owner = argp->lock.fl.fl_owner; -/* Now check for conflicting locks */ resp->status =cast_status (nlmsvc_testlock (rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie));if (resp->status == nlm_drop_reply)
@@ -137,7 +134,7 @@ __nlmsvc_proc_test(struct svc_rqst *rqstdprintk ("lockd: TEST status %d vers %d\n" ,ntohl (resp->status), rqstp->rq_vers); -nlmsvc_put_lockowner (test_owner); +nlmsvc_release_lockowner (&argp->lock);nlmsvc_release_host (host);nlm_release_file (file);return rc;
fs/locks.c +11 -2
@@ -2140,13 +2140,22 @@ SYSCALL_DEFINE2(flock, unsigned int, fd,/** * vfs_test_lock - test file byte range lock * @filp: The file to test lock for -* @fl: The lock to test; also used to hold result +* @fl: The byte-range in the file to test; also used to hold result * +* On entry, @fl does not contain a lock, but identifies a range (fl_start, fl_end) +* in the file (c.flc_file), and an owner (c.flc_owner) for whom existing locks +* should be ignored. c.flc_type and c.flc_flags are ignored. +* Both fl_lmops and fl_ops in @fl must be NULL. * Returns -ERRNO on failure. Indicates presence of conflicting lock by -* setting conf->fl_type to something other than F_UNLCK. +* setting fl->fl_type to something other than F_UNLCK. +* +* If vfs_test_lock() does find a lock and return it, the caller must +* use locks_free_lock() or locks_release_private() on the returned lock. */ int vfs_test_lock (struct file *filp,struct file_lock *fl) { +WARN_ON_ONCE (fl->fl_ops || fl->fl_lmops); +WARN_ON_ONCE (filp != fl->fl_file);if (filp->f_op->lock)return filp->f_op->lock (filp,F_GETLK , fl);posix_test_lock (filp, fl);
Greg Kroah-Hartman
maintainerPATCH 589/634 mm: simplify folio_expected_ref_count()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Hildenbrand <[email protected]>
[ Upstream commit 78cb1a13c42a6d843e21389f74d1edb90ed07288 ]
Now that PAGE_MAPPING_MOVABLE is gone, we can simplify and rely on the folio_test_anon() test only.
... but staring at the users, this function should never even have been called on movable_ops pages. E.g.,
* __buffer_migrate_folio() does not make sense for them
* folio_migrate_mapping() does not make sense for them
* migrate_huge_page_move_mapping() does not make sense for them
* __migrate_folio() does not make sense for them
* ... and khugepaged should never stumble over them
Let's simply refuse typed pages (which includes slab) except hugetlb, and WARN.
Stable-dep-of: f183663901f2 ("mm: consider non-anon swap cache folios in folio_expected_ref_count()")
--- include/linux/mm.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
include/linux/mm.h +2 -2
@@ -1820,13 +1820,13 @@ static inline int folio_expected_ref_couconst int order =folio_order (folio);int ref_count =0 ; -if (WARN_ON_ONCE (folio_test_slab (folio))) +if (WARN_ON_ONCE (page_has_type (&folio->page) && !folio_test_hugetlb (folio)))return 0 ;if (folio_test_anon (folio)) {/* One reference per page from the swapcache. */ ref_count +=folio_test_swapcache (folio) << order; - }else if (!((unsigned long )folio->mapping &PAGE_MAPPING_FLAGS )) { + }else {/* One reference per page from the pagecache. */ ref_count += !!folio->mapping << order;/* One reference from PG_private. */
Greg Kroah-Hartman
maintainerPATCH 590/634 mm: consider non-anon swap cache folios in folio_expected_ref_count()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bijan Tabatabai <[email protected]>
[ Upstream commit f183663901f21fe0fba8bd31ae894bc529709ee0 ]
Currently, folio_expected_ref_count() only adds references for the swap cache if the folio is anonymous. However, according to the comment above the definition of PG_swapcache in enum pageflags, shmem folios can also have PG_swapcache set. This patch makes sure references for the swap cache are added if folio_test_swapcache(folio) is true.
This issue was found when trying to hot-unplug memory in a QEMU/KVM virtual machine. When initiating hot-unplug when most of the guest memory is allocated, hot-unplug hangs partway through removal due to migration failures. The following message would be printed several times, and would be printed again about every five seconds:
[ 49.641309] migrating pfn b12f25 failed ret:7 [ 49.641310] page: refcount:2 mapcount:0 mapping:0000000033bd8fe2 index:0x7f404d925 pfn:0xb12f25 [ 49.641311] aops:swap_aops [ 49.641313] flags: 0x300000000030508(uptodate|active|owner_priv_1|reclaim|swapbacked|node=0|zone=3) [ 49.641314] raw: 0300000000030508 ffffed312c4bc908 ffffed312c4bc9c8 0000000000000000 [ 49.641315] raw: 00000007f404d925 00000000000c823b 00000002ffffffff 0000000000000000 [ 49.641315] page dumped because: migration failure
When debugging this, I found that these migration failures were due to __migrate_folio() returning -EAGAIN for a small set of folios because the expected reference count it calculates via folio_expected_ref_count() is one less than the actual reference count of the folios. Furthermore, all of the affected folios were not anonymous, but had the PG_swapcache flag set, inspiring this patch. After applying this patch, the memory hot-unplug behaves as expected.
I tested this on a machine running Ubuntu 24.04 with kernel version 6.8.0-90-generic and 64GB of memory. The guest VM is managed by libvirt and runs Ubuntu 24.04 with kernel version 6.18 (though the head of the mm-unstable branch as a Dec 16, 2025 was also tested and behaves the same) and 48GB of memory. The libvirt XML definition for the VM can be found at [1]. CONFIG_MHP_DEFAULT_ONLINE_TYPE_ONLINE_MOVABLE is set in the guest kernel so the hot-pluggable memory is automatically onlined.
Below are the steps to reproduce this behavior:
1) Define and start and virtual machine
host$ virsh -c qemu:///system define ./test_vm.xml # test_vm.xml from [1] host$ virsh -c qemu:///system start test_vm
2) Setup swap in the guest
guest$ sudo fallocate -l 32G /swapfile
guest$ sudo chmod 0600 /swapfile
guest$ sudo mkswap /swapfile
guest$ sudo swapon /swapfile
3) Use alloc_data [2] to allocate most of the remaining guest memory guest$ ./alloc_data 45
4) In a separate guest terminal, monitor the amount of used memory guest$ watch -n1 free -h
5) When alloc_data has finished allocating, initiate the memory hot-unplug using the provided xml file [3]
host$ virsh -c qemu:///system detach-device test_vm ./remove.xml --live
After initiating the memory hot-unplug, you should see the amount of available memory in the guest decrease, and the amount of used swap data increase. If everything works as expected, when all of the memory is unplugged, there should be around 8.5-9GB of data in swap. If the unplugging is unsuccessful, the amount of used swap data will settle below that. If that happens, you should be able to see log messages in dmesg similar to the one posted above.
--- include/linux/mm.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
include/linux/mm.h +4 -4
@@ -1823,10 +1823,10 @@ static inline int folio_expected_ref_couif (WARN_ON_ONCE (page_has_type (&folio->page) && !folio_test_hugetlb (folio)))return 0 ; -if (folio_test_anon (folio)) { -/* One reference per page from the swapcache. */ - ref_count +=folio_test_swapcache (folio) << order; - }else { +/* One reference per page from the swapcache. */ + ref_count +=folio_test_swapcache (folio) << order; + +if (!folio_test_anon (folio)) {/* One reference per page from the pagecache. */ ref_count += !!folio->mapping << order;/* One reference from PG_private. */
Greg Kroah-Hartman
maintainerPATCH 591/634 wifi: mac80211: Discard Beacon frames to non-broadcast address
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jouni Malinen <[email protected]>
[ Upstream commit 193d18f60588e95d62e0f82b6a53893e5f2f19f8 ]
Beacon frames are required to be sent to the broadcast address, see IEEE Std 802.11-2020, 11.1.3.1 ("The Address 1 field of the Beacon .. frame shall be set to the broadcast address"). A unicast Beacon frame might be used as a targeted attack to get one of the associated STAs to do something (e.g., using CSA to move it to another channel). As such, it is better have strict filtering for this on the received side and discard all Beacon frames that are sent to an unexpected address.
This is even more important for cases where beacon protection is used. The current implementation in mac80211 is correctly discarding unicast Beacon frames if the Protected Frame bit in the Frame Control field is set to 0. However, if that bit is set to 1, the logic used for checking for configured BIGTK(s) does not actually work. If the driver does not have logic for dropping unicast Beacon frames with Protected Frame bit 1, these frames would be accepted in mac80211 processing as valid Beacon frames even though they are not protected. This would allow beacon protection to be bypassed. While the logic for checking beacon protection could be extended to cover this corner case, a more generic check for discard all Beacon frames based on A1=unicast address covers this without needing additional changes.
Address all these issues by dropping received Beacon frames if they are sent to a non-broadcast address.
--- net/mac80211/rx.c | 5 +++++ 1 file changed, 5 insertions(+)
net/mac80211/rx.c +5 -0
@@ -3299,6 +3299,11 @@ ieee80211_rx_h_mgmt_check(struct ieee802if (!ieee80211_is_mgmt (mgmt->frame_control))return RX_DROP_MONITOR ; +/* Drop non-broadcast Beacon frames */ +if (ieee80211_is_beacon (mgmt->frame_control) && + !is_broadcast_ether_addr (mgmt->da)) +return RX_DROP_MONITOR ; +if (rx->sdata->vif.type ==NL80211_IFTYPE_AP &&ieee80211_is_beacon (mgmt->frame_control) && !(rx->flags &IEEE80211_RX_BEACON_REPORTED )) {
Greg Kroah-Hartman
maintainerPATCH 592/634 drm/amdgpu: cleanup scheduler job initialization v2
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian König <[email protected]>
[ Upstream commit f7d66fb2ea43a3016e78a700a2ca6c77a74579f9 ]
Init the DRM scheduler base class while allocating the job.
This makes the whole handling much more cleaner.
v2: fix coding style
Stable-dep-of: 4fa944255be5 ("drm/amdgpu: add missing lock to amdgpu_ttm_access_memory_sdma")
--- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 2 drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 8 --- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 44 ++++++++++---------- drivers/gpu/drm/amd/amdgpu/amdgpu_job.h | 14 +++--- drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c | 7 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 56 +++++++++---------------- drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 9 +--- drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 13 +++-- drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 22 +++++----- drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c | 61 ++++++++++++++-------------- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 12 +---- drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c | 8 +-- drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c | 12 ++--- drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 17 ++----- 14 files changed, 135 insertions(+), 150 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +1 -1
@@ -673,7 +673,7 @@ int amdgpu_amdkfd_submit_ib(struct amdgp goto err; } - ret =amdgpu_job_alloc (adev,1 , &job,NULL ); + ret =amdgpu_job_alloc (adev,NULL ,NULL ,NULL ,1 , &job);if (ret) goto err;
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +2 -6
@@ -285,12 +285,8 @@ static int amdgpu_cs_pass1(struct amdgpu }for (i =0 ; i < p->gang_size; ++i) { - ret =amdgpu_job_alloc (p->adev, num_ibs[i], &p->jobs[i], vm); -if (ret) - goto free_all_kdata; - - ret =drm_sched_job_init (&p->jobs[i]->base, p->entities[i], - &fpriv->vm); + ret =amdgpu_job_alloc (p->adev, vm, p->entities[i], vm, + num_ibs[i], &p->jobs[i]);if (ret) goto free_all_kdata; }
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +23 -21
85 lines not on this page · raw message
drivers/gpu/drm/amd/amdgpu/amdgpu_job.h +8 -6
@@ -78,18 +78,20 @@ static inline struct amdgpu_ring *amdgpureturn to_amdgpu_ring (job->base.entity->rq->sched); } -int amdgpu_job_alloc (struct amdgpu_device *adev,unsigned num_ibs, -struct amdgpu_job **job,struct amdgpu_vm *vm); -int amdgpu_job_alloc_with_ib (struct amdgpu_device *adev,unsigned size, -enum amdgpu_ib_pool_type pool,struct amdgpu_job **job); +int amdgpu_job_alloc (struct amdgpu_device *adev,struct amdgpu_vm *vm, +struct drm_sched_entity *entity,void *owner, +unsigned int num_ibs,struct amdgpu_job **job); +int amdgpu_job_alloc_with_ib (struct amdgpu_device *adev, +struct drm_sched_entity *entity,void *owner, +size_t size,enum amdgpu_ib_pool_type pool_type, +struct amdgpu_job **job);void amdgpu_job_set_resources (struct amdgpu_job *job,struct amdgpu_bo *gds,struct amdgpu_bo *gws,struct amdgpu_bo *oa);void amdgpu_job_free_resources (struct amdgpu_job *job);void amdgpu_job_set_gang_leader (struct amdgpu_job *job,struct amdgpu_job *leader);void amdgpu_job_free (struct amdgpu_job *job); -int amdgpu_job_submit (struct amdgpu_job *job,struct drm_sched_entity *entity, -void *owner,struct dma_fence **f); +struct dma_fence *amdgpu_job_submit (struct amdgpu_job *job);int amdgpu_job_submit_direct (struct amdgpu_job *job,struct amdgpu_ring *ring,struct dma_fence **fence);
drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c +4 -3
@@ -152,14 +152,15 @@ static int amdgpu_jpeg_dec_set_reg(strucconst unsigned ib_size_dw =16 ;int i, r; - r =amdgpu_job_alloc_with_ib (ring->adev, ib_size_dw *4 , -AMDGPU_IB_POOL_DIRECT , &job); + r =amdgpu_job_alloc_with_ib (ring->adev,NULL ,NULL , ib_size_dw *4 , +AMDGPU_IB_POOL_DIRECT , &job);if (r)return r; ib = &job->ibs[0 ]; - ib->ptr[0 ] =PACKETJ (adev->jpeg.internal.jpeg_pitch,0 ,0 ,PACKETJ_TYPE0 ); + ib->ptr[0 ] =PACKETJ (adev->jpeg.internal.jpeg_pitch,0 ,0 , +PACKETJ_TYPE0 ); ib->ptr[1 ] =0xDEADBEEF ;for (i =2 ; i <16 ; i +=2 ) { ib->ptr[i] =PACKETJ (0 ,0 ,0 ,PACKETJ_TYPE6 );
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +21 -35
117 lines not on this page · raw message
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +4 -5
@@ -1132,7 +1132,9 @@ static int amdgpu_uvd_send_msg(struct amunsigned offset_idx =0 ;unsigned offset[3 ] = {UVD_BASE_SI ,0 ,0 }; - r =amdgpu_job_alloc_with_ib (adev,64 , direct ?AMDGPU_IB_POOL_DIRECT : + r =amdgpu_job_alloc_with_ib (ring->adev, &adev->uvd.entity, +AMDGPU_FENCE_OWNER_UNDEFINED , +64 , direct ?AMDGPU_IB_POOL_DIRECT :AMDGPU_IB_POOL_DELAYED , &job);if (r)return r;
@@ -1181,10 +1183,7 @@ static int amdgpu_uvd_send_msg(struct amif (r) goto err_free; - r =amdgpu_job_submit (job, &adev->uvd.entity, -AMDGPU_FENCE_OWNER_UNDEFINED , &f); -if (r) - goto err_free; + f =amdgpu_job_submit (job); }amdgpu_bo_reserve (bo, true);
drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +8 -5
@@ -450,8 +450,10 @@ static int amdgpu_vce_get_create_msg(struint64_t addr;int i, r; - r =amdgpu_job_alloc_with_ib (ring->adev, ib_size_dw *4 , -AMDGPU_IB_POOL_DIRECT , &job); + r =amdgpu_job_alloc_with_ib (ring->adev, &ring->adev->vce.entity, +AMDGPU_FENCE_OWNER_UNDEFINED , + ib_size_dw *4 ,AMDGPU_IB_POOL_DIRECT , + &job);if (r)return r;
@@ -538,7 +540,9 @@ static int amdgpu_vce_get_destroy_msg(ststruct dma_fence *f =NULL ;int i, r; - r =amdgpu_job_alloc_with_ib (ring->adev, ib_size_dw *4 , + r =amdgpu_job_alloc_with_ib (ring->adev, &ring->adev->vce.entity, +AMDGPU_FENCE_OWNER_UNDEFINED , + ib_size_dw *4 , direct ?AMDGPU_IB_POOL_DIRECT :AMDGPU_IB_POOL_DELAYED , &job);if (r)
@@ -570,8 +574,7 @@ static int amdgpu_vce_get_destroy_msg(stif (direct) r =amdgpu_job_submit_direct (job, ring, &f);else - r =amdgpu_job_submit (job, &ring->adev->vce.entity, -AMDGPU_FENCE_OWNER_UNDEFINED , &f); + f =amdgpu_job_submit (job);if (r) goto err;
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +13 -9
@@ -627,15 +627,16 @@ static int amdgpu_vcn_dec_send_msg(strucstruct amdgpu_ib *ib_msg, struct dma_fence **fence) { + u64 addr = AMDGPU_GPU_PAGE_ALIGN(ib_msg->gpu_addr);struct amdgpu_device *adev = ring->adev;struct dma_fence *f =NULL ;struct amdgpu_job *job;struct amdgpu_ib *ib; -uint64_t addr =AMDGPU_GPU_PAGE_ALIGN (ib_msg->gpu_addr);int i, r; - r =amdgpu_job_alloc_with_ib (adev,64 , -AMDGPU_IB_POOL_DIRECT , &job); + r =amdgpu_job_alloc_with_ib (ring->adev,NULL ,NULL , +64 ,AMDGPU_IB_POOL_DIRECT , + &job);if (r) goto err;
@@ -813,8 +814,9 @@ static int amdgpu_vcn_dec_sw_send_msg(stif (adev->vcn.using_unified_queue) ib_size_dw +=8 ; - r =amdgpu_job_alloc_with_ib (adev, ib_size_dw *4 , -AMDGPU_IB_POOL_DIRECT , &job); + r =amdgpu_job_alloc_with_ib (ring->adev,NULL ,NULL , + ib_size_dw *4 ,AMDGPU_IB_POOL_DIRECT , + &job);if (r) goto err;
@@ -942,8 +944,9 @@ static int amdgpu_vcn_enc_get_create_msgif (adev->vcn.using_unified_queue) ib_size_dw +=8 ; - r =amdgpu_job_alloc_with_ib (ring->adev, ib_size_dw *4 , -AMDGPU_IB_POOL_DIRECT , &job); + r =amdgpu_job_alloc_with_ib (ring->adev,NULL ,NULL , + ib_size_dw *4 ,AMDGPU_IB_POOL_DIRECT , + &job);if (r)return r;
@@ -1008,8 +1011,9 @@ static int amdgpu_vcn_enc_get_destroy_msif (adev->vcn.using_unified_queue) ib_size_dw +=8 ; - r =amdgpu_job_alloc_with_ib (ring->adev, ib_size_dw *4 , -AMDGPU_IB_POOL_DIRECT , &job); + r =amdgpu_job_alloc_with_ib (ring->adev,NULL ,NULL , + ib_size_dw *4 ,AMDGPU_IB_POOL_DIRECT , + &job);if (r)return r;
drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c +31 -30
111 lines not on this page · raw message
drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +4 -8
@@ -371,7 +371,9 @@ static void gmc_v10_0_flush_gpu_tlb(stru* translation. Avoid this by doing the invalidation from the SDMA * itself. */ - r =amdgpu_job_alloc_with_ib (adev,16 *4 ,AMDGPU_IB_POOL_IMMEDIATE , + r =amdgpu_job_alloc_with_ib (ring->adev, &adev->mman.entity, +AMDGPU_FENCE_OWNER_UNDEFINED , +16 *4 ,AMDGPU_IB_POOL_IMMEDIATE , &job);if (r) goto error_alloc;
@@ -380,10 +382,7 @@ static void gmc_v10_0_flush_gpu_tlb(stru job->vm_needs_flush = true; job->ibs->ptr[job->ibs->length_dw++] = ring->funcs->nop;amdgpu_ring_pad_ib (ring, &job->ibs[0 ]); - r =amdgpu_job_submit (job, &adev->mman.entity, -AMDGPU_FENCE_OWNER_UNDEFINED , &fence); -if (r) - goto error_submit; + fence =amdgpu_job_submit (job);mutex_unlock (&adev->mman.gtt_window_lock);
@@ -392,9 +391,6 @@ static void gmc_v10_0_flush_gpu_tlb(strureturn ; -error_submit: -amdgpu_job_free (job); - error_alloc:mutex_unlock (&adev->mman.gtt_window_lock);DRM_ERROR ("Error flushing GPU TLB using the SDMA (%d)!\n" , r);
drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c +4 -4
@@ -216,8 +216,8 @@ static int uvd_v6_0_enc_get_create_msg(suint64_t addr;int i, r; - r =amdgpu_job_alloc_with_ib (ring->adev, ib_size_dw *4 , -AMDGPU_IB_POOL_DIRECT , &job); + r =amdgpu_job_alloc_with_ib (ring->adev,NULL ,NULL , ib_size_dw *4 , +AMDGPU_IB_POOL_DIRECT , &job);if (r)return r;
@@ -280,8 +280,8 @@ static int uvd_v6_0_enc_get_destroy_msg(uint64_t addr;int i, r; - r =amdgpu_job_alloc_with_ib (ring->adev, ib_size_dw *4 , -AMDGPU_IB_POOL_DIRECT , &job); + r =amdgpu_job_alloc_with_ib (ring->adev,NULL ,NULL , ib_size_dw *4 , +AMDGPU_IB_POOL_DIRECT , &job);if (r)return r;
drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c +6 -6
@@ -213,7 +213,7 @@ static int uvd_v7_0_enc_ring_test_ring(s* * Open up a stream for HW test */ -static int uvd_v7_0_enc_get_create_msg (struct amdgpu_ring *ring,uint32_t handle, +static int uvd_v7_0_enc_get_create_msg (struct amdgpu_ring *ring,u32 handle,struct amdgpu_bo *bo,struct dma_fence **fence) {
@@ -224,8 +224,8 @@ static int uvd_v7_0_enc_get_create_msg(suint64_t addr;int i, r; - r =amdgpu_job_alloc_with_ib (ring->adev, ib_size_dw *4 , -AMDGPU_IB_POOL_DIRECT , &job); + r =amdgpu_job_alloc_with_ib (ring->adev,NULL ,NULL , ib_size_dw *4 , +AMDGPU_IB_POOL_DIRECT , &job);if (r)return r;
@@ -276,7 +276,7 @@ err:* * Close up a stream for HW test or if userspace failed to do so */ -static int uvd_v7_0_enc_get_destroy_msg (struct amdgpu_ring *ring,uint32_t handle, +static int uvd_v7_0_enc_get_destroy_msg (struct amdgpu_ring *ring,u32 handle,struct amdgpu_bo *bo,struct dma_fence **fence) {
@@ -287,8 +287,8 @@ static int uvd_v7_0_enc_get_destroy_msg(uint64_t addr;int i, r; - r =amdgpu_job_alloc_with_ib (ring->adev, ib_size_dw *4 , -AMDGPU_IB_POOL_DIRECT , &job); + r =amdgpu_job_alloc_with_ib (ring->adev,NULL ,NULL , ib_size_dw *4 , +AMDGPU_IB_POOL_DIRECT , &job);if (r)return r;
drivers/gpu/drm/amd/amdkfd/kfd_migrate.c +6 -11
@@ -65,8 +65,11 @@ svm_migrate_gart_map(struct amdgpu_ring num_dw =ALIGN (adev->mman.buffer_funcs->copy_num_dw,8 ); num_bytes = npages *8 ; - r =amdgpu_job_alloc_with_ib (adev, num_dw *4 + num_bytes, -AMDGPU_IB_POOL_DELAYED , &job); + r =amdgpu_job_alloc_with_ib (adev, &adev->mman.entity, +AMDGPU_FENCE_OWNER_UNDEFINED , + num_dw *4 + num_bytes, +AMDGPU_IB_POOL_DELAYED , + &job);if (r)return r;
@@ -89,18 +92,10 @@ svm_migrate_gart_map(struct amdgpu_ring cpu_addr = &job->ibs[0 ].ptr[num_dw];amdgpu_gart_map (adev,0 , npages, addr, pte_flags, cpu_addr); - r =amdgpu_job_submit (job, &adev->mman.entity, -AMDGPU_FENCE_OWNER_UNDEFINED , &fence); -if (r) - goto error_free; - + fence =amdgpu_job_submit (job);dma_fence_put (fence);return r; - -error_free: -amdgpu_job_free (job); -return r; }/**
Greg Kroah-Hartman
maintainerPATCH 593/634 drm/amdgpu: add missing lock to amdgpu_ttm_access_memory_sdma
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pierre-Eric Pelloux-Prayer <[email protected]>
[ Upstream commit 4fa944255be521b1bbd9780383f77206303a3a5c ]
Users of ttm entities need to hold the gtt_window_lock before using them to guarantee proper ordering of jobs.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +2 -0
@@ -1425,6 +1425,7 @@ static int amdgpu_ttm_access_memory_sdmaif (r) goto out; +mutex_lock (&adev->mman.gtt_window_lock);amdgpu_res_first (abo->tbo.resource, offset, len, &src_mm); src_addr =amdgpu_ttm_domain_start (adev, bo->resource->mem_type) + src_mm.start;
@@ -1439,6 +1440,7 @@ static int amdgpu_ttm_access_memory_sdmaWARN_ON (job->ibs[0 ].length_dw > num_dw); fence =amdgpu_job_submit (job); +mutex_unlock (&adev->mman.gtt_window_lock);if (!dma_fence_wait_timeout (fence, false, adev->sdma_timeout)) r = -ETIMEDOUT ;
Greg Kroah-Hartman
maintainerPATCH 594/634 drm/gma500: Remove unused helper psb_fbdev_fb_setcolreg()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Zimmermann <[email protected]>
[ Upstream commit be729f9de6c64240645dc80a24162ac4d3fe00a8 ]
Remove psb_fbdev_fb_setcolreg(), which hasn't been called in almost a decade.
Gma500 commit 4d8d096e9ae8 ("gma500: introduce the framebuffer support code") added the helper psb_fbdev_fb_setcolreg() for setting the fbdev palette via fbdev's fb_setcolreg callback. Later
commit 3da6c2f3b730 ("drm/gma500: use DRM_FB_HELPER_DEFAULT_OPS for fb_ops") set several default helpers for fbdev emulation, including fb_setcmap.
The fbdev subsystem always prefers fb_setcmap over fb_setcolreg. [1] Hence, the gma500 code is no longer in use and gma500 has been using drm_fb_helper_setcmap() for several years without issues.
--- drivers/gpu/drm/gma500/framebuffer.c | 42 ----------------------------------- 1 file changed, 42 deletions(-)
drivers/gpu/drm/gma500/framebuffer.c +0 -42
@@ -35,47 +35,6 @@ static const struct drm_framebuffer_func .create_handle = drm_gem_fb_create_handle, }; -#define CMAP_TOHW (_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16) - -static int psbfb_setcolreg (unsigned regno,unsigned red,unsigned green, -unsigned blue,unsigned transp, -struct fb_info *info) -{ -struct drm_fb_helper *fb_helper = info->par; -struct drm_framebuffer *fb = fb_helper->fb; -uint32_t v; - -if (!fb) -return -ENOMEM ; - -if (regno >255 ) -return 1 ; - - red =CMAP_TOHW (red, info->var.red.length); - blue =CMAP_TOHW (blue, info->var.blue.length); - green =CMAP_TOHW (green, info->var.green.length); - transp =CMAP_TOHW (transp, info->var.transp.length); - - v = (red << info->var.red.offset) | - (green << info->var.green.offset) | - (blue << info->var.blue.offset) | - (transp << info->var.transp.offset); - -if (regno <16 ) { -switch (fb->format->cpp[0 ] *8 ) { -case 16 : - ((uint32_t *) info->pseudo_palette)[regno] = v; -break ; -case 24 : -case 32 : - ((uint32_t *) info->pseudo_palette)[regno] = v; -break ; - } - } - -return 0 ; -} -static vm_fault_t psbfb_vm_fault (struct vm_fault *vmf) {struct vm_area_struct *vma = vmf->vma;
@@ -146,7 +105,6 @@ static int psbfb_mmap(struct fb_info *instatic const struct fb_ops psbfb_unaccel_ops = { .owner =THIS_MODULE ,DRM_FB_HELPER_DEFAULT_OPS , - .fb_setcolreg = psbfb_setcolreg, .fb_fillrect = drm_fb_helper_cfb_fillrect, .fb_copyarea = drm_fb_helper_cfb_copyarea, .fb_imageblit = drm_fb_helper_cfb_imageblit,
Greg Kroah-Hartman
maintainerPATCH 595/634 net: Remove RTNL dance for SIOCBRADDIF and SIOCBRDELIF.
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thadeu Lima de Souza Cascardo <[email protected]>
commit ed3ba9b6e280e14cc3148c1b226ba453f02fa76c upstream.
SIOCBRDELIF is passed to dev_ioctl() first and later forwarded to br_ioctl_call(), which causes unnecessary RTNL dance and the splat below [0] under RTNL pressure.
Let's say Thread A is trying to detach a device from a bridge and Thread B is trying to remove the bridge.
In dev_ioctl(), Thread A bumps the bridge device's refcnt by netdev_hold() and releases RTNL because the following br_ioctl_call() also re-acquires RTNL.
In the race window, Thread B could acquire RTNL and try to remove the bridge device. Then, rtnl_unlock() by Thread B will release RTNL and wait for netdev_put() by Thread A.
Thread A, however, must hold RTNL after the unlock in dev_ifsioc(), which may take long under RTNL pressure, resulting in the splat by Thread B.
Thread A (SIOCBRDELIF) Thread B (SIOCBRDELBR)
---------------------- ----------------------
sock_ioctl sock_ioctl
`- sock_do_ioctl `- br_ioctl_call
`- dev_ioctl `- br_ioctl_stub
|- rtnl_lock |
|- dev_ifsioc '
' |- dev = __dev_get_by_name(...)
|- netdev_hold(dev, ...) .
/ |- rtnl_unlock ------. |
| |- br_ioctl_call `---> |- rtnl_lock
Race | | `- br_ioctl_stub |- br_del_bridge
Window | | | |- dev = __dev_get_by_name(...)
| | | May take long | `- br_dev_delete(dev, ...)
| | | under RTNL pressure | `- unregister_netdevice_queue(dev, ...)
| | | | `- rtnl_unlock
\ | |- rtnl_lock <-' `- netdev_run_todo
| |- ... `- netdev_run_todo
| `- rtnl_unlock |- __rtnl_unlock
| |- netdev_wait_allrefs_any
|- netdev_put(dev, ...) <----------------'Wait refcnt decrement and log splat below
To avoid blocking SIOCBRDELBR unnecessarily, let's not call dev_ioctl() for SIOCBRADDIF and SIOCBRDELIF.
In the dev_ioctl() path, we do the following:
1. Copy struct ifreq by get_user_ifreq in sock_do_ioctl()
2. Check CAP_NET_ADMIN in dev_ioctl()
3. Call dev_load() in dev_ioctl()
4. Fetch the master dev from ifr.ifr_name in dev_ifsioc()
3. can be done by request_module() in br_ioctl_call(), so we move 1., 2., and 4. to br_ioctl_stub().
Note that 2. is also checked later in add_del_if(), but it's better performed before RTNL.
SIOCBRADDIF and SIOCBRDELIF have been processed in dev_ioctl() since the pre-git era, and there seems to be no specific reason to process them there.
[0]:unregister_netdevice: waiting for wpan3 to become free. Usage count = 2ref_tracker: wpan3@ffff8880662d8608 has 1/1 users at
__netdev_tracker_alloc include/linux/netdevice.h:4282 [inline]
netdev_hold include/linux/netdevice.h:4311 [inline]
dev_ifsioc+0xc6a/0x1160 net/core/dev_ioctl.c:624
dev_ioctl+0x255/0x10c0 net/core/dev_ioctl.c:826
sock_do_ioctl+0x1ca/0x260 net/socket.c:1213
sock_ioctl+0x23a/0x6c0 net/socket.c:1318
vfs_ioctl fs/ioctl.c:51 [inline]
__do_sys_ioctl fs/ioctl.c:906 [inline]
__se_sys_ioctl fs/ioctl.c:892 [inline]
__x64_sys_ioctl+0x1a4/0x210 fs/ioctl.c:892
do_syscall_x64 arch/x86/entry/common.c:52 [inline]
do_syscall_64+0xcb/0x250 arch/x86/entry/common.c:83
entry_SYSCALL_64_after_hwframe+0x77/0x7f--- include/linux/if_bridge.h | 6 ++---- net/bridge/br_ioctl.c | 36 +++++++++++++++++++++++++++++++++--- net/bridge/br_private.h | 3 +-- net/core/dev_ioctl.c | 16 ---------------- net/socket.c | 19 +++++++++---------- 5 files changed, 45 insertions(+), 35 deletions(-)
include/linux/if_bridge.h +2 -4
@@ -63,11 +63,9 @@ struct br_ip_list {#define BR_DEFAULT_AGEING_TIME (300 * HZ)struct net_bridge ; -void brioctl_set (int (*hook)(struct net *net,struct net_bridge *br, -unsigned int cmd,struct ifreq *ifr, +void brioctl_set (int (*hook)(struct net *net,unsigned int cmd,void __user *uarg)); -int br_ioctl_call (struct net *net,struct net_bridge *br,unsigned int cmd, -struct ifreq *ifr,void __user *uarg); +int br_ioctl_call (struct net *net,unsigned int cmd,void __user *uarg);#if IS_ENABLED (CONFIG_BRIDGE ) &&IS_ENABLED (CONFIG_BRIDGE_IGMP_SNOOPING ) int br_multicast_list_adjacent(struct net_device *dev,
net/bridge/br_ioctl.c +33 -3
@@ -394,10 +394,26 @@ static int old_deviceless(struct net *nereturn -EOPNOTSUPP ; } -int br_ioctl_stub (struct net *net,struct net_bridge *br,unsigned int cmd, -struct ifreq *ifr,void __user *uarg) +int br_ioctl_stub (struct net *net,unsigned int cmd,void __user *uarg) {int ret = -EOPNOTSUPP ; +struct ifreq ifr; + +if (cmd ==SIOCBRADDIF || cmd ==SIOCBRDELIF ) { +void __user *data; +char *colon; + +if (!ns_capable (net->user_ns,CAP_NET_ADMIN )) +return -EPERM ; + +if (get_user_ifreq (&ifr, &data, uarg)) +return -EFAULT ; + + ifr.ifr_name[IFNAMSIZ -1 ] =0 ; + colon =strchr (ifr.ifr_name,':' ); +if (colon) + *colon =0 ; + }rtnl_lock ();
@@ -430,7 +446,21 @@ int br_ioctl_stub(struct net *net, strucbreak ;case SIOCBRADDIF :case SIOCBRDELIF : - ret =add_del_if (br, ifr->ifr_ifindex, cmd ==SIOCBRADDIF ); + { +struct net_device *dev; + + dev =__dev_get_by_name (net, ifr.ifr_name); +if (!dev || !netif_device_present (dev)) { + ret = -ENODEV ; +break ; + } +if (!netif_is_bridge_master (dev)) { + ret = -EOPNOTSUPP ; +break ; + } + + ret =add_del_if (netdev_priv (dev), ifr.ifr_ifindex, cmd ==SIOCBRADDIF ); + }break ; }
net/bridge/br_private.h +1 -2
@@ -895,8 +895,7 @@ br_port_get_check_rtnl(const struct net_/* br_ioctl.c */ int br_dev_siocdevprivate (struct net_device *dev,struct ifreq *rq,void __user *data,int cmd); -int br_ioctl_stub (struct net *net,struct net_bridge *br,unsigned int cmd, -struct ifreq *ifr,void __user *uarg); +int br_ioctl_stub (struct net *net,unsigned int cmd,void __user *uarg);/* br_multicast.c */ #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
net/core/dev_ioctl.c +0 -16
@@ -315,7 +315,6 @@ static int dev_ifsioc(struct net *net, sint err;struct net_device *dev =__dev_get_by_name (net, ifr->ifr_name);const struct net_device_ops *ops; -netdevice_tracker dev_tracker;if (!dev)return -ENODEV ;
@@ -378,19 +377,6 @@ static int dev_ifsioc(struct net *net, scase SIOCWANDEV :return dev_siocwandev (dev, &ifr->ifr_settings); -case SIOCBRADDIF : -case SIOCBRDELIF : -if (!netif_device_present (dev)) -return -ENODEV ; -if (!netif_is_bridge_master (dev)) -return -EOPNOTSUPP ; -netdev_hold (dev, &dev_tracker,GFP_KERNEL ); -rtnl_unlock (); - err =br_ioctl_call (net,netdev_priv (dev), cmd, ifr,NULL ); -netdev_put (dev, &dev_tracker); -rtnl_lock (); -return err; -case SIOCSHWTSTAMP : err =net_hwtstamp_validate (ifr);if (err)
@@ -575,8 +561,6 @@ int dev_ioctl(struct net *net, unsignedcase SIOCBONDRELEASE :case SIOCBONDSETHWADDR :case SIOCBONDCHANGEACTIVE : -case SIOCBRADDIF : -case SIOCBRDELIF :case SIOCSHWTSTAMP :if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ;
net/socket.c +9 -10
@@ -1151,12 +1151,10 @@ static ssize_t sock_write_iter(struct ki*/ static DEFINE_MUTEX (br_ioctl_mutex); -static int (*br_ioctl_hook)(struct net *net,struct net_bridge *br, -unsigned int cmd,struct ifreq *ifr, +static int (*br_ioctl_hook)(struct net *net,unsigned int cmd,void __user *uarg); -void brioctl_set (int (*hook)(struct net *net,struct net_bridge *br, -unsigned int cmd,struct ifreq *ifr, +void brioctl_set (int (*hook)(struct net *net,unsigned int cmd,void __user *uarg)) {mutex_lock (&br_ioctl_mutex);
@@ -1165,8 +1163,7 @@ void brioctl_set(int (*hook)(struct net }EXPORT_SYMBOL (brioctl_set); -int br_ioctl_call (struct net *net,struct net_bridge *br,unsigned int cmd, -struct ifreq *ifr,void __user *uarg) +int br_ioctl_call (struct net *net,unsigned int cmd,void __user *uarg) {int err = -ENOPKG ;
@@ -1175,7 +1172,7 @@ int br_ioctl_call(struct net *net, strucmutex_lock (&br_ioctl_mutex);if (br_ioctl_hook) - err =br_ioctl_hook (net, br, cmd, ifr, uarg); + err =br_ioctl_hook (net, cmd, uarg);mutex_unlock (&br_ioctl_mutex);return err;
@@ -1272,7 +1269,9 @@ static long sock_ioctl(struct file *filecase SIOCSIFBR :case SIOCBRADDBR :case SIOCBRDELBR : - err =br_ioctl_call (net,NULL , cmd,NULL , argp); +case SIOCBRADDIF : +case SIOCBRDELIF : + err =br_ioctl_call (net, cmd, argp);break ;case SIOCGIFVLAN :case SIOCSIFVLAN :
@@ -3376,6 +3375,8 @@ static int compat_sock_ioctl_trans(struccase SIOCGPGRP :case SIOCBRADDBR :case SIOCBRDELBR : +case SIOCBRADDIF : +case SIOCBRDELIF :case SIOCGIFVLAN :case SIOCSIFVLAN :case SIOCGSKNS :
@@ -3415,8 +3416,6 @@ static int compat_sock_ioctl_trans(struccase SIOCGIFPFLAGS :case SIOCGIFTXQLEN :case SIOCSIFTXQLEN : -case SIOCBRADDIF : -case SIOCBRDELIF :case SIOCGIFNAME :case SIOCSIFNAME :case SIOCGMIIPHY :
Greg Kroah-Hartman
maintainerPATCH 596/634 serial: Make uart_remove_one_port() return void
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uwe Kleine-König <[email protected]>
[ Upstream commit d5b3d02d0b107345f2a6ecb5b06f98356f5c97ab ]
The return value is only ever used as a return value for remove callbacks of platform drivers. This return value is ignored by the driver core. (The only effect is an error message, but uart_remove_one_port() already emitted one in this case.)
So the return value isn't used at all and uart_remove_one_port() can be changed to return void without any loss. Also this better matches the Linux device model as remove functions are not supposed to fail.
Stable-dep-of: 74098cc06e75 ("xhci: dbgtty: fix device unregister: fixup")
--- drivers/tty/serial/atmel_serial.c | 5 ++--- drivers/tty/serial/clps711x.c | 4 +++- drivers/tty/serial/cpm_uart/cpm_uart_core.c | 5 ++++- drivers/tty/serial/imx.c | 4 +++- drivers/tty/serial/lantiq.c | 4 +++- drivers/tty/serial/serial_core.c | 6 +----- drivers/tty/serial/st-asc.c | 4 +++- drivers/tty/serial/uartlite.c | 12 ++++-------- drivers/tty/serial/xilinx_uartps.c | 5 ++--- include/linux/serial_core.h | 2 +- 10 files changed, 26 insertions(+), 25 deletions(-)
drivers/tty/serial/atmel_serial.c +2 -3
@@ -3022,14 +3022,13 @@ static int atmel_serial_remove(struct pl {struct uart_port *port =platform_get_drvdata (pdev);struct atmel_uart_port *atmel_port =to_atmel_uart_port (port); -int ret =0 ;tasklet_kill (&atmel_port->tasklet_rx);tasklet_kill (&atmel_port->tasklet_tx);device_init_wakeup (&pdev->dev,0 ); - ret =uart_remove_one_port (&atmel_uart, port); +uart_remove_one_port (&atmel_uart, port);kfree (atmel_port->rx_ring.buf);
@@ -3039,7 +3038,7 @@ static int atmel_serial_remove(struct pl pdev->dev.of_node =NULL ; -return ret; +return 0 ; } static SIMPLE_DEV_PM_OPS(atmel_serial_pm_ops, atmel_serial_suspend,
drivers/tty/serial/clps711x.c +3 -1
@@ -515,7 +515,9 @@ static int uart_clps711x_remove(struct p {struct clps711x_port *s =platform_get_drvdata (pdev); -return uart_remove_one_port (&clps711x_uart, &s->port); +uart_remove_one_port (&clps711x_uart, &s->port); + +return 0 ; }static const struct of_device_id __maybe_unused clps711x_uart_dt_ids[] = {
drivers/tty/serial/cpm_uart/cpm_uart_core.c +4 -1
@@ -1428,7 +1428,10 @@ static int cpm_uart_probe(struct platforstatic int cpm_uart_remove (struct platform_device *ofdev) {struct uart_cpm_port *pinfo =platform_get_drvdata (ofdev); -return uart_remove_one_port (&cpm_reg, &pinfo->port); + +uart_remove_one_port (&cpm_reg, &pinfo->port); + +return 0 ; }static const struct of_device_id cpm_uart_match[] = {
drivers/tty/serial/imx.c +3 -1
@@ -2538,7 +2538,9 @@ static int imx_uart_remove(struct platfo {struct imx_port *sport =platform_get_drvdata (pdev); -return uart_remove_one_port (&imx_uart_uart_driver, &sport->port); +uart_remove_one_port (&imx_uart_uart_driver, &sport->port); + +return 0 ; }static void imx_uart_restore_context (struct imx_port *sport)
drivers/tty/serial/lantiq.c +3 -1
@@ -918,7 +918,9 @@ static int lqasc_remove(struct platform_ {struct uart_port *port =platform_get_drvdata (pdev); -return uart_remove_one_port (&lqasc_reg, port); +uart_remove_one_port (&lqasc_reg, port); + +return 0 ; }static const struct ltq_soc_data soc_data_lantiq = {
drivers/tty/serial/serial_core.c +1 -5
@@ -3186,13 +3186,12 @@ EXPORT_SYMBOL(uart_add_one_port);* This unhooks (and hangs up) the specified port structure from the core * driver. No further calls will be made to the low-level code for this port. */ -int uart_remove_one_port (struct uart_driver *drv,struct uart_port *uport) +void uart_remove_one_port (struct uart_driver *drv,struct uart_port *uport) {struct uart_state *state = drv->state + uport->line;struct tty_port *port = &state->port;struct uart_port *uart_port;struct tty_struct *tty; -int ret =0 ;mutex_lock (&port_mutex);
@@ -3208,7 +3207,6 @@ int uart_remove_one_port(struct uart_driif (!uart_port) {mutex_unlock (&port->mutex); - ret = -EINVAL ; goto out; } uport->flags |=UPF_DEAD ;
@@ -3251,8 +3249,6 @@ int uart_remove_one_port(struct uart_drimutex_unlock (&port->mutex); out:mutex_unlock (&port_mutex); - -return ret; }EXPORT_SYMBOL (uart_remove_one_port);
drivers/tty/serial/st-asc.c +3 -1
@@ -834,7 +834,9 @@ static int asc_serial_remove(struct plat {struct uart_port *port =platform_get_drvdata (pdev); -return uart_remove_one_port (&asc_uart_driver, port); +uart_remove_one_port (&asc_uart_driver, port); + +return 0 ; }#ifdef CONFIG_PM_SLEEP
drivers/tty/serial/uartlite.c +4 -8
@@ -686,18 +686,15 @@ static int ulite_assign(struct device *d* * @dev: pointer to device structure */ -static int ulite_release (struct device *dev) +static void ulite_release (struct device *dev) {struct uart_port *port =dev_get_drvdata (dev); -int rc =0 ;if (port) { - rc =uart_remove_one_port (&ulite_uart_driver, port); +uart_remove_one_port (&ulite_uart_driver, port);dev_set_drvdata (dev,NULL ); port->mapbase =0 ; } - -return rc; }/**
@@ -891,14 +888,13 @@ static int ulite_remove(struct platform_ {struct uart_port *port =dev_get_drvdata (&pdev->dev);struct uartlite_data *pdata = port->private_data; -int rc;clk_disable_unprepare (pdata->clk); - rc =ulite_release (&pdev->dev); +ulite_release (&pdev->dev);pm_runtime_disable (&pdev->dev);pm_runtime_set_suspended (&pdev->dev);pm_runtime_dont_use_autosuspend (&pdev->dev); -return rc; +return 0 ; }/* work with hotplug and coldplug */
drivers/tty/serial/xilinx_uartps.c +2 -3
@@ -1670,14 +1670,13 @@ static int cdns_uart_remove(struct platf {struct uart_port *port =platform_get_drvdata (pdev);struct cdns_uart *cdns_uart_data = port->private_data; -int rc;/* Remove the cdns_uart port from the serial core */ #ifdef CONFIG_COMMON_CLK clk_notifier_unregister (cdns_uart_data->uartclk, &cdns_uart_data->clk_rate_change_nb);#endif - rc =uart_remove_one_port (cdns_uart_data->cdns_uart_driver, port); +uart_remove_one_port (cdns_uart_data->cdns_uart_driver, port); port->mapbase =0 ;clk_disable_unprepare (cdns_uart_data->uartclk);clk_disable_unprepare (cdns_uart_data->pclk);
@@ -1693,7 +1692,7 @@ static int cdns_uart_remove(struct platfif (!--instances)uart_unregister_driver (cdns_uart_data->cdns_uart_driver); -return rc; +return 0 ; }static struct platform_driver cdns_uart_platform_driver = {
include/linux/serial_core.h +1 -1
@@ -847,7 +847,7 @@ void uart_console_write(struct uart_portint uart_register_driver (struct uart_driver *uart);void uart_unregister_driver (struct uart_driver *uart);int uart_add_one_port (struct uart_driver *reg,struct uart_port *port); -int uart_remove_one_port (struct uart_driver *reg,struct uart_port *port); +void uart_remove_one_port (struct uart_driver *reg,struct uart_port *port);bool uart_match_port (const struct uart_port *port1,const struct uart_port *port2);
Greg Kroah-Hartman
maintainerPATCH 597/634 tty: introduce and use tty_port_tty_vhangup() helper
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: "Jiri Slaby (SUSE)" <[email protected]>
[ Upstream commit 2b5eac0f8c6e79bc152c8804f9f88d16717013ab ]
This code (tty_get -> vhangup -> tty_put) is repeated on few places. Introduce a helper similar to tty_port_tty_hangup() (asynchronous) to handle even vhangup (synchronous).
And use it on those places.
In fact, reuse the tty_port_tty_hangup()'s code and call tty_vhangup() depending on a new bool parameter.
Stable-dep-of: 74098cc06e75 ("xhci: dbgtty: fix device unregister: fixup")
--- drivers/isdn/capi/capi.c | 8 +------- drivers/staging/greybus/uart.c | 7 +------ drivers/tty/serial/serial_core.c | 7 +------ drivers/tty/tty_port.c | 12 ++++++++---- drivers/usb/class/cdc-acm.c | 7 +------ drivers/usb/serial/usb-serial.c | 7 +------ include/linux/tty_port.h | 12 +++++++++++- net/bluetooth/rfcomm/tty.c | 7 +------ 8 files changed, 25 insertions(+), 42 deletions(-)
drivers/isdn/capi/capi.c +1 -7
@@ -304,15 +304,9 @@ static void capincci_alloc_minor(structstatic void capincci_free_minor (struct capincci *np) {struct capiminor *mp = np->minorp; -struct tty_struct *tty;if (mp) { - tty =tty_port_tty_get (&mp->port); -if (tty) { -tty_vhangup (tty); -tty_kref_put (tty); - } - +tty_port_tty_vhangup (&mp->port);capiminor_free (mp); } }
drivers/staging/greybus/uart.c +1 -6
@@ -915,7 +915,6 @@ static void gb_uart_remove(struct gbphy_ {struct gb_tty *gb_tty =gb_gbphy_get_data (gbphy_dev);struct gb_connection *connection = gb_tty->connection; -struct tty_struct *tty;int ret; ret =gbphy_runtime_get_sync (gbphy_dev);
@@ -928,11 +927,7 @@ static void gb_uart_remove(struct gbphy_wake_up_all (&gb_tty->wioctl);mutex_unlock (&gb_tty->mutex); - tty =tty_port_tty_get (&gb_tty->port); -if (tty) { -tty_vhangup (tty); -tty_kref_put (tty); - } +tty_port_tty_vhangup (&gb_tty->port);gb_connection_disable_rx (connection);tty_unregister_device (gb_tty_driver, gb_tty->minor);
drivers/tty/serial/serial_core.c +1 -6
@@ -3191,7 +3191,6 @@ void uart_remove_one_port(struct uart_drstruct uart_state *state = drv->state + uport->line;struct tty_port *port = &state->port;struct uart_port *uart_port; -struct tty_struct *tty;mutex_lock (&port_mutex);
@@ -3217,11 +3216,7 @@ void uart_remove_one_port(struct uart_dr*/ tty_port_unregister_device (port, drv->tty_driver, uport->line); - tty =tty_port_tty_get (port); -if (tty) { -tty_vhangup (port->tty); -tty_kref_put (tty); - } +tty_port_tty_vhangup (port);/* * If the port is used as a console, unregister it
drivers/tty/tty_port.c +8 -4
@@ -416,15 +416,19 @@ EXPORT_SYMBOL(tty_port_hangup);* @port: tty port * @check_clocal: hang only ttys with %CLOCAL unset? */ -void tty_port_tty_hangup (struct tty_port *port,bool check_clocal) +void __tty_port_tty_hangup (struct tty_port *port,bool check_clocal,bool async) {struct tty_struct *tty =tty_port_tty_get (port); -if (tty && (!check_clocal || !C_CLOCAL (tty))) -tty_hangup (tty); +if (tty && (!check_clocal || !C_CLOCAL (tty))) { +if (async) +tty_hangup (tty); +else +tty_vhangup (tty); + }tty_kref_put (tty); } -EXPORT_SYMBOL_GPL (tty_port_tty_hangup); +EXPORT_SYMBOL_GPL (__tty_port_tty_hangup);/** * tty_port_tty_wakeup - helper to wake up a tty
drivers/usb/class/cdc-acm.c +1 -6
@@ -1548,7 +1548,6 @@ err_put_port:static void acm_disconnect (struct usb_interface *intf) {struct acm *acm =usb_get_intfdata (intf); -struct tty_struct *tty;int i;/* sibling interface is already cleaning up */
@@ -1575,11 +1574,7 @@ static void acm_disconnect(struct usb_inusb_set_intfdata (acm->data,NULL );mutex_unlock (&acm->mutex); - tty =tty_port_tty_get (&acm->port); -if (tty) { -tty_vhangup (tty); -tty_kref_put (tty); - } +tty_port_tty_vhangup (&acm->port);cancel_delayed_work_sync (&acm->dwork);
drivers/usb/serial/usb-serial.c +1 -6
@@ -1179,7 +1179,6 @@ static void usb_serial_disconnect(structstruct usb_serial *serial =usb_get_intfdata (interface);struct device *dev = &interface->dev;struct usb_serial_port *port; -struct tty_struct *tty;/* sibling interface is cleaning up */ if (!serial)
@@ -1194,11 +1193,7 @@ static void usb_serial_disconnect(structfor (i =0 ; i < serial->num_ports; ++i) { port = serial->port[i]; - tty =tty_port_tty_get (&port->port); -if (tty) { -tty_vhangup (tty); -tty_kref_put (tty); - } +tty_port_tty_vhangup (&port->port);usb_serial_port_poison_urbs (port);wake_up_interruptible (&port->port.delta_msr_wait);cancel_work_sync (&port->work);
include/linux/tty_port.h +11 -1
@@ -234,7 +234,7 @@ int tty_port_carrier_raised(struct tty_pvoid tty_port_raise_dtr_rts (struct tty_port *port);void tty_port_lower_dtr_rts (struct tty_port *port);void tty_port_hangup (struct tty_port *port); -void tty_port_tty_hangup (struct tty_port *port,bool check_clocal); +void __tty_port_tty_hangup (struct tty_port *port,bool check_clocal,bool async);void tty_port_tty_wakeup (struct tty_port *port);int tty_port_block_til_ready (struct tty_port *port,struct tty_struct *tty,struct file *filp);
@@ -253,4 +253,14 @@ static inline int tty_port_users(struct return port->count + port->blocked_open; } +static inline void tty_port_tty_hangup (struct tty_port *port,bool check_clocal) +{ +__tty_port_tty_hangup (port, check_clocal, true); +} + +static inline void tty_port_tty_vhangup (struct tty_port *port) +{ +__tty_port_tty_hangup (port, false, false); +} +#endif
net/bluetooth/rfcomm/tty.c +1 -6
@@ -438,7 +438,6 @@ static int __rfcomm_release_dev(void __u {struct rfcomm_dev_req req;struct rfcomm_dev *dev; -struct tty_struct *tty;if (copy_from_user (&req, arg,sizeof (req)))return -EFAULT ;
@@ -464,11 +463,7 @@ static int __rfcomm_release_dev(void __urfcomm_dlc_close (dev->dlc,0 );/* Shut down TTY synchronously before freeing rfcomm_dev */ - tty =tty_port_tty_get (&dev->port); -if (tty) { -tty_vhangup (tty); -tty_kref_put (tty); - } +tty_port_tty_vhangup (&dev->port);if (!test_bit (RFCOMM_TTY_OWNED , &dev->status))tty_port_put (&dev->port);
Greg Kroah-Hartman
maintainerPATCH 598/634 xhci: dbgtty: fix device unregister: fixup
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Łukasz Bartosik <[email protected]>
[ Upstream commit 74098cc06e753d3ffd8398b040a3a1dfb65260c0 ]
This fixup replaces tty_vhangup() call with call to tty_port_tty_vhangup(). Both calls hangup tty device synchronously however tty_port_tty_vhangup() increases reference count during the hangup operation using scoped_guard(tty_port_tty).
--- drivers/usb/host/xhci-dbgtty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/host/xhci-dbgtty.c +1 -1
@@ -523,7 +523,7 @@ static void xhci_dbc_tty_unregister_devi* Hang up the TTY. This wakes up any blocked * writers and causes subsequent writes to fail. */ -tty_vhangup (port->port.tty); +tty_port_tty_vhangup (&port->port);tty_unregister_device (dbc_tty_driver, port->minor);xhci_dbc_tty_exit_port (port);
Greg Kroah-Hartman
maintainerPATCH 599/634 NFSD: NFSv4 file creation neglects setting ACL
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 913f7cf77bf14c13cfea70e89bcb6d0b22239562 ]
An NFSv4 client that sets an ACL with a named principal during file creation retrieves the ACL afterwards, and finds that it is only a default ACL (based on the mode bits) and not the ACL that was requested during file creation. This violates RFC 8881 section 6.4.1.3: "the ACL attribute is set as given".
The issue occurs in nfsd_create_setattr(). On 6.1.y, the check to determine whether nfsd_setattr() should be called is simply "iap->ia_valid", which only accounts for iattr changes. When only an ACL is present (and no iattr fields are set), nfsd_setattr() is skipped and the POSIX ACL is never applied to the inode.
Subsequently, when the client retrieves the ACL, the server finds no POSIX ACL on the inode and returns one generated from the file's mode bits rather than returning the originally-specified ACL.
--- fs/nfsd/vfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nfsd/vfs.c +1 -1
@@ -1320,7 +1320,7 @@ nfsd_create_setattr(struct svc_rqst *rqs* Callers expect new file metadata to be committed even * if the attributes have not changed. */ -if (iap->ia_valid) +if (iap->ia_valid || attrs->na_pacl || attrs->na_dpacl) status =nfsd_setattr (rqstp, resfhp, attrs,0 , (time64_t )0 );else status =nfserrno (commit_metadata (resfhp));
Greg Kroah-Hartman
maintainerPATCH 600/634 iommu/arm-smmu: Drop if with an always false condition
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uwe Kleine-König <[email protected]>
[ Upstream commit a2972cb89935160bfe515b15d28a77694723ac06 ]
The remove and shutdown callback are only called after probe completed successfully. In this case platform_set_drvdata() was called with a non-NULL argument and so smmu is never NULL. Other functions in this driver also don't check for smmu being non-NULL before using it.
Also note that returning an error code from a remove callback doesn't result in the device staying bound. It's still removed and devm allocated resources are freed (among others *smmu and the register mapping). So after an early exit to iommu device stayed around and using it probably oopses.
Stable-dep-of: 6a3908ce56e6 ("iommu/qcom: fix device leak on of_xlate()")
--- drivers/iommu/arm/arm-smmu/arm-smmu.c | 6 ------ 1 file changed, 6 deletions(-)
drivers/iommu/arm/arm-smmu/arm-smmu.c +0 -6
@@ -2209,9 +2209,6 @@ static void arm_smmu_device_shutdown(str {struct arm_smmu_device *smmu =platform_get_drvdata (pdev); -if (!smmu) -return ; -if (!bitmap_empty (smmu->context_map,ARM_SMMU_MAX_CBS ))dev_notice (&pdev->dev,"disabling translation\n" );
@@ -2232,9 +2229,6 @@ static int arm_smmu_device_remove(struct {struct arm_smmu_device *smmu =platform_get_drvdata (pdev); -if (!smmu) -return -ENODEV ; -iommu_device_unregister (&smmu->iommu);iommu_device_sysfs_remove (&smmu->iommu);
Greg Kroah-Hartman
maintainerPATCH 601/634 iommu/arm-smmu: Convert to platform remove callback returning void
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uwe Kleine-König <[email protected]>
[ Upstream commit 62565a77c2323d32f2be737455729ac7d3efe6ad ]
The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void.
Trivially convert this driver from always returning zero in the remove callback to the void returning variant.
Stable-dep-of: 6a3908ce56e6 ("iommu/qcom: fix device leak on of_xlate()")
--- drivers/iommu/arm/arm-smmu/arm-smmu.c | 6 ++---- drivers/iommu/arm/arm-smmu/qcom_iommu.c | 12 ++++-------- 2 files changed, 6 insertions(+), 12 deletions(-)
drivers/iommu/arm/arm-smmu/arm-smmu.c +2 -4
@@ -2225,7 +2225,7 @@ static void arm_smmu_device_shutdown(strclk_bulk_unprepare (smmu->num_clks, smmu->clks); } -static int arm_smmu_device_remove (struct platform_device *pdev) +static void arm_smmu_device_remove (struct platform_device *pdev) {struct arm_smmu_device *smmu =platform_get_drvdata (pdev);
@@ -2233,8 +2233,6 @@ static int arm_smmu_device_remove(structiommu_device_sysfs_remove (&smmu->iommu);arm_smmu_device_shutdown (pdev); - -return 0 ; }static int __maybe_unused arm_smmu_runtime_resume (struct device *dev)
@@ -2310,7 +2308,7 @@ static struct platform_driver arm_smmu_d .suppress_bind_attrs = true, }, .probe = arm_smmu_device_probe, - .remove = arm_smmu_device_remove, + .remove_new = arm_smmu_device_remove, .shutdown = arm_smmu_device_shutdown, };module_platform_driver (arm_smmu_driver);
drivers/iommu/arm/arm-smmu/qcom_iommu.c +4 -8
@@ -715,7 +715,7 @@ static int qcom_iommu_ctx_probe(struct preturn 0 ; } -static int qcom_iommu_ctx_remove (struct platform_device *pdev) +static void qcom_iommu_ctx_remove (struct platform_device *pdev) {struct qcom_iommu_dev *qcom_iommu =dev_get_drvdata (pdev->dev.parent);struct qcom_iommu_ctx *ctx =platform_get_drvdata (pdev);
@@ -723,8 +723,6 @@ static int qcom_iommu_ctx_remove(structplatform_set_drvdata (pdev,NULL ); qcom_iommu->ctxs[ctx->asid -1 ] =NULL ; - -return 0 ; }static const struct of_device_id ctx_of_match[] = {
@@ -739,7 +737,7 @@ static struct platform_driver qcom_iommu .of_match_table = ctx_of_match, }, .probe = qcom_iommu_ctx_probe, - .remove = qcom_iommu_ctx_remove, + .remove_new = qcom_iommu_ctx_remove, };static bool qcom_iommu_has_secure_context (struct qcom_iommu_dev *qcom_iommu)
@@ -857,7 +855,7 @@ err_pm_disable:return ret; } -static int qcom_iommu_device_remove (struct platform_device *pdev) +static void qcom_iommu_device_remove (struct platform_device *pdev) {struct qcom_iommu_dev *qcom_iommu =platform_get_drvdata (pdev);
@@ -865,8 +863,6 @@ static int qcom_iommu_device_remove(struplatform_set_drvdata (pdev,NULL );iommu_device_sysfs_remove (&qcom_iommu->iommu);iommu_device_unregister (&qcom_iommu->iommu); - -return 0 ; }static int __maybe_unused qcom_iommu_resume (struct device *dev)
@@ -903,7 +899,7 @@ static struct platform_driver qcom_iommu .pm = &qcom_iommu_pm_ops, }, .probe = qcom_iommu_device_probe, - .remove = qcom_iommu_device_remove, + .remove_new = qcom_iommu_device_remove, };static int __init qcom_iommu_init (void )
Greg Kroah-Hartman
maintainerPATCH 602/634 iommu/qcom: Use the asid read from device-tree if specified
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: AngeloGioacchino Del Regno <[email protected]>
[ Upstream commit fcf226f1f7083cba76af47bf8dd764b68b149cd2 ]
As specified in this driver, the context banks are 0x1000 apart but on some SoCs the context number does not necessarily match this logic, hence we end up using the wrong ASID: keeping in mind that this IOMMU implementation relies heavily on SCM (TZ) calls, it is mandatory that we communicate the right context number.
Since this is all about how context banks are mapped in firmware, which may be board dependent (as a different firmware version may eventually change the expected context bank numbers), introduce a new property "qcom,ctx-asid": when found, the ASID will be forced as read from the devicetree.
When "qcom,ctx-asid" is not found, this driver retains the previous behavior as to avoid breaking older devicetrees or systems that do not require forcing ASID numbers.
Stable-dep-of: 6a3908ce56e6 ("iommu/qcom: fix device leak on of_xlate()")
--- drivers/iommu/arm/arm-smmu/qcom_iommu.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-)
drivers/iommu/arm/arm-smmu/qcom_iommu.c +15 -3
@@ -563,7 +563,8 @@ static int qcom_iommu_of_xlate(struct de* index into qcom_iommu->ctxs: */ if (WARN_ON (asid <1 ) || -WARN_ON (asid > qcom_iommu->num_ctxs)) { +WARN_ON (asid > qcom_iommu->num_ctxs) || +WARN_ON (qcom_iommu->ctxs[asid -1 ] ==NULL )) {put_device (&iommu_pdev->dev);return -EINVAL ; }
@@ -650,7 +651,8 @@ free_mem:static int get_asid (const struct device_node *np) { -u32 reg; +u32 reg, val; +int asid;/* read the "reg" property directly to get the relative address * of the context bank, and calculate the asid from that:
@@ -658,7 +660,17 @@ static int get_asid(const struct device_if (of_property_read_u32_index (np,"reg" ,0 , ®))return -ENODEV ; -return reg /0x1000 ;/* context banks are 0x1000 apart */ +/* +* Context banks are 0x1000 apart but, in some cases, the ASID +* number doesn't match to this logic and needs to be passed +* from the DT configuration explicitly. +*/ +if (!of_property_read_u32 (np,"qcom,ctx-asid" , &val)) + asid = val; +else + asid = reg /0x1000 ; + +return asid; }static int qcom_iommu_ctx_probe (struct platform_device *pdev)
Greg Kroah-Hartman
maintainerPATCH 603/634 iommu/qcom: Index contexts by asid number to allow asid 0
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: AngeloGioacchino Del Regno <[email protected]>
[ Upstream commit ec5601661bfcdc206e6ceba1b97837e763dab1ba ]
This driver was indexing the contexts by asid-1, which is probably done under the assumption that the first ASID is always 1. Unfortunately this is not always true: at least for MSM8956 and MSM8976's GPU IOMMU, the gpu_user context's ASID number is zero. To allow using a zero asid number, index the contexts by asid instead of by asid - 1.
While at it, also enhance human readability by renaming the num_ctxs member of struct qcom_iommu_dev to max_asid.
Stable-dep-of: 6a3908ce56e6 ("iommu/qcom: fix device leak on of_xlate()")
--- drivers/iommu/arm/arm-smmu/qcom_iommu.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-)
drivers/iommu/arm/arm-smmu/qcom_iommu.c +10 -12
@@ -51,8 +51,8 @@ struct qcom_iommu_dev {struct clk_bulk_data clks[CLK_NUM ];void __iomem *local_base;u32 sec_id; -u8 num_ctxs; -struct qcom_iommu_ctx *ctxs[];/* indexed by asid-1 */ +u8 max_asid; +struct qcom_iommu_ctx *ctxs[];/* indexed by asid */ };struct qcom_iommu_ctx {
@@ -94,7 +94,7 @@ static struct qcom_iommu_ctx * to_ctx(ststruct qcom_iommu_dev *qcom_iommu = d->iommu;if (!qcom_iommu)return NULL ; -return qcom_iommu->ctxs[asid -1 ]; +return qcom_iommu->ctxs[asid]; } static inline void
@@ -559,12 +559,10 @@ static int qcom_iommu_of_xlate(struct de qcom_iommu =platform_get_drvdata (iommu_pdev);/* make sure the asid specified in dt is valid, so we don't have -* to sanity check this elsewhere, since 'asid - 1' is used to -* index into qcom_iommu->ctxs: +* to sanity check this elsewhere: */ -if (WARN_ON (asid <1 ) || -WARN_ON (asid > qcom_iommu->num_ctxs) || -WARN_ON (qcom_iommu->ctxs[asid -1 ] ==NULL )) { +if (WARN_ON (asid > qcom_iommu->max_asid) || +WARN_ON (qcom_iommu->ctxs[asid] ==NULL )) {put_device (&iommu_pdev->dev);return -EINVAL ; }
@@ -722,7 +720,7 @@ static int qcom_iommu_ctx_probe(struct pdev_dbg (dev,"found asid %u\n" , ctx->asid); - qcom_iommu->ctxs[ctx->asid -1 ] = ctx; + qcom_iommu->ctxs[ctx->asid] = ctx;return 0 ; }
@@ -734,7 +732,7 @@ static void qcom_iommu_ctx_remove(structplatform_set_drvdata (pdev,NULL ); - qcom_iommu->ctxs[ctx->asid -1 ] =NULL ; + qcom_iommu->ctxs[ctx->asid] =NULL ; }static const struct of_device_id ctx_of_match[] = {
@@ -781,11 +779,11 @@ static int qcom_iommu_device_probe(strucfor_each_child_of_node (dev->of_node, child) max_asid =max (max_asid,get_asid (child)); - qcom_iommu =devm_kzalloc (dev,struct_size (qcom_iommu, ctxs, max_asid), + qcom_iommu =devm_kzalloc (dev,struct_size (qcom_iommu, ctxs, max_asid +1 ),GFP_KERNEL );if (!qcom_iommu)return -ENOMEM ; - qcom_iommu->num_ctxs = max_asid; + qcom_iommu->max_asid = max_asid; qcom_iommu->dev = dev; res =platform_get_resource (pdev,IORESOURCE_MEM ,0 );
Greg Kroah-Hartman
maintainerPATCH 604/634 iommu/qcom: fix device leak on of_xlate()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
[ Upstream commit 6a3908ce56e6879920b44ef136252b2f0c954194 ]
Make sure to drop the reference taken to the iommu platform device when looking up its driver data during of_xlate().
Note that commit e2eae09939a8 ("iommu/qcom: add missing put_device() call in qcom_iommu_of_xlate()") fixed the leak in a couple of error paths, but the reference is still leaking on success and late failures.
--- drivers/iommu/arm/arm-smmu/qcom_iommu.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
drivers/iommu/arm/arm-smmu/qcom_iommu.c +4 -6
@@ -558,14 +558,14 @@ static int qcom_iommu_of_xlate(struct de qcom_iommu =platform_get_drvdata (iommu_pdev); +put_device (&iommu_pdev->dev); +/* make sure the asid specified in dt is valid, so we don't have * to sanity check this elsewhere: */ if (WARN_ON (asid > qcom_iommu->max_asid) || -WARN_ON (qcom_iommu->ctxs[asid] ==NULL )) { -put_device (&iommu_pdev->dev); +WARN_ON (qcom_iommu->ctxs[asid] ==NULL ))return -EINVAL ; - }if (!dev_iommu_priv_get (dev)) {dev_iommu_priv_set (dev, qcom_iommu);
@@ -574,10 +574,8 @@ static int qcom_iommu_of_xlate(struct de* multiple different iommu devices. Multiple context * banks are ok, but multiple devices are not: */ -if (WARN_ON (qcom_iommu !=dev_iommu_priv_get (dev))) { -put_device (&iommu_pdev->dev); +if (WARN_ON (qcom_iommu !=dev_iommu_priv_get (dev)))return -EINVAL ; - } }return iommu_fwspec_add_ids (dev, &asid,1 );
Greg Kroah-Hartman
maintainerPATCH 605/634 virtio_console: fix order of fields cols and rows
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maximilian Immanuel Brandtner <[email protected]>
commit 5326ab737a47278dbd16ed3ee7380b26c7056ddd upstream.
According to section 5.3.6.2 (Multiport Device Operation) of the virtio spec(version 1.2) a control buffer with the event VIRTIO_CONSOLE_RESIZE is followed by a virtio_console_resize struct containing cols then rows. The kernel implements this the wrong way around (rows then cols) resulting in the two values being swapped.
Message-Id: <[email protected]>
--- drivers/char/virtio_console.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/char/virtio_console.c +1 -1
@@ -1615,8 +1615,8 @@ static void handle_control_message(strucbreak ;case VIRTIO_CONSOLE_RESIZE : {struct { -__virtio16 rows;__virtio16 cols; +__virtio16 rows; } size;if (!is_console_port (port))
Greg Kroah-Hartman
maintainerPATCH 606/634 KVM: arm64: sys_regs: disable -Wuninitialized-const-pointer warning
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Justin Stitt <[email protected]>
A new warning in Clang 22 [1] complains that @clidr passed to get_clidr_el1() is an uninitialized const pointer. get_clidr_el1() doesn't really care since it casts away the const-ness anyways -- it is a false positive.
This patch isn't needed for anything past 6.1 as this code section was reworked in Commit 7af0c2534f4c ("KVM: arm64: Normalize cache configuration") which incidentally removed the aforementioned warning. Since there is no upstream equivalent, this patch just needs to be applied to 6.1.
Disable this warning for sys_regs.o instead of backporting the patches from 6.2+ that modified this code area.
--- arch/arm64/kvm/Makefile | 3 +++ 1 file changed, 3 insertions(+)
arch/arm64/kvm/Makefile +3 -0
@@ -24,6 +24,9 @@ kvm-y += arm.o mmu.o mmio.o psci.o hyper kvm-$(CONFIG_HW_PERF_EVENTS) += pmu-emul.o pmu.o +# Work around a false positive Clang 22 -Wuninitialized-const-pointer warning +CFLAGS_sys_regs.o := $(call cc-disable-warning, uninitialized-const-pointer) + always-y := hyp_constants.h hyp-constants.s define rule_gen_hyp_constants
Greg Kroah-Hartman
maintainerPATCH 607/634 dmaengine: idxd: Remove improper idxd_free
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yi Sun <[email protected]>
[ Upstream commit f41c538881eec4dcf5961a242097d447f848cda6 ]
The call to idxd_free() introduces a duplicate put_device() leading to a reference count underflow:refcount_t: underflow; use-after-free.
WARNING: CPU: 15 PID: 4428 at lib/refcount.c:28 refcount_warn_saturate+0xbe/0x110 ... Call Trace: <TASK> idxd_remove+0xe4/0x120 [idxd] pci_device_remove+0x3f/0xb0 device_release_driver_internal+0x197/0x200 driver_detach+0x48/0x90 bus_remove_driver+0x74/0xf0 pci_unregister_driver+0x2e/0xb0 idxd_exit_module+0x34/0x7a0 [idxd] __do_sys_delete_module.constprop.0+0x183/0x280 do_syscall_64+0x54/0xd70 entry_SYSCALL_64_after_hwframe+0x76/0x7e
The idxd_unregister_devices() which is invoked at the very beginning of idxd_remove(), already takes care of the necessary put_device() through the following call path:idxd_unregister_devices() -> device_unregister() -> put_device()
In addition, when CONFIG_DEBUG_KOBJECT_RELEASE is enabled, put_device() may trigger asynchronous cleanup via schedule_delayed_work(). If idxd_free() is called immediately after, it can result in a use-after-free.
Remove the improper idxd_free() to avoid both the refcount underflow and potential memory corruption during module unload.
---
Without this patch, this issue can be reproduced in Linux-6.1.y when the idxd module is removed.
--- drivers/dma/idxd/init.c | 1 - 1 file changed, 1 deletion(-)
drivers/dma/idxd/init.c +0 -1
@@ -816,7 +816,6 @@ static void idxd_remove(struct pci_dev *destroy_workqueue (idxd->wq);perfmon_pmu_remove (idxd);put_device (idxd_confdev (idxd)); -idxd_free (idxd); }static struct pci_driver idxd_pci_driver = {
Greg Kroah-Hartman
maintainerPATCH 608/634 x86/mm/pat: clear VM_PAT if copy_p4d_range failed
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ma Wupeng <[email protected]>
[ Upstream commit d155df53f31068c3340733d586eb9b3ddfd70fc5 ]
Syzbot reports a warning in untrack_pfn(). Digging into the root we found that this is due to memory allocation failure in pmd_alloc_one. And this failure is produced due to failslab.
In copy_page_range(), memory alloaction for pmd failed. During the error handling process in copy_page_range(), mmput() is called to remove all vmas. While untrack_pfn this empty pfn, warning happens.
Here's a simplified flow:
dup_mm
dup_mmap
copy_page_range
copy_p4d_range
copy_pud_range
copy_pmd_range
pmd_alloc
__pmd_alloc
pmd_alloc_one
page = alloc_pages(gfp, 0);
if (!page)
return NULL;
mmput
exit_mmap
unmap_vmas
unmap_single_vma
untrack_pfn
follow_phys
WARN_ON_ONCE(1);Since this vma is not generate successfully, we can clear flag VM_PAT. In this case, untrack_pfn() will not be called while cleaning this vma.
Function untrack_pfn_moved() has also been renamed to fit the new logic.
--- arch/x86/mm/pat/memtype.c | 12 ++++++++---- include/linux/pgtable.h | 7 ++++--- mm/memory.c | 1 + mm/mremap.c | 2 +- 4 files changed, 14 insertions(+), 8 deletions(-)
arch/x86/mm/pat/memtype.c +8 -4
@@ -1137,11 +1137,15 @@ void untrack_pfn(struct vm_area_struct * }/* -* untrack_pfn_moved is called, while mremapping a pfnmap for a new region, -* with the old vma after its pfnmap page table has been removed. The new -* vma has a new pfnmap to the same pfn & cache type with VM_PAT set. +* untrack_pfn_clear is called if the following situation fits: +* +* 1) while mremapping a pfnmap for a new region, with the old vma after +* its pfnmap page table has been removed. The new vma has a new pfnmap +* to the same pfn & cache type with VM_PAT set. +* 2) while duplicating vm area, the new vma fails to copy the pgtable from +* old vma. */ -void untrack_pfn_moved (struct vm_area_struct *vma) +void untrack_pfn_clear (struct vm_area_struct *vma) { vma->vm_flags &= ~VM_PAT ; }
include/linux/pgtable.h +4 -3
@@ -1214,9 +1214,10 @@ static inline void untrack_pfn(struct vm }/* -* untrack_pfn_moved is called while mremapping a pfnmap for a new region. +* untrack_pfn_clear is called while mremapping a pfnmap for a new region +* or fails to copy pgtable during duplicate vm area. */ -static inline void untrack_pfn_moved (struct vm_area_struct *vma) +static inline void untrack_pfn_clear (struct vm_area_struct *vma) { }#else
@@ -1228,7 +1229,7 @@ extern void track_pfn_insert(struct vm_aextern int track_pfn_copy (struct vm_area_struct *vma);extern void untrack_pfn (struct vm_area_struct *vma,unsigned long pfn,unsigned long size); -extern void untrack_pfn_moved (struct vm_area_struct *vma); +extern void untrack_pfn_clear (struct vm_area_struct *vma);#endif #ifdef CONFIG_MMU
mm/memory.c +1 -0
@@ -1335,6 +1335,7 @@ copy_page_range(struct vm_area_struct *dcontinue ;if (unlikely (copy_p4d_range (dst_vma, src_vma, dst_pgd, src_pgd, addr, next))) { +untrack_pfn_clear (dst_vma); ret = -ENOMEM ;break ; }
mm/mremap.c +1 -1
@@ -682,7 +682,7 @@ static unsigned long move_vma(struct vm_/* Tell pfnmap has moved from this vma */ if (unlikely (vma->vm_flags &VM_PFNMAP )) -untrack_pfn_moved (vma); +untrack_pfn_clear (vma);if (unlikely (!err && (flags &MREMAP_DONTUNMAP ))) {/* We always clear VM_LOCKED[ONFAULT] on the old vma */
Greg Kroah-Hartman
maintainerPATCH 609/634 x86/mm/pat: Fix VM_PAT handling when fork() fails in copy_page_range()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Hildenbrand <[email protected]>
[ Upstream commit dc84bc2aba85a1508f04a936f9f9a15f64ebfb31 ]
If track_pfn_copy() fails, we already added the dst VMA to the maple tree. As fork() fails, we'll cleanup the maple tree, and stumble over the dst VMA for which we neither performed any reservation nor copied any page tables.
Consequently untrack_pfn() will see VM_PAT and try obtaining the PAT information from the page table -- which fails because the page table was not copied.
The easiest fix would be to simply clear the VM_PAT flag of the dst VMA if track_pfn_copy() fails. However, the whole thing is about "simply" clearing the VM_PAT flag is shaky as well: if we passed track_pfn_copy() and performed a reservation, but copying the page tables fails, we'll simply clear the VM_PAT flag, not properly undoing the reservation ... which is also wrong.
So let's fix it properly: set the VM_PAT flag only if the reservation succeeded (leaving it clear initially), and undo the reservation if anything goes wrong while copying the page tables: clearing the VM_PAT flag after undoing the reservation.
Note that any copied page table entries will get zapped when the VMA will get removed later, after copy_page_range() succeeded; as VM_PAT is not set then, we won't try cleaning VM_PAT up once more and untrack_pfn() will be happy. Note that leaving these page tables in place without a reservation is not a problem, as we are aborting fork(); this process will never run.
A reproducer can trigger this usually at the first try:
https://gitlab.com/davidhildenbrand/scratchspace/-/raw/main/reproducers/pat_fork.c
WARNING: CPU: 26 PID: 11650 at arch/x86/mm/pat/memtype.c:983 get_pat_info+0xf6/0x110 Modules linked in: ... CPU: 26 UID: 0 PID: 11650 Comm: repro3 Not tainted 6.12.0-rc5+ #92 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-2.fc40 04/01/2014 RIP: 0010:get_pat_info+0xf6/0x110 ... Call Trace: <TASK> ... untrack_pfn+0x52/0x110 unmap_single_vma+0xa6/0xe0 unmap_vmas+0x105/0x1f0 exit_mmap+0xf6/0x460 __mmput+0x4b/0x120 copy_process+0x1bf6/0x2aa0 kernel_clone+0xab/0x440 __do_sys_clone+0x66/0x90 do_syscall_64+0x95/0x180
Likely this case was missed in:
d155df53f310 ("x86/mm/pat: clear VM_PAT if copy_p4d_range failed")
... and instead of undoing the reservation we simply cleared the VM_PAT flag.
Keep the documentation of these functions in include/linux/pgtable.h, one place is more than sufficient -- we should clean that up for the other functions like track_pfn_remap/untrack_pfn separately.
--- arch/x86/mm/pat/memtype.c | 52 ++++++++++++++++++++++++---------------------- include/linux/pgtable.h | 28 +++++++++++++++++++----- kernel/fork.c | 4 +++ mm/memory.c | 11 +++------ 4 files changed, 58 insertions(+), 37 deletions(-)
arch/x86/mm/pat/memtype.c +28 -24
@@ -1029,29 +1029,42 @@ static int get_pat_info(struct vm_area_sreturn -EINVAL ; } -/* -* track_pfn_copy is called when vma that is covering the pfnmap gets -* copied through copy_page_range(). -* -* If the vma has a linear pfn mapping for the entire range, we get the prot -* from pte and reserve the entire vma range with single reserve_pfn_range call. -*/ -int track_pfn_copy (struct vm_area_struct *vma) +int track_pfn_copy (struct vm_area_struct *dst_vma, +struct vm_area_struct *src_vma,unsigned long *pfn) { +const unsigned long vma_size = src_vma->vm_end - src_vma->vm_start;resource_size_t paddr; -unsigned long vma_size = vma->vm_end - vma->vm_start;pgprot_t pgprot; +int rc; -if (vma->vm_flags &VM_PAT ) { -if (get_pat_info (vma, &paddr, &pgprot)) -return -EINVAL ; -/* reserve the whole chunk covered by vma. */ -return reserve_pfn_range (paddr, vma_size, &pgprot,1 ); - } +if (!(src_vma->vm_flags &VM_PAT )) +return 0 ; +/* +* Duplicate the PAT information for the dst VMA based on the src +* VMA. +*/ +if (get_pat_info (src_vma, &paddr, &pgprot)) +return -EINVAL ; + rc =reserve_pfn_range (paddr, vma_size, &pgprot,1 ); +if (rc) +return rc; + +/* Reservation for the destination VMA succeeded. */ + dst_vma->vm_flags |=VM_PAT ; + *pfn =PHYS_PFN (paddr);return 0 ; } +void untrack_pfn_copy (struct vm_area_struct *dst_vma,unsigned long pfn) +{ +untrack_pfn (dst_vma, pfn, dst_vma->vm_end - dst_vma->vm_start); +/* +* Reservation was freed, any copied page tables will get cleaned +* up later, but without getting PAT involved again. +*/ +} +/* * prot is passed in as a parameter for the new mapping. If the vma has * a linear pfn mapping for the entire range, or no vma is provided,
@@ -1136,15 +1149,6 @@ void untrack_pfn(struct vm_area_struct * vma->vm_flags &= ~VM_PAT ; } -/* -* untrack_pfn_clear is called if the following situation fits: -* -* 1) while mremapping a pfnmap for a new region, with the old vma after -* its pfnmap page table has been removed. The new vma has a new pfnmap -* to the same pfn & cache type with VM_PAT set. -* 2) while duplicating vm area, the new vma fails to copy the pgtable from -* old vma. -*/ void untrack_pfn_clear (struct vm_area_struct *vma) { vma->vm_flags &= ~VM_PAT ;
include/linux/pgtable.h +22 -6
@@ -1195,15 +1195,26 @@ static inline void track_pfn_insert(stru }/* -* track_pfn_copy is called when vma that is covering the pfnmap gets -* copied through copy_page_range(). +* track_pfn_copy is called when a VM_PFNMAP VMA is about to get the page +* tables copied during copy_page_range(). On success, stores the pfn to be +* passed to untrack_pfn_copy(). */ -static inline int track_pfn_copy (struct vm_area_struct *vma) +static inline int track_pfn_copy (struct vm_area_struct *dst_vma, +struct vm_area_struct *src_vma,unsigned long *pfn) {return 0 ; }/* +* untrack_pfn_copy is called when a VM_PFNMAP VMA failed to copy during +* copy_page_range(), but after track_pfn_copy() was already called. +*/ +static inline void untrack_pfn_copy (struct vm_area_struct *dst_vma, +unsigned long pfn) +{ +} + +/* * untrack_pfn is called while unmapping a pfnmap for a region. * untrack can be called for a specific region indicated by pfn and size or * can be for the entire vma (in which case pfn, size are zero).
@@ -1214,8 +1225,10 @@ static inline void untrack_pfn(struct vm }/* -* untrack_pfn_clear is called while mremapping a pfnmap for a new region -* or fails to copy pgtable during duplicate vm area. +* untrack_pfn_clear is called in the following cases on a VM_PFNMAP VMA: +* +* 1) During mremap() on the src VMA after the page tables were moved. +* 2) During fork() on the dst VMA, immediately after duplicating the src VMA. */ static inline void untrack_pfn_clear (struct vm_area_struct *vma) {
@@ -1226,7 +1239,10 @@ extern int track_pfn_remap(struct vm_are unsigned long size);extern void track_pfn_insert (struct vm_area_struct *vma,pgprot_t *prot,pfn_t pfn); -extern int track_pfn_copy (struct vm_area_struct *vma); +extern int track_pfn_copy (struct vm_area_struct *dst_vma, +struct vm_area_struct *src_vma,unsigned long *pfn); +extern void untrack_pfn_copy (struct vm_area_struct *dst_vma, +unsigned long pfn);extern void untrack_pfn (struct vm_area_struct *vma,unsigned long pfn,unsigned long size);extern void untrack_pfn_clear (struct vm_area_struct *vma);
kernel/fork.c +4 -0
@@ -476,6 +476,10 @@ struct vm_area_struct *vm_area_dup(struc *new =data_race (*orig);INIT_LIST_HEAD (&new->anon_vma_chain);dup_anon_vma_name (orig, new); + +/* track_pfn_copy() will later take care of copying internal state. */ +if (unlikely (new->vm_flags &VM_PFNMAP )) +untrack_pfn_clear (new); }return new; }
mm/memory.c +4 -7
@@ -1278,12 +1278,12 @@ int copy_page_range(struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma) { pgd_t *src_pgd, *dst_pgd; -unsigned long next;unsigned long addr = src_vma->vm_start;unsigned long end = src_vma->vm_end;struct mm_struct *dst_mm = dst_vma->vm_mm;struct mm_struct *src_mm = src_vma->vm_mm;struct mmu_notifier_range range; +unsigned long next, pfn;bool is_cow;int ret;
@@ -1294,11 +1294,7 @@ copy_page_range(struct vm_area_struct *dreturn copy_hugetlb_page_range (dst_mm, src_mm, dst_vma, src_vma);if (unlikely (src_vma->vm_flags &VM_PFNMAP )) { -/* -* We do not free on error cases below as remove_vma -* gets called on error from higher level routine -*/ - ret =track_pfn_copy (src_vma); + ret =track_pfn_copy (dst_vma, src_vma, &pfn);if (ret)return ret; }
@@ -1335,7 +1331,6 @@ copy_page_range(struct vm_area_struct *dcontinue ;if (unlikely (copy_p4d_range (dst_vma, src_vma, dst_pgd, src_pgd, addr, next))) { -untrack_pfn_clear (dst_vma); ret = -ENOMEM ;break ; }
@@ -1345,6 +1340,8 @@ copy_page_range(struct vm_area_struct *draw_write_seqcount_end (&src_mm->write_protect_seq);mmu_notifier_invalidate_range_end (&range); } +if (ret &&unlikely (src_vma->vm_flags &VM_PFNMAP )) +untrack_pfn_copy (dst_vma, pfn);return ret; }
Greg Kroah-Hartman
maintainerPATCH 610/634 mm/mprotect: use long for page accountings and retval
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Xu <[email protected]>
commit a79390f5d6a78647fd70856bd42b22d994de0ba2 upstream.
Switch to use type "long" for page accountings and retval across the whole procedure of change_protection().
The change should have shrinked the possible maximum page number to be half comparing to previous (ULONG_MAX / 2), but it shouldn't overflow on any system either because the maximum possible pages touched by change protection should be ULONG_MAX / PAGE_SIZE.
Two reasons to switch from "unsigned long" to "long":
1. It suites better on count_vm_numa_events(), whose 2nd parameter takes a long type.
2. It paves way for returning negative (error) values in the future.
Currently the only caller that consumes this retval is change_prot_numa(), where the unsigned long was converted to an int. Since at it, touching up the numa code to also take a long, so it'll avoid any possible overflow too during the int-size convertion.
--- include/linux/hugetlb.h | 4 ++-- include/linux/mm.h | 2 +- mm/hugetlb.c | 4 ++-- mm/mempolicy.c | 2 +- mm/mprotect.c | 26 +++++++++++++------------- 5 files changed, 19 insertions(+), 19 deletions(-)
include/linux/hugetlb.h +2 -2
@@ -233,7 +233,7 @@ void hugetlb_vma_lock_release(struct kreint pmd_huge (pmd_t pmd);int pud_huge (pud_t pud); -unsigned long hugetlb_change_protection (struct vm_area_struct *vma, +long hugetlb_change_protection (struct vm_area_struct *vma,unsigned long address,unsigned long end,pgprot_t newprot,unsigned long cp_flags);
@@ -447,7 +447,7 @@ static inline void move_hugetlb_state(st { } -static inline unsigned long hugetlb_change_protection ( +static inline long hugetlb_change_protection (struct vm_area_struct *vma,unsigned long address,unsigned long end,pgprot_t newprot,unsigned long cp_flags)
include/linux/mm.h +1 -1
@@ -2148,7 +2148,7 @@ extern unsigned long move_page_tables(st#define MM_CP_UFFD_WP_ALL (MM_CP_UFFD_WP | \ MM_CP_UFFD_WP_RESOLVE) -extern unsigned long change_protection (struct mmu_gather *tlb, +extern long change_protection (struct mmu_gather *tlb,struct vm_area_struct *vma,unsigned long start,unsigned long end,pgprot_t newprot,unsigned long cp_flags);
mm/hugetlb.c +2 -2
@@ -6668,7 +6668,7 @@ long follow_hugetlb_page(struct mm_strucreturn i ? i : err; } -unsigned long hugetlb_change_protection (struct vm_area_struct *vma, +long hugetlb_change_protection (struct vm_area_struct *vma,unsigned long address,unsigned long end,pgprot_t newprot,unsigned long cp_flags) {
@@ -6677,7 +6677,7 @@ unsigned long hugetlb_change_protection(pte_t *ptep;pte_t pte;struct hstate *h =hstate_vma (vma); -unsigned long pages =0 , psize =huge_page_size (h); +long pages =0 , psize =huge_page_size (h);bool shared_pmd = false;struct mmu_notifier_range range;unsigned long last_addr_mask;
mm/mempolicy.c +1 -1
@@ -628,7 +628,7 @@ unsigned long change_prot_numa(struct vm unsigned long addr, unsigned long end) {struct mmu_gather tlb; -int nr_updated; +long nr_updated;tlb_gather_mmu (&tlb, vma->vm_mm);
mm/mprotect.c +13 -13
@@ -72,13 +72,13 @@ static inline bool can_change_pte_writabreturn true; } -static unsigned long change_pte_range (struct mmu_gather *tlb, +static long change_pte_range (struct mmu_gather *tlb,struct vm_area_struct *vma,pmd_t *pmd,unsigned long addr,unsigned long end,pgprot_t newprot,unsigned long cp_flags) {pte_t *pte, oldpte;spinlock_t *ptl; -unsigned long pages =0 ; +long pages =0 ;int target_node =NUMA_NO_NODE ;bool prot_numa = cp_flags &MM_CP_PROT_NUMA ;bool uffd_wp = cp_flags &MM_CP_UFFD_WP ;
@@ -346,13 +346,13 @@ uffd_wp_protect_file(struct vm_area_stru } \ }while (0 ) -static inline unsigned long change_pmd_range(struct mmu_gather *tlb, +static inline long change_pmd_range(struct mmu_gather *tlb,struct vm_area_struct *vma,pud_t *pud,unsigned long addr,unsigned long end,pgprot_t newprot,unsigned long cp_flags) {pmd_t *pmd;unsigned long next; -unsigned long pages =0 ; +long pages =0 ;unsigned long nr_huge_updates =0 ;struct mmu_notifier_range range;
@@ -360,7 +360,7 @@ static inline unsigned long change_pmd_r pmd =pmd_offset (pud, addr); do { - unsigned long this_pages; + long this_pages; next = pmd_addr_end(addr, end);
@@ -430,13 +430,13 @@ next:return pages; } -static inline unsigned long change_pud_range (struct mmu_gather *tlb, +static inline long change_pud_range (struct mmu_gather *tlb,struct vm_area_struct *vma,p4d_t *p4d,unsigned long addr,unsigned long end,pgprot_t newprot,unsigned long cp_flags) {pud_t *pud;unsigned long next; -unsigned long pages =0 ; +long pages =0 ; pud =pud_offset (p4d, addr); do {
@@ -451,13 +451,13 @@ static inline unsigned long change_pud_rreturn pages; } -static inline unsigned long change_p4d_range (struct mmu_gather *tlb, +static inline long change_p4d_range (struct mmu_gather *tlb,struct vm_area_struct *vma,pgd_t *pgd,unsigned long addr,unsigned long end,pgprot_t newprot,unsigned long cp_flags) {p4d_t *p4d;unsigned long next; -unsigned long pages =0 ; +long pages =0 ; p4d =p4d_offset (pgd, addr); do {
@@ -472,14 +472,14 @@ static inline unsigned long change_p4d_rreturn pages; } -static unsigned long change_protection_range (struct mmu_gather *tlb, +static long change_protection_range (struct mmu_gather *tlb,struct vm_area_struct *vma,unsigned long addr,unsigned long end,pgprot_t newprot,unsigned long cp_flags) {struct mm_struct *mm = vma->vm_mm;pgd_t *pgd;unsigned long next; -unsigned long pages =0 ; +long pages =0 ;BUG_ON (addr >= end); pgd =pgd_offset (mm, addr);
@@ -498,12 +498,12 @@ static unsigned long change_protection_rreturn pages; } -unsigned long change_protection (struct mmu_gather *tlb, +long change_protection (struct mmu_gather *tlb,struct vm_area_struct *vma,unsigned long start,unsigned long end,pgprot_t newprot,unsigned long cp_flags) { -unsigned long pages; +long pages;BUG_ON ((cp_flags &MM_CP_UFFD_WP_ALL ) ==MM_CP_UFFD_WP_ALL );
Greg Kroah-Hartman
maintainerPATCH 611/634 mm/mprotect: delete pmd_none_or_clear_bad_unless_trans_huge()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hugh Dickins <[email protected]>
commit 670ddd8cdcbd1d07a4571266ae3517f821728c3a upstream.
change_pmd_range() had special pmd_none_or_clear_bad_unless_trans_huge(), required to avoid "bad" choices when setting automatic NUMA hinting under mmap_read_lock(); but most of that is already covered in pte_offset_map() now. change_pmd_range() just wants a pmd_none() check before wasting time on MMU notifiers, then checks on the read-once _pmd value to work out what's needed for huge cases. If change_pte_range() returns -EAGAIN to retry if pte_offset_map_lock() fails, nothing more special is needed.
[ Background: It was reported that a bad pmd is seen when automatic NUMA
balancing is marking page table entries as prot_numa:
[2437548.196018] mm/pgtable-generic.c:50: bad pmd 00000000af22fc02(dffffffe71fbfe02)
[2437548.235022] Call Trace:
[2437548.238234] <TASK>
[2437548.241060] dump_stack_lvl+0x46/0x61
[2437548.245689] panic+0x106/0x2e5
[2437548.249497] pmd_clear_bad+0x3c/0x3c
[2437548.253967] change_pmd_range.isra.0+0x34d/0x3a7
[2437548.259537] change_p4d_range+0x156/0x20e
[2437548.264392] change_protection_range+0x116/0x1a9
[2437548.269976] change_prot_numa+0x15/0x37
[2437548.274774] task_numa_work+0x1b8/0x302
[2437548.279512] task_work_run+0x62/0x95
[2437548.283882] exit_to_user_mode_loop+0x1a4/0x1a9
[2437548.289277] exit_to_user_mode_prepare+0xf4/0xfc
[2437548.294751] ? sysvec_apic_timer_interrupt+0x34/0x81
[2437548.300677] irqentry_exit_to_user_mode+0x5/0x25
[2437548.306153] asm_sysvec_apic_timer_interrupt+0x16/0x1b This is due to a race condition between change_prot_numa() and THP migration because the kernel doesn't check is_swap_pmd() and pmd_trans_huge() atomically:
change_prot_numa() THP migration
======================================================================
- change_pmd_range()
-> is_swap_pmd() returns false,
meaning it's not a PMD migration
entry.
- do_huge_pmd_numa_page() -> migrate_misplaced_page() sets migration entries for the THP.
- change_pmd_range()
-> pmd_none_or_clear_bad_unless_trans_huge()
-> pmd_none() and pmd_trans_huge() returns false
- pmd_none_or_clear_bad_unless_trans_huge()
-> pmd_bad() returns true for the migration entry!
The upstream commit 670ddd8cdcbd ("mm/mprotect: delete pmd_none_or_clear_bad_unless_trans_huge()") closes this race condition by checking is_swap_pmd() and pmd_trans_huge() atomically.
Backporting note:
Unlike the mainline, pte_offset_map_lock() does not check if the pmd entry is a migration entry or a hugepage; acquires PTL unconditionally instead of returning failure. Therefore, it is necessary to keep the !is_swap_pmd() && !pmd_trans_huge() && !pmd_devmap() check before acquiring the PTL.
After acquiring the lock, open-code the semantics of pte_offset_map_lock() in the mainline kernel; change_pte_range() fails if the pmd value has changed. This requires adding pmd_old parameter (pmd_t value that is read before calling the function) to change_pte_range(). ]
--- mm/mprotect.c | 101 ++++++++++++++++++++++++---------------------------------- 1 file changed, 43 insertions(+), 58 deletions(-)
mm/mprotect.c +43 -58
@@ -73,10 +73,12 @@ static inline bool can_change_pte_writab }static long change_pte_range (struct mmu_gather *tlb, -struct vm_area_struct *vma,pmd_t *pmd,unsigned long addr, -unsigned long end,pgprot_t newprot,unsigned long cp_flags) +struct vm_area_struct *vma,pmd_t *pmd,pmd_t pmd_old, +unsigned long addr,unsigned long end,pgprot_t newprot, +unsigned long cp_flags) {pte_t *pte, oldpte; +pmd_t _pmd;spinlock_t *ptl;long pages =0 ;int target_node =NUMA_NO_NODE ;
@@ -86,21 +88,15 @@ static long change_pte_range(struct mmu_tlb_change_page_size (tlb,PAGE_SIZE ); -/* -* Can be called with only the mmap_lock for reading by -* prot_numa so we must check the pmd isn't constantly -* changing from under us from pmd_none to pmd_trans_huge -* and/or the other way around. -*/ -if (pmd_trans_unstable (pmd)) -return 0 ; - -/* -* The pmd points to a regular pte so the pmd can't change -* from under us even if the mmap_lock is only hold for -* reading. -*/ pte =pte_offset_map_lock (vma->vm_mm, pmd, addr, &ptl); +/* Make sure pmd didn't change after acquiring ptl */ + _pmd =pmd_read_atomic (pmd); +/* See pmd_none_or_trans_huge_or_clear_bad for info on barrier */ +barrier (); +if (!pmd_same (pmd_old, _pmd)) { +pte_unmap_unlock (pte, ptl); +return -EAGAIN ; + }/* Get target node for single threaded private VMAs */ if (prot_numa && !(vma->vm_flags & VM_SHARED) &&
@@ -288,31 +284,6 @@ static long change_pte_range(struct mmu_return pages; } -/* -* Used when setting automatic NUMA hinting protection where it is -* critical that a numa hinting PMD is not confused with a bad PMD. -*/ -static inline int pmd_none_or_clear_bad_unless_trans_huge (pmd_t *pmd) -{ -pmd_t pmdval =pmd_read_atomic (pmd); - -/* See pmd_none_or_trans_huge_or_clear_bad for info on barrier */ -#ifdef CONFIG_TRANSPARENT_HUGEPAGE -barrier (); -#endif - -if (pmd_none (pmdval)) -return 1 ; -if (pmd_trans_huge (pmdval)) -return 0 ; -if (unlikely (pmd_bad (pmdval))) { -pmd_clear_bad (pmd); -return 1 ; - } - -return 0 ; -} -/* Return true if we're uffd wr-protecting file-backed memory, or false */ static inline bool uffd_wp_protect_file (struct vm_area_struct *vma,unsigned long cp_flags)
@@ -360,22 +331,34 @@ static inline long change_pmd_range(stru pmd =pmd_offset (pud, addr); do { - long this_pages; - + long ret; + pmd_t _pmd; +again: next = pmd_addr_end(addr, end); + _pmd = pmd_read_atomic(pmd); + /* See pmd_none_or_trans_huge_or_clear_bad for info on barrier */ +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + barrier(); +#endif change_pmd_prepare(vma, pmd, cp_flags); /* * Automatic NUMA balancing walks the tables with mmap_lock * held for read. It's possible a parallel update to occur - * between pmd_trans_huge() and a pmd_none_or_clear_bad() - * check leading to a false positive and clearing. - * Hence, it's necessary to atomically read the PMD value - * for all the checks. + * between pmd_trans_huge(), is_swap_pmd(), and + * a pmd_none_or_clear_bad() check leading to a false positive + * and clearing. Hence, it's necessary to atomically read + * the PMD value for all the checks. */ - if (!is_swap_pmd(*pmd) && !pmd_devmap(*pmd) && - pmd_none_or_clear_bad_unless_trans_huge(pmd)) - goto next; + if (!is_swap_pmd(_pmd) && !pmd_devmap(_pmd) && !pmd_trans_huge(_pmd)) { + if (pmd_none(_pmd)) + goto next; + + if (pmd_bad(_pmd)) { + pmd_clear_bad(pmd); + goto next; + } + } /* invoke the mmu notifier if the pmd is populated */ if (!range.start) {
@@ -385,7 +368,7 @@ static inline long change_pmd_range(strummu_notifier_invalidate_range_start (&range); } -if (is_swap_pmd (*pmd) ||pmd_trans_huge (*pmd) ||pmd_devmap (*pmd)) { +if (is_swap_pmd (_pmd) ||pmd_trans_huge (_pmd) ||pmd_devmap (_pmd)) {if ((next - addr !=HPAGE_PMD_SIZE ) ||uffd_wp_protect_file (vma, cp_flags)) {__split_huge_pmd (vma, pmd, addr, false,NULL );
@@ -400,11 +383,11 @@ static inline long change_pmd_range(stru* change_huge_pmd() does not defer TLB flushes, * so no need to propagate the tlb argument. */ -int nr_ptes =change_huge_pmd (tlb, vma, pmd, - addr, newprot, cp_flags); + ret =change_huge_pmd (tlb, vma, pmd, + addr, newprot, cp_flags); -if (nr_ptes) { -if (nr_ptes ==HPAGE_PMD_NR ) { +if (ret) { +if (ret ==HPAGE_PMD_NR ) { pages +=HPAGE_PMD_NR ; nr_huge_updates++; }
@@ -415,9 +398,11 @@ static inline long change_pmd_range(stru }/* fall through, the trans huge pmd just split */ } - this_pages =change_pte_range (tlb, vma, pmd, addr, next, - newprot, cp_flags); - pages += this_pages; + ret =change_pte_range (tlb, vma, pmd, _pmd, addr, next, + newprot, cp_flags); +if (ret <0 ) + goto again; + pages += ret; next:cond_resched (); }while (pmd++, addr = next, addr != end);
Greg Kroah-Hartman
maintainerPATCH 612/634 drm/vmwgfx: Fix a null-ptr access in the cursor snooper
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zack Rusin <[email protected]>
[ Upstream commit 5ac2c0279053a2c5265d46903432fb26ae2d0da2 ]
Check that the resource which is converted to a surface exists before trying to use the cursor snooper on it.
vmw_cmd_res_check allows explicit invalid (SVGA3D_INVALID_ID) identifiers because some svga commands accept SVGA3D_INVALID_ID to mean "no surface", unfortunately functions that accept the actual surfaces as objects might (and in case of the cursor snooper, do not) be able to handle null objects. Make sure that we validate not only the identifier (via the vmw_cmd_res_check) but also check that the actual resource exists before trying to do something with it.
Fixes unchecked null-ptr reference in the snooping code.
--- drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +12 -5
@@ -1507,6 +1507,7 @@ static int vmw_cmd_dma(struct vmw_privat SVGA3dCmdHeader *header) {struct vmw_buffer_object *vmw_bo =NULL ; +struct vmw_resource *res;struct vmw_surface *srf =NULL ;VMW_DECLARE_CMD_VAR (*cmd, SVGA3dCmdSurfaceDMA);int ret;
@@ -1542,18 +1543,24 @@ static int vmw_cmd_dma(struct vmw_privat dirty = (cmd->body.transfer ==SVGA3D_WRITE_HOST_VRAM ) ?VMW_RES_DIRTY_SET :0 ; - ret =vmw_cmd_res_check (dev_priv, sw_context, vmw_res_surface, - dirty, user_surface_converter, - &cmd->body.host.sid,NULL ); + ret =vmw_cmd_res_check (dev_priv, sw_context, vmw_res_surface, dirty, + user_surface_converter, &cmd->body.host.sid, +NULL );if (unlikely (ret !=0 )) {if (unlikely (ret != -ERESTARTSYS ))VMW_DEBUG_USER ("could not find surface for DMA.\n" );return ret; } - srf =vmw_res_to_srf (sw_context->res_cache[vmw_res_surface].res); + res = sw_context->res_cache[vmw_res_surface].res; +if (!res) { +VMW_DEBUG_USER ("Invalid DMA surface.\n" ); +return -EINVAL ; + } -vmw_kms_cursor_snoop (srf, sw_context->fp->tfile, &vmw_bo->base, header); + srf =vmw_res_to_srf (res); +vmw_kms_cursor_snoop (srf, sw_context->fp->tfile, &vmw_bo->base, + header);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 613/634 usb: xhci: move link chain bit quirk checks into one helper function.
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Niklas Neronin <[email protected]>
commit 7476a2215c07703db5e95efaa3fc5b9f957b9417 upstream.
Older 0.95 xHCI hosts and some other specific newer hosts require the chain bit to be set for Link TRBs even if the link TRB is not in the middle of a transfer descriptor (TD).
move the checks for all those cases into one xhci_link_chain_quirk() function to clean up and avoid code duplication.
No functional changes.
[skip renaming chain_links flag, reword commit message -Mathias]
--- drivers/usb/host/xhci-mem.c | 10 ++-------- drivers/usb/host/xhci-ring.c | 8 ++------ drivers/usb/host/xhci.h | 7 +++++-- 3 files changed, 9 insertions(+), 16 deletions(-)
drivers/usb/host/xhci-mem.c +2 -8
@@ -133,10 +133,7 @@ static void xhci_link_rings(struct xhci_if (!ring || !first || !last)return ; -/* Set chain bit for 0.95 hosts, and for isoc rings on AMD 0.96 host */ - chain_links = !!(xhci_link_trb_quirk (xhci) || - (ring->type ==TYPE_ISOC && - (xhci->quirks & XHCI_AMD_0x96_HOST))); + chain_links =xhci_link_chain_quirk (xhci, ring->type); next = ring->enq_seg->next;xhci_link_segments (ring->enq_seg, first, ring->type, chain_links);
@@ -326,10 +323,7 @@ static int xhci_alloc_segments_for_ring(struct xhci_segment *prev;bool chain_links; -/* Set chain bit for 0.95 hosts, and for isoc rings on AMD 0.96 host */ - chain_links = !!(xhci_link_trb_quirk (xhci) || - (type ==TYPE_ISOC && - (xhci->quirks & XHCI_AMD_0x96_HOST))); + chain_links =xhci_link_chain_quirk (xhci, type); prev =xhci_segment_alloc (xhci, cycle_state, max_packet, flags);if (!prev)
drivers/usb/host/xhci-ring.c +2 -6
@@ -250,9 +250,7 @@ static void inc_enq(struct xhci_hcd *xhc* AMD 0.96 host, carry over the chain bit of the previous TRB * (which may mean the chain bit is cleared). */ -if (!(ring->type ==TYPE_ISOC && - (xhci->quirks & XHCI_AMD_0x96_HOST)) && - !xhci_link_trb_quirk (xhci)) { +if (!xhci_link_chain_quirk (xhci, ring->type)) { next->link.control &=cpu_to_le32 (~TRB_CHAIN ); next->link.control |=cpu_to_le32 (chain); }
@@ -3355,9 +3353,7 @@ static int prepare_ring(struct xhci_hcd/* If we're not dealing with 0.95 hardware or isoc rings * on AMD 0.96 host, clear the chain bit. */ -if (!xhci_link_trb_quirk (xhci) && - !(ep_ring->type ==TYPE_ISOC && - (xhci->quirks & XHCI_AMD_0x96_HOST))) +if (!xhci_link_chain_quirk (xhci, ep_ring->type)) ep_ring->enqueue->link.control &=cpu_to_le32 (~TRB_CHAIN );else
drivers/usb/host/xhci.h +5 -2
@@ -1788,9 +1788,12 @@ static inline void xhci_write_64(structlo_hi_writeq (val, regs); } -static inline int xhci_link_trb_quirk (struct xhci_hcd *xhci) + +/* Link TRB chain should always be set on 0.95 hosts, and AMD 0.96 ISOC rings */ +static inline bool xhci_link_chain_quirk (struct xhci_hcd *xhci,enum xhci_ring_type type) { -return xhci->quirks &XHCI_LINK_TRB_QUIRK ; +return (xhci->quirks &XHCI_LINK_TRB_QUIRK ) || + (type ==TYPE_ISOC && (xhci->quirks & XHCI_AMD_0x96_HOST)); }/* xHCI debugging */
Greg Kroah-Hartman
maintainerPATCH 614/634 usb: xhci: Apply the link chain quirk on NEC isoc endpoints
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michal Pecio <[email protected]>
commit bb0ba4cb1065e87f9cc75db1fa454e56d0894d01 upstream.
Two clearly different specimens of NEC uPD720200 (one with start/stop bug, one without) were seen to cause IOMMU faults after some Missed Service Errors. Faulting address is immediately after a transfer ring segment and patched dynamic debug messages revealed that the MSE was received when waiting for a TD near the end of that segment:
[ 1.041954] xhci_hcd: Miss service interval error for slot 1 ep 2 expected TD DMA ffa08fe0 [ 1.042120] xhci_hcd: AMD-Vi: Event logged [IO_PAGE_FAULT domain=0x0005 address=0xffa09000 flags=0x0000] [ 1.042146] xhci_hcd: AMD-Vi: Event logged [IO_PAGE_FAULT domain=0x0005 address=0xffa09040 flags=0x0000]
It gets even funnier if the next page is a ring segment accessible to the HC. Below, it reports MSE in segment at ff1e8000, plows through a zero-filled page at ff1e9000 and starts reporting events for TRBs in page at ff1ea000 every microframe, instead of jumping to seg ff1e6000.
[ 7.041671] xhci_hcd: Miss service interval error for slot 1 ep 2 expected TD DMA ff1e8fe0 [ 7.041999] xhci_hcd: Miss service interval error for slot 1 ep 2 expected TD DMA ff1e8fe0 [ 7.042011] xhci_hcd: WARN: buffer overrun event for slot 1 ep 2 on endpoint [ 7.042028] xhci_hcd: All TDs skipped for slot 1 ep 2. Clear skip flag. [ 7.042134] xhci_hcd: WARN: buffer overrun event for slot 1 ep 2 on endpoint [ 7.042138] xhci_hcd: ERROR Transfer event TRB DMA ptr not part of current TD ep_index 2 comp_code 31 [ 7.042144] xhci_hcd: Looking for event-dma 00000000ff1ea040 trb-start 00000000ff1e6820 trb-end 00000000ff1e6820 [ 7.042259] xhci_hcd: WARN: buffer overrun event for slot 1 ep 2 on endpoint [ 7.042262] xhci_hcd: ERROR Transfer event TRB DMA ptr not part of current TD ep_index 2 comp_code 31 [ 7.042266] xhci_hcd: Looking for event-dma 00000000ff1ea050 trb-start 00000000ff1e6820 trb-end 00000000ff1e6820
At some point completion events change from Isoch Buffer Overrun to Short Packet and the HC finally finds cycle bit mismatch in ff1ec000.
[ 7.098130] xhci_hcd: ERROR Transfer event TRB DMA ptr not part of current TD ep_index 2 comp_code 13 [ 7.098132] xhci_hcd: Looking for event-dma 00000000ff1ecc50 trb-start 00000000ff1e6820 trb-end 00000000ff1e6820 [ 7.098254] xhci_hcd: ERROR Transfer event TRB DMA ptr not part of current TD ep_index 2 comp_code 13 [ 7.098256] xhci_hcd: Looking for event-dma 00000000ff1ecc60 trb-start 00000000ff1e6820 trb-end 00000000ff1e6820 [ 7.098379] xhci_hcd: Overrun event on slot 1 ep 2
It's possible that data from the isochronous device were written to random buffers of pending TDs on other endpoints (either IN or OUT), other devices or even other HCs in the same IOMMU domain.
Lastly, an error from a different USB device on another HC. Was it caused by the above? I don't know, but it may have been. The disk was working without any other issues and generated PCIe traffic to starve the NEC of upstream BW and trigger those MSEs. The two HCs shared one x1 slot by means of a commercial "PCIe splitter" board.
[ 7.162604] usb 10-2: reset SuperSpeed USB device number 3 using xhci_hcd [ 7.178990] sd 9:0:0:0: [sdb] tag#0 UNKNOWN(0x2003) Result: hostbyte=0x07 driverbyte=DRIVER_OK cmd_age=0s [ 7.179001] sd 9:0:0:0: [sdb] tag#0 CDB: opcode=0x28 28 00 04 02 ae 00 00 02 00 00 [ 7.179004] I/O error, dev sdb, sector 67284480 op 0x0:(READ) flags 0x80700 phys_seg 5 prio class 0
Fortunately, it appears that this ridiculous bug is avoided by setting the chain bit of Link TRBs on isochronous rings. Other ancient HCs are known which also expect the bit to be set and they ignore Link TRBs if it's not. Reportedly, 0.95 spec guaranteed that the bit is set.
The bandwidth-starved NEC HC running a 32KB/uframe UVC endpoint reports tens of MSEs per second and runs into the bug within seconds. Chaining Link TRBs allows the same workload to run for many minutes, many times.
No negative side effects seen in UVC recording and UAC playback with a few devices at full speed, high speed and SuperSpeed.
The problem doesn't reproduce on the newer Renesas uPD720201/uPD720202 and on old Etron EJ168 and VIA VL805 (but the VL805 has other bug).
[shorten line length of log snippets in commit messge -Mathias]
--- drivers/usb/host/xhci.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
drivers/usb/host/xhci.h +11 -2
@@ -1789,11 +1789,20 @@ static inline void xhci_write_64(struct } -/* Link TRB chain should always be set on 0.95 hosts, and AMD 0.96 ISOC rings */ +/* +* Reportedly, some chapters of v0.95 spec said that Link TRB always has its chain bit set. +* Other chapters and later specs say that it should only be set if the link is inside a TD +* which continues from the end of one segment to the next segment. +* +* Some 0.95 hardware was found to misbehave if any link TRB doesn't have the chain bit set. +* +* 0.96 hardware from AMD and NEC was found to ignore unchained isochronous link TRBs when +* "resynchronizing the pipe" after a Missed Service Error. +*/ static inline bool xhci_link_chain_quirk (struct xhci_hcd *xhci,enum xhci_ring_type type) {return (xhci->quirks &XHCI_LINK_TRB_QUIRK ) || - (type ==TYPE_ISOC && (xhci->quirks & XHCI_AMD_0x96_HOST)); + (type ==TYPE_ISOC && (xhci->quirks & (XHCI_AMD_0x96_HOST |XHCI_NEC_HOST ))); }/* xHCI debugging */
Greg Kroah-Hartman
maintainerPATCH 615/634 sched/fair: Small cleanup to sched_balance_newidle()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Zijlstra <[email protected]>
commit e78e70dbf603c1425f15f32b455ca148c932f6c1 upstream.
Pull out the !sd check to simplify code.
--- kernel/sched/fair.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
kernel/sched/fair.c +6 -5
@@ -11589,14 +11589,15 @@ static int sched_balance_newidle(structrcu_read_lock (); sd =rcu_dereference_check_sched_domain (this_rq->sd); +if (!sd) { +rcu_read_unlock (); + goto out; + }if (!READ_ONCE (this_rq->rd->overload) || - (sd && this_rq->avg_idle < sd->max_newidle_lb_cost)) { - -if (sd) -update_next_balance (sd, &next_balance); + this_rq->avg_idle < sd->max_newidle_lb_cost) { +update_next_balance (sd, &next_balance);rcu_read_unlock (); - goto out; }rcu_read_unlock ();
Greg Kroah-Hartman
maintainerPATCH 616/634 sched/fair: Small cleanup to update_newidle_cost()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Zijlstra <[email protected]>
commit 08d473dd8718e4a4d698b1113a14a40ad64a909b upstream.
Simplify code by adding a few variables.
--- kernel/sched/fair.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
kernel/sched/fair.c +7 -4
@@ -10937,22 +10937,25 @@ void update_max_interval(void)static inline bool update_newidle_cost (struct sched_domain *sd,u64 cost) { +unsigned long next_decay = sd->last_decay_max_lb_cost +HZ ; +unsigned long now = jiffies; +if (cost > sd->max_newidle_lb_cost) {/* * Track max cost of a domain to make sure to not delay the * next wakeup on the CPU. */ sd->max_newidle_lb_cost = cost; - sd->last_decay_max_lb_cost = jiffies; - }else if (time_after (jiffies, sd->last_decay_max_lb_cost +HZ )) { + sd->last_decay_max_lb_cost = now; + + }else if (time_after (now, next_decay)) {/* * Decay the newidle max times by ~1% per second to ensure that * it is not outdated and the current max cost is actually * shorter. */ sd->max_newidle_lb_cost = (sd->max_newidle_lb_cost *253 ) /256 ; - sd->last_decay_max_lb_cost = jiffies; - + sd->last_decay_max_lb_cost = now;return true; }
Greg Kroah-Hartman
maintainerPATCH 617/634 sched/fair: Proportional newidle balance
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Zijlstra <[email protected]>
commit 33cf66d88306663d16e4759e9d24766b0aaa2e17 upstream.
Add a randomized algorithm that runs newidle balancing proportional to its success rate.
This improves schbench significantly:
6.18-rc4: 2.22 Mrps/s
6.18-rc4+revert: 2.04 Mrps/s
6.18-rc4+revert+random: 2.18 Mrps/S
Conversely, per Adam Li this affects SpecJBB slightly, reducing it by 1%:
6.17: -6%
6.17+revert: 0%
6.17+revert+random: -1%
--- include/linux/sched/topology.h | 3 ++ kernel/sched/core.c | 3 ++ kernel/sched/fair.c | 44 +++++++++++++++++++++++++++++++++++++---- kernel/sched/features.h | 5 ++++ kernel/sched/sched.h | 7 ++++++ kernel/sched/topology.c | 6 +++++ 6 files changed, 64 insertions(+), 4 deletions(-)
include/linux/sched/topology.h +3 -0
@@ -106,6 +106,9 @@ struct sched_domain {unsigned int nr_balance_failed;/* initialise to 0 */ /* idle_balance() stats */ +unsigned int newidle_call; +unsigned int newidle_success; +unsigned int newidle_ratio;u64 max_newidle_lb_cost;unsigned long last_decay_max_lb_cost;
kernel/sched/core.c +3 -0
@@ -112,6 +112,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(sched_util_EXPORT_TRACEPOINT_SYMBOL_GPL (sched_update_nr_running_tp); DEFINE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues); +DEFINE_PER_CPU(struct rnd_state, sched_rnd_state);#ifdef CONFIG_SCHED_DEBUG /*
@@ -9632,6 +9633,8 @@ void __init sched_init_smp(void) {sched_init_numa (NUMA_NO_NODE ); +prandom_init_once (&sched_rnd_state); +/* * There's no userspace yet to cause hotplug operations; hence all the * CPU masks are stable and all blatant races in the below code cannot
kernel/sched/fair.c +40 -4
74 lines not on this page · raw message
kernel/sched/features.h +5 -0
@@ -99,5 +99,10 @@ SCHED_FEAT(UTIL_EST_FASTUP, true)SCHED_FEAT (LATENCY_WARN , false) +/* +* Do newidle balancing proportional to its success rate using randomization. + */ +SCHED_FEAT(NI_RANDOM, true) + SCHED_FEAT(ALT_PERIOD, true)SCHED_FEAT (BASE_SLICE , true)
kernel/sched/sched.h +7 -0
@@ -5,6 +5,7 @@#ifndef _KERNEL_SCHED_SCHED_H#define _KERNEL_SCHED_SCHED_H +#include <linux/prandom.h> #include <linux/sched/affinity.h> #include <linux/sched/autogroup.h> #include <linux/sched/cpufreq.h>
@@ -1190,6 +1191,12 @@ static inline bool is_migration_disabled } DECLARE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues); +DECLARE_PER_CPU(struct rnd_state, sched_rnd_state); + +static inline u32 sched_rng (void ) +{ +return prandom_u32_state (this_cpu_ptr (&sched_rnd_state)); +}#define cpu_rq (cpu) (&per_cpu(runqueues, (cpu)))#define this_rq () this_cpu_ptr(&runqueues)
kernel/sched/topology.c +6 -0
@@ -1584,6 +1584,12 @@ sd_init(struct sched_domain_topology_lev .last_balance = jiffies, .balance_interval = sd_weight, + +/* 50% success rate */ + .newidle_call = 512, + .newidle_success = 256, + .newidle_ratio = 512, + .max_newidle_lb_cost = 0, .last_decay_max_lb_cost = jiffies, .child = child,
Greg Kroah-Hartman
maintainerPATCH 618/634 ext4: filesystems without casefold feature cannot be mounted with siphash
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lizhi Xu <[email protected]>
commit 985b67cd86392310d9e9326de941c22fc9340eec upstream.
When mounting the ext4 filesystem, if the default hash version is set to DX_HASH_SIPHASH but the casefold feature is not set, exit the mounting.
--- fs/ext4/super.c | 8 ++++++++ 1 file changed, 8 insertions(+)
fs/ext4/super.c +8 -0
@@ -3552,6 +3552,14 @@ int ext4_feature_set_ok(struct super_blo }#endif +if (EXT4_SB (sb)->s_es->s_def_hash_version ==DX_HASH_SIPHASH && + !ext4_has_feature_casefold (sb)) { +ext4_msg (sb,KERN_ERR , +"Filesystem without casefold feature cannot be " +"mounted with siphash" ); +return 0 ; + } +if (readonly)return 1 ;
Greg Kroah-Hartman
maintainerPATCH 619/634 ext4: factor out ext4_hash_info_init()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Yan <[email protected]>
commit db9345d9e6f075e1ec26afadf744078ead935fec upstream.
Factor out ext4_hash_info_init() to simplify __ext4_fill_super(). No functional change.
Stable-dep-of: a2187431c395 ("ext4: fix error message when rejecting the default hash")
--- fs/ext4/super.c | 50 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 20 deletions(-)
fs/ext4/super.c +30 -20
@@ -5043,6 +5043,35 @@ out:return ret; } +static void ext4_hash_info_init (struct super_block *sb) +{ +struct ext4_sb_info *sbi =EXT4_SB (sb); +struct ext4_super_block *es = sbi->s_es; +unsigned int i; + +for (i =0 ; i <4 ; i++) + sbi->s_hash_seed[i] =le32_to_cpu (es->s_hash_seed[i]); + + sbi->s_def_hash_version = es->s_def_hash_version; +if (ext4_has_feature_dir_index (sb)) { + i =le32_to_cpu (es->s_flags); +if (i &EXT2_FLAGS_UNSIGNED_HASH ) + sbi->s_hash_unsigned =3 ; +else if ((i &EXT2_FLAGS_SIGNED_HASH ) ==0 ) { +#ifdef __CHAR_UNSIGNED__ +if (!sb_rdonly (sb)) + es->s_flags |= +cpu_to_le32 (EXT2_FLAGS_UNSIGNED_HASH ); + sbi->s_hash_unsigned =3 ; +#else +if (!sb_rdonly (sb)) + es->s_flags |= +cpu_to_le32 (EXT2_FLAGS_SIGNED_HASH ); +#endif + } + } +} +static int __ext4_fill_super (struct fs_context *fc,struct super_block *sb) {struct ext4_super_block *es =NULL ;
@@ -5195,26 +5224,7 @@ static int __ext4_fill_super(struct fs_c sbi->s_addr_per_block_bits =ilog2 (EXT4_ADDR_PER_BLOCK (sb)); sbi->s_desc_per_block_bits =ilog2 (EXT4_DESC_PER_BLOCK (sb)); -for (i =0 ; i <4 ; i++) - sbi->s_hash_seed[i] =le32_to_cpu (es->s_hash_seed[i]); - sbi->s_def_hash_version = es->s_def_hash_version; -if (ext4_has_feature_dir_index (sb)) { - i =le32_to_cpu (es->s_flags); -if (i &EXT2_FLAGS_UNSIGNED_HASH ) - sbi->s_hash_unsigned =3 ; -else if ((i &EXT2_FLAGS_SIGNED_HASH ) ==0 ) { -#ifdef __CHAR_UNSIGNED__ -if (!sb_rdonly (sb)) - es->s_flags |= -cpu_to_le32 (EXT2_FLAGS_UNSIGNED_HASH ); - sbi->s_hash_unsigned =3 ; -#else -if (!sb_rdonly (sb)) - es->s_flags |= -cpu_to_le32 (EXT2_FLAGS_SIGNED_HASH ); -#endif - } - } +ext4_hash_info_init (sb);if (ext4_handle_clustersize (sb)) goto failed_mount;
Greg Kroah-Hartman
maintainerPATCH 620/634 ext4: fix error message when rejecting the default hash
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
commit a2187431c395cdfbf144e3536f25468c64fc7cfa upstream.
Commit 985b67cd8639 ("ext4: filesystems without casefold feature cannot be mounted with siphash") properly rejects volumes where s_def_hash_version is set to DX_HASH_SIPHASH, but the check and the error message should not look into casefold setup - a filesystem should never have DX_HASH_SIPHASH as the default hash. Fix it and, since we are there, move the check to ext4_hash_info_init.
be mounted with siphash")
--- fs/ext4/ext4.h | 1 + fs/ext4/super.c | 28 +++++++++++++++++----------- 2 files changed, 18 insertions(+), 11 deletions(-)
fs/ext4/ext4.h +1 -0
@@ -2460,6 +2460,7 @@ static inline __le16 ext4_rec_len_to_dis#define DX_HASH_HALF_MD4_UNSIGNED 4#define DX_HASH_TEA_UNSIGNED 5#define DX_HASH_SIPHASH 6 +#define DX_HASH_LAST DX_HASH_SIPHASHstatic inline u32 ext4_chksum (struct ext4_sb_info *sbi,u32 crc,const void *address,unsigned int length)
fs/ext4/super.c +17 -11
@@ -3552,14 +3552,6 @@ int ext4_feature_set_ok(struct super_blo }#endif -if (EXT4_SB (sb)->s_es->s_def_hash_version ==DX_HASH_SIPHASH && - !ext4_has_feature_casefold (sb)) { -ext4_msg (sb,KERN_ERR , -"Filesystem without casefold feature cannot be " -"mounted with siphash" ); -return 0 ; - } -if (readonly)return 1 ;
@@ -5043,16 +5035,27 @@ out:return ret; } -static void ext4_hash_info_init (struct super_block *sb) +static int ext4_hash_info_init (struct super_block *sb) {struct ext4_sb_info *sbi =EXT4_SB (sb);struct ext4_super_block *es = sbi->s_es;unsigned int i; + sbi->s_def_hash_version = es->s_def_hash_version; + +if (sbi->s_def_hash_version >DX_HASH_LAST ) { +ext4_msg (sb,KERN_ERR , +"Invalid default hash set in the superblock" ); +return -EINVAL ; + }else if (sbi->s_def_hash_version ==DX_HASH_SIPHASH ) { +ext4_msg (sb,KERN_ERR , +"SIPHASH is not a valid default hash value" ); +return -EINVAL ; + } +for (i =0 ; i <4 ; i++) sbi->s_hash_seed[i] =le32_to_cpu (es->s_hash_seed[i]); - sbi->s_def_hash_version = es->s_def_hash_version;if (ext4_has_feature_dir_index (sb)) { i =le32_to_cpu (es->s_flags);if (i &EXT2_FLAGS_UNSIGNED_HASH )
@@ -5070,6 +5073,7 @@ static void ext4_hash_info_init(struct s#endif } } +return 0 ; }static int __ext4_fill_super (struct fs_context *fc,struct super_block *sb)
@@ -5224,7 +5228,9 @@ static int __ext4_fill_super(struct fs_c sbi->s_addr_per_block_bits =ilog2 (EXT4_ADDR_PER_BLOCK (sb)); sbi->s_desc_per_block_bits =ilog2 (EXT4_DESC_PER_BLOCK (sb)); -ext4_hash_info_init (sb); + err =ext4_hash_info_init (sb); +if (err) + goto failed_mount;if (ext4_handle_clustersize (sb)) goto failed_mount;
Greg Kroah-Hartman
maintainerPATCH 621/634 pwm: stm32: Always program polarity
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Nyekjaer <[email protected]>
Commit 7346e7a058a2 ("pwm: stm32: Always do lazy disabling") triggered a regression where PWM polarity changes could be ignored.
stm32_pwm_set_polarity() was skipped due to a mismatch between the cached pwm->state.polarity and the actual hardware state, leaving the hardware polarity unchanged.
--- drivers/pwm/pwm-stm32.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/pwm/pwm-stm32.c +1 -2
@@ -458,8 +458,7 @@ static int stm32_pwm_apply(struct pwm_chreturn 0 ; } -if (state->polarity != pwm->state.polarity) -stm32_pwm_set_polarity (priv, pwm->hwpwm, state->polarity); +stm32_pwm_set_polarity (priv, pwm->hwpwm, state->polarity); ret =stm32_pwm_config (priv, pwm->hwpwm, state->duty_cycle, state->period);
Greg Kroah-Hartman
maintainerPATCH 622/634 blk-mq: setup queue ->tag_set before initializing hctx
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Lei <[email protected]>
commit c25c0c9035bb8b28c844dfddeda7b8bdbcfcae95 upstream.
Commit 7b815817aa58 ("blk-mq: add helper for checking if one CPU is mapped to specified hctx") needs to check queue mapping via tag set in hctx's cpuhp handler.
However, q->tag_set may not be setup yet when the cpuhp handler is enabled, then kernel oops is triggered.
Fix the issue by setup queue tag_set before initializing hctx.
--- block/blk-mq.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
block/blk-mq.c +6 -2
@@ -4337,6 +4337,12 @@ int blk_mq_init_allocated_queue(struct bif (!q->poll_cb) goto err_exit; +/* +* ->tag_set has to be setup before initialize hctx, which cpuphp +* handler needs it for checking queue mapping +*/ + q->tag_set = set; +if (blk_mq_alloc_ctxs (q)) goto err_poll;
@@ -4355,8 +4361,6 @@ int blk_mq_init_allocated_queue(struct bINIT_WORK (&q->timeout_work, blk_mq_timeout_work);blk_queue_rq_timeout (q, set->timeout ? set->timeout :30 *HZ ); - q->tag_set = set; - q->queue_flags |=QUEUE_FLAG_MQ_DEFAULT ;blk_mq_update_poll_flag (q);
Greg Kroah-Hartman
maintainerPATCH 623/634 tty: fix tty_port_tty_*hangup() kernel-doc
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiri Slaby (SUSE) <[email protected]>
commit 6241b49540a65a6d5274fa938fd3eb4cbfe2e076 upstream.
The commit below added a new helper, but omitted to move (and add) the corressponding kernel-doc. Do it now.
--- Documentation/driver-api/tty/tty_port.rst | 5 +++-- drivers/tty/tty_port.c | 5 ----- include/linux/tty_port.h | 9 +++++++++ 3 files changed, 12 insertions(+), 7 deletions(-)
Documentation/driver-api/tty/tty_port.rst +3 -2
@@ -42,9 +42,10 @@ TTY Refcounting TTY Helpers ----------- +.. kernel-doc:: include/linux/tty_port.h + :identifiers: tty_port_tty_hangup tty_port_tty_vhangup .. kernel-doc:: drivers/tty/tty_port.c - :identifiers: tty_port_tty_hangup tty_port_tty_wakeup - + :identifiers: tty_port_tty_wakeup Modem Signals -------------
drivers/tty/tty_port.c +0 -5
@@ -411,11 +411,6 @@ void tty_port_hangup(struct tty_port *po }EXPORT_SYMBOL (tty_port_hangup); -/** -* tty_port_tty_hangup - helper to hang up a tty -* @port: tty port -* @check_clocal: hang only ttys with %CLOCAL unset? -*/ void __tty_port_tty_hangup (struct tty_port *port,bool check_clocal,bool async) {struct tty_struct *tty =tty_port_tty_get (port);
include/linux/tty_port.h +9 -0
@@ -253,11 +253,20 @@ static inline int tty_port_users(structreturn port->count + port->blocked_open; } +/** +* tty_port_tty_hangup - helper to hang up a tty asynchronously +* @port: tty port +* @check_clocal: hang only ttys with %CLOCAL unset? +*/ static inline void tty_port_tty_hangup (struct tty_port *port,bool check_clocal) {__tty_port_tty_hangup (port, check_clocal, true); } +/** +* tty_port_tty_vhangup - helper to hang up a tty synchronously +* @port: tty port +*/ static inline void tty_port_tty_vhangup (struct tty_port *port) {__tty_port_tty_hangup (port, false, false);
Greg Kroah-Hartman
maintainerPATCH 624/634 firmware: arm_scmi: Fix unused notifier-block in unregister
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amitai Gottlieb <[email protected]>
In scmi_devm_notifier_unregister(), the notifier-block argument was ignored and never passed to devres_release(). As a result, the function always returned -ENOENT and failed to unregister the notifier.
Drivers that depend on this helper for teardown could therefore hit unexpected failures, including kernel panics.
Commit 264a2c520628 ("firmware: arm_scmi: Simplify scmi_devm_notifier_unregister") removed the faulty code path during refactoring and hence this fix is not required upstream.
--- drivers/firmware/arm_scmi/notify.c | 1 + 1 file changed, 1 insertion(+)
drivers/firmware/arm_scmi/notify.c +1 -0
@@ -1539,6 +1539,7 @@ static int scmi_devm_notifier_unregister dres.handle = sdev->handle; dres.proto_id = proto_id; dres.evt_id = evt_id; + dres.nb = nb;if (src_id) { dres.__src_id = *src_id; dres.src_id = &dres.__src_id;
Greg Kroah-Hartman
maintainerPATCH 625/634 Revert "iommu/amd: Skip enabling command/event buffers for kdump"
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Greg Kroah-Hartman <[email protected]>
This reverts commit f33890f95140660923003ba1e2f114dee20e691b which is commit 9be15fbfc6c5c89c22cf6e209f66ea43ee0e58bb upstream.
This causes problems in older kernel trees as SNP host kdump is not supported in them, so drop it from the stable branches.
--- drivers/iommu/amd/init.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-)
drivers/iommu/amd/init.c +9 -19
@@ -805,16 +805,11 @@ static void iommu_enable_command_buffer(BUG_ON (iommu->cmd_buf ==NULL ); -if (!is_kdump_kernel ()) { -/* -* Command buffer is re-used for kdump kernel and setting -* of MMIO register is not required. -*/ - entry =iommu_virt_to_phys (iommu->cmd_buf); - entry |=MMIO_CMD_SIZE_512 ; -memcpy_toio (iommu->mmio_base +MMIO_CMD_BUF_OFFSET , - &entry,sizeof (entry)); - } + entry =iommu_virt_to_phys (iommu->cmd_buf); + entry |=MMIO_CMD_SIZE_512 ; + +memcpy_toio (iommu->mmio_base +MMIO_CMD_BUF_OFFSET , + &entry,sizeof (entry));amd_iommu_reset_cmd_buffer (iommu); }
@@ -863,15 +858,10 @@ static void iommu_enable_event_buffer(stBUG_ON (iommu->evt_buf ==NULL ); -if (!is_kdump_kernel ()) { -/* -* Event buffer is re-used for kdump kernel and setting -* of MMIO register is not required. -*/ - entry =iommu_virt_to_phys (iommu->evt_buf) |EVT_LEN_MASK ; -memcpy_toio (iommu->mmio_base +MMIO_EVT_BUF_OFFSET , - &entry,sizeof (entry)); - } + entry =iommu_virt_to_phys (iommu->evt_buf) |EVT_LEN_MASK ; + +memcpy_toio (iommu->mmio_base +MMIO_EVT_BUF_OFFSET , + &entry,sizeof (entry));/* set head and tail to zero manually */ writel (0x00 , iommu->mmio_base +MMIO_EVT_HEAD_OFFSET );
Greg Kroah-Hartman
maintainerPATCH 626/634 net: ethtool: fix the error condition in ethtool_get_phy_stats_ethtool()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Su Hui <[email protected]>
commit 0dcc53abf58d572d34c5313de85f607cd33fc691 upstream.
Clang static checker (scan-build) warning:
net/ethtool/ioctl.c:line 2233, column 2 Called function pointer is null (null dereference).
Return '-EOPNOTSUPP' when 'ops->get_ethtool_phy_stats' is NULL to fix this typo error.
--- net/ethtool/ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ethtool/ioctl.c +1 -1
@@ -2132,7 +2132,7 @@ static int ethtool_get_phy_stats_ethtoolconst struct ethtool_ops *ops = dev->ethtool_ops;int n_stats, ret; -if (!ops || !ops->get_sset_count || ops->get_ethtool_phy_stats) +if (!ops || !ops->get_sset_count || !ops->get_ethtool_phy_stats)return -EOPNOTSUPP ; n_stats = ops->get_sset_count (dev,ETH_SS_PHY_STATS );
Greg Kroah-Hartman
maintainerPATCH 627/634 kernel/fork: only call untrack_pfn_clear() on VMAs duplicated for fork()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Hildenbrand <[email protected]>
commit e9f180d7cfde23b9f8eebd60272465176373ab2c upstream.
Not intuitive, but vm_area_dup() located in kernel/fork.c is not only used for duplicating VMAs during fork(), but also for duplicating VMAs when splitting VMAs or when mremap()'ing them.
VM_PFNMAP mappings can at least get ordinarily mremap()'ed (no change in size) and apparently also shrunk during mremap(), which implies duplicating the VMA in __split_vma() first.
In case of ordinary mremap() (no change in size), we first duplicate the VMA in copy_vma_and_data()->copy_vma() to then call untrack_pfn_clear() on the old VMA: we effectively move the VM_PAT reservation. So the untrack_pfn_clear() call on the new VMA duplicating is wrong in that context.
Splitting of VMAs seems problematic, because we don't duplicate/adjust the reservation when splitting the VMA. Instead, in memtype_erase() -- called during zapping/munmap -- we shrink a reservation in case only the end address matches: Assume we split a VMA into A and B, both would share a reservation until B is unmapped.
So when unmapping B, the reservation would be updated to cover only A. When unmapping A, we would properly remove the now-shrunk reservation. That scenario describes the mremap() shrinking (old_size > new_size), where we split + unmap B, and the untrack_pfn_clear() on the new VMA when is wrong.
What if we manage to split a VM_PFNMAP VMA into A and B and unmap A first? It would be broken because we would never free the reservation. Likely, there are ways to trigger such a VMA split outside of mremap().
Affecting other VMA duplication was not intended, vm_area_dup() being used outside of kernel/fork.c was an oversight. So let's fix that for; how to handle VMA splits better should be investigated separately.
With a simple reproducer that uses mprotect() to split such a VMA I can trigger
x86/PAT: pat_mremap:26448 freeing invalid memtype [mem 0x00000000-0x00000fff]
--- kernel/fork.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
kernel/fork.c +5 -4
@@ -476,10 +476,6 @@ struct vm_area_struct *vm_area_dup(struc *new =data_race (*orig);INIT_LIST_HEAD (&new->anon_vma_chain);dup_anon_vma_name (orig, new); - -/* track_pfn_copy() will later take care of copying internal state. */ -if (unlikely (new->vm_flags &VM_PFNMAP )) -untrack_pfn_clear (new); }return new; }
@@ -650,6 +646,11 @@ static __latent_entropy int dup_mmap(str tmp =vm_area_dup (mpnt);if (!tmp) goto fail_nomem; + +/* track_pfn_copy() will later take care of copying internal state. */ +if (unlikely (tmp->vm_flags &VM_PFNMAP )) +untrack_pfn_clear (tmp); + retval =vma_dup_policy (mpnt, tmp);if (retval) goto fail_nomem_policy;
Greg Kroah-Hartman
maintainerPATCH 628/634 mm: (un)track_pfn_copy() fix + doc improvements
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Hildenbrand <[email protected]>
commit 8c56c5dbcf52220cc9be7a36e7f21ebd5939e0b9 upstream.
We got a late smatch warning and some additional review feedback.
smatch warnings:
mm/memory.c:1428 copy_page_range() error: uninitialized symbol 'pfn'.
We actually use the pfn only when it is properly initialized; however, we may pass an uninitialized value to a function -- although it will not use it that likely still is UB in C.
So let's just fix it by always initializing pfn in the caller of track_pfn_copy(), and improving the documentation of track_pfn_copy().
While at it, clarify the doc of untrack_pfn_copy(), that internal checks make sure if we actually have to untrack anything.
--- include/linux/pgtable.h | 9 ++++++--- mm/memory.c | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-)
include/linux/pgtable.h +6 -3
@@ -1196,8 +1196,9 @@ static inline void track_pfn_insert(stru/* * track_pfn_copy is called when a VM_PFNMAP VMA is about to get the page -* tables copied during copy_page_range(). On success, stores the pfn to be -* passed to untrack_pfn_copy(). +* tables copied during copy_page_range(). Will store the pfn to be +* passed to untrack_pfn_copy() only if there is something to be untracked. +* Callers should initialize the pfn to 0. */ static inline int track_pfn_copy (struct vm_area_struct *dst_vma,struct vm_area_struct *src_vma,unsigned long *pfn)
@@ -1207,7 +1208,9 @@ static inline int track_pfn_copy(struct/* * untrack_pfn_copy is called when a VM_PFNMAP VMA failed to copy during -* copy_page_range(), but after track_pfn_copy() was already called. +* copy_page_range(), but after track_pfn_copy() was already called. Can +* be called even if track_pfn_copy() did not actually track anything: +* handled internally. */ static inline void untrack_pfn_copy (struct vm_area_struct *dst_vma,unsigned long pfn)
mm/memory.c +1 -1
@@ -1283,7 +1283,7 @@ copy_page_range(struct vm_area_struct *dstruct mm_struct *dst_mm = dst_vma->vm_mm;struct mm_struct *src_mm = src_vma->vm_mm;struct mmu_notifier_range range; -unsigned long next, pfn; +unsigned long next, pfn =0 ;bool is_cow;int ret;
Greg Kroah-Hartman
maintainerPATCH 629/634 usb: gadget: lpc32xx_udc: fix clock imbalance in error path
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 782be79e4551550d7a82b1957fc0f7347e6d461f upstream.
A recent change fixing a device reference leak introduced a clock imbalance by reusing an error path so that the clock may be disabled before having been enabled.
Note that the clock framework allows for passing in NULL clocks so there is no risk for a NULL pointer dereference.
Also drop the bogus I2C client NULL check added by the offending commit as the pointer has already been verified to be non-NULL.
--- drivers/usb/gadget/udc/lpc32xx_udc.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-)
drivers/usb/gadget/udc/lpc32xx_udc.c +9 -10
@@ -3027,7 +3027,7 @@ static int lpc32xx_udc_probe(struct plat pdev->dev.dma_mask = &lpc32xx_usbd_dmamask; retval =dma_set_coherent_mask (&pdev->dev,DMA_BIT_MASK (32 ));if (retval) - goto i2c_fail; + goto err_put_client; udc->board = &lpc32xx_usbddata;
@@ -3047,7 +3047,7 @@ static int lpc32xx_udc_probe(struct plat udc->udp_irq[i] =platform_get_irq (pdev, i);if (udc->udp_irq[i] <0 ) { retval = udc->udp_irq[i]; - goto i2c_fail; + goto err_put_client; } }
@@ -3055,7 +3055,7 @@ static int lpc32xx_udc_probe(struct platif (IS_ERR (udc->udp_baseaddr)) {dev_err (udc->dev,"IO map failure\n" ); retval =PTR_ERR (udc->udp_baseaddr); - goto i2c_fail; + goto err_put_client; }/* Get USB device clock */
@@ -3063,14 +3063,14 @@ static int lpc32xx_udc_probe(struct platif (IS_ERR (udc->usb_slv_clk)) {dev_err (udc->dev,"failed to acquire USB device clock\n" ); retval =PTR_ERR (udc->usb_slv_clk); - goto i2c_fail; + goto err_put_client; }/* Enable USB device clock */ retval =clk_prepare_enable (udc->usb_slv_clk);if (retval <0 ) {dev_err (udc->dev,"failed to start USB device clock\n" ); - goto i2c_fail; + goto err_put_client; }/* Setup deferred workqueue data */
@@ -3172,9 +3172,10 @@ dma_alloc_fail:dma_free_coherent (&pdev->dev,UDCA_BUFF_SIZE , udc->udca_v_base, udc->udca_p_base); i2c_fail: -if (udc->isp1301_i2c_client) -put_device (&udc->isp1301_i2c_client->dev);clk_disable_unprepare (udc->usb_slv_clk); +err_put_client: +put_device (&udc->isp1301_i2c_client->dev); +dev_err (udc->dev,"%s probe failed, %d\n" , driver_name, retval);return retval;
@@ -3199,11 +3200,9 @@ static int lpc32xx_udc_remove(struct pladma_free_coherent (&pdev->dev,UDCA_BUFF_SIZE , udc->udca_v_base, udc->udca_p_base); -if (udc->isp1301_i2c_client) -put_device (&udc->isp1301_i2c_client->dev); -clk_disable_unprepare (udc->usb_slv_clk); +put_device (&udc->isp1301_i2c_client->dev);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 630/634 net: stmmac: fix incorrect rxq|txq_stats reference
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jisheng Zhang <[email protected]>
commit 8070274b472e2e9f5f67a990f5e697634c415708 upstream.
commit 133466c3bbe1 ("net: stmmac: use per-queue 64 bit statistics where necessary") caused one regression as found by Uwe, the backtrace looks like:
INFO: trying to register non-static key. The code is fine but needs lockdep annotation, or maybe you didn't initialize this object before use? turning off the locking correctness validator. CPU: 0 PID: 1 Comm: swapper/0 Not tainted 6.5.0-rc1-00449-g133466c3bbe1-dirty #21 Hardware name: STM32 (Device Tree Support) unwind_backtrace from show_stack+0x18/0x1c show_stack from dump_stack_lvl+0x60/0x90 dump_stack_lvl from register_lock_class+0x98c/0x99c register_lock_class from __lock_acquire+0x74/0x293c __lock_acquire from lock_acquire+0x134/0x398 lock_acquire from stmmac_get_stats64+0x2ac/0x2fc stmmac_get_stats64 from dev_get_stats+0x44/0x130 dev_get_stats from rtnl_fill_stats+0x38/0x120 rtnl_fill_stats from rtnl_fill_ifinfo+0x834/0x17f4 rtnl_fill_ifinfo from rtmsg_ifinfo_build_skb+0xc0/0x144 rtmsg_ifinfo_build_skb from rtmsg_ifinfo+0x50/0x88 rtmsg_ifinfo from __dev_notify_flags+0xc0/0xec __dev_notify_flags from dev_change_flags+0x50/0x5c dev_change_flags from ip_auto_config+0x2f4/0x1260 ip_auto_config from do_one_initcall+0x70/0x35c do_one_initcall from kernel_init_freeable+0x2ac/0x308 kernel_init_freeable from kernel_init+0x1c/0x138 kernel_init from ret_from_fork+0x14/0x2c
The reason is the rxq|txq_stats structures are not what expected because stmmac_open() -> __stmmac_open() the structure is overwritten by "memcpy(&priv->dma_conf, dma_conf, sizeof(*dma_conf));" This causes the well initialized syncp member of rxq|txq_stats is overwritten unexpectedly as pointed out by Johannes and Uwe.
Fix this issue by moving rxq|txq_stats back to stmmac_extra_stats. For SMP cache friendly, we also mark stmmac_txq_stats and stmmac_rxq_stats as ____cacheline_aligned_in_smp.
--- drivers/net/ethernet/stmicro/stmmac/common.h | 7 - drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 16 +- drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c | 16 +- drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c | 16 +- drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 16 +- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 32 ++-- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 127 ++++++++++--------- 8 files changed, 121 insertions(+), 111 deletions(-)
drivers/net/ethernet/stmicro/stmmac/common.h +5 -2
@@ -69,7 +69,7 @@ struct stmmac_txq_stats {u64 tx_tso_frames;u64 tx_tso_nfrags;struct u64_stats_sync syncp; -}; +}____cacheline_aligned_in_smp ;struct stmmac_rxq_stats {u64 rx_bytes;
@@ -78,7 +78,7 @@ struct stmmac_rxq_stats {u64 rx_normal_irq_n;u64 napi_poll;struct u64_stats_sync syncp; -}; +}____cacheline_aligned_in_smp ;/* Extra statistic and debug information exposed by ethtool */ struct stmmac_extra_stats {
@@ -201,6 +201,9 @@ struct stmmac_extra_stats {unsigned long mtl_est_hlbf;unsigned long mtl_est_btre;unsigned long mtl_est_btrlm; +/* per queue statistics */ +struct stmmac_txq_stats txq_stats[MTL_MAX_TX_QUEUES ]; +struct stmmac_rxq_stats rxq_stats[MTL_MAX_RX_QUEUES ];unsigned long rx_dropped;unsigned long rx_errors;unsigned long tx_dropped;
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +8 -8
@@ -440,8 +440,8 @@ static int sun8i_dwmac_dma_interrupt(str struct stmmac_extra_stats *x, u32 chan, u32 dir) { - struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[chan]; -struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[chan]; + struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan]; +struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];int ret =0 ;u32 v;
@@ -454,9 +454,9 @@ static int sun8i_dwmac_dma_interrupt(strif (v &EMAC_TX_INT ) { ret |= handle_tx; -u64_stats_update_begin (&tx_q->txq_stats.syncp); - tx_q->txq_stats.tx_normal_irq_n++; -u64_stats_update_end (&tx_q->txq_stats.syncp); +u64_stats_update_begin (&txq_stats->syncp); + txq_stats->tx_normal_irq_n++; +u64_stats_update_end (&txq_stats->syncp); }if (v &EMAC_TX_DMA_STOP_INT )
@@ -478,9 +478,9 @@ static int sun8i_dwmac_dma_interrupt(strif (v &EMAC_RX_INT ) { ret |= handle_rx; -u64_stats_update_begin (&rx_q->rxq_stats.syncp); - rx_q->rxq_stats.rx_normal_irq_n++; -u64_stats_update_end (&rx_q->rxq_stats.syncp); +u64_stats_update_begin (&rxq_stats->syncp); + rxq_stats->rx_normal_irq_n++; +u64_stats_update_end (&rxq_stats->syncp); }if (v &EMAC_RX_BUF_UA_INT )
drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c +8 -8
@@ -171,8 +171,8 @@ int dwmac4_dma_interrupt(struct stmmac_pconst struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;u32 intr_status =readl (ioaddr +DMA_CHAN_STATUS (dwmac4_addrs, chan));u32 intr_en =readl (ioaddr +DMA_CHAN_INTR_ENA (dwmac4_addrs, chan)); -struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[chan]; -struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[chan]; +struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan]; +struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];int ret =0 ;if (dir ==DMA_DIR_RX )
@@ -201,15 +201,15 @@ int dwmac4_dma_interrupt(struct stmmac_p }/* TX/RX NORMAL interrupts */ if (likely (intr_status &DMA_CHAN_STATUS_RI )) { -u64_stats_update_begin (&rx_q->rxq_stats.syncp); - rx_q->rxq_stats.rx_normal_irq_n++; -u64_stats_update_end (&rx_q->rxq_stats.syncp); +u64_stats_update_begin (&rxq_stats->syncp); + rxq_stats->rx_normal_irq_n++; +u64_stats_update_end (&rxq_stats->syncp); ret |= handle_rx; }if (likely (intr_status &DMA_CHAN_STATUS_TI )) { -u64_stats_update_begin (&tx_q->txq_stats.syncp); - tx_q->txq_stats.tx_normal_irq_n++; -u64_stats_update_end (&tx_q->txq_stats.syncp); +u64_stats_update_begin (&txq_stats->syncp); + txq_stats->tx_normal_irq_n++; +u64_stats_update_end (&txq_stats->syncp); ret |= handle_tx; }
drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c +8 -8
@@ -162,8 +162,8 @@ static void show_rx_process_state(unsignint dwmac_dma_interrupt (struct stmmac_priv *priv,void __iomem *ioaddr,struct stmmac_extra_stats *x,u32 chan,u32 dir) { -struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[chan]; -struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[chan]; +struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan]; +struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];int ret =0 ;/* read the status register (CSR5) */ u32 intr_status =readl (ioaddr +DMA_STATUS );
@@ -215,16 +215,16 @@ int dwmac_dma_interrupt(struct stmmac_pru32 value =readl (ioaddr +DMA_INTR_ENA );/* to schedule NAPI on real RIE event. */ if (likely (value &DMA_INTR_ENA_RIE )) { -u64_stats_update_begin (&rx_q->rxq_stats.syncp); - rx_q->rxq_stats.rx_normal_irq_n++; -u64_stats_update_end (&rx_q->rxq_stats.syncp); +u64_stats_update_begin (&rxq_stats->syncp); + rxq_stats->rx_normal_irq_n++; +u64_stats_update_end (&rxq_stats->syncp); ret |= handle_rx; } }if (likely (intr_status &DMA_STATUS_TI )) { -u64_stats_update_begin (&tx_q->txq_stats.syncp); - tx_q->txq_stats.tx_normal_irq_n++; -u64_stats_update_end (&tx_q->txq_stats.syncp); +u64_stats_update_begin (&txq_stats->syncp); + txq_stats->tx_normal_irq_n++; +u64_stats_update_end (&txq_stats->syncp); ret |= handle_tx; }if (unlikely (intr_status &DMA_STATUS_ERI ))
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +8 -8
@@ -333,8 +333,8 @@ static int dwxgmac2_dma_interrupt(struct struct stmmac_extra_stats *x, u32 chan, u32 dir) { - struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[chan]; -struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[chan]; + struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan]; +struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan];u32 intr_status =readl (ioaddr +XGMAC_DMA_CH_STATUS (chan));u32 intr_en =readl (ioaddr +XGMAC_DMA_CH_INT_EN (chan));int ret =0 ;
@@ -363,15 +363,15 @@ static int dwxgmac2_dma_interrupt(struct/* TX/RX NORMAL interrupts */ if (likely (intr_status &XGMAC_NIS )) {if (likely (intr_status &XGMAC_RI )) { -u64_stats_update_begin (&rx_q->rxq_stats.syncp); - rx_q->rxq_stats.rx_normal_irq_n++; -u64_stats_update_end (&rx_q->rxq_stats.syncp); +u64_stats_update_begin (&rxq_stats->syncp); + rxq_stats->rx_normal_irq_n++; +u64_stats_update_end (&rxq_stats->syncp); ret |= handle_rx; }if (likely (intr_status & (XGMAC_TI |XGMAC_TBU ))) { -u64_stats_update_begin (&tx_q->txq_stats.syncp); - tx_q->txq_stats.tx_normal_irq_n++; -u64_stats_update_end (&tx_q->txq_stats.syncp); +u64_stats_update_begin (&txq_stats->syncp); + txq_stats->tx_normal_irq_n++; +u64_stats_update_end (&txq_stats->syncp); ret |= handle_tx; } }
drivers/net/ethernet/stmicro/stmmac/stmmac.h +0 -2
@@ -77,7 +77,6 @@ struct stmmac_tx_queue {dma_addr_t dma_tx_phy;dma_addr_t tx_tail_addr;u32 mss; -struct stmmac_txq_stats txq_stats; };struct stmmac_rx_buffer {
@@ -119,7 +118,6 @@ struct stmmac_rx_queue {unsigned int len;unsigned int error; } state; -struct stmmac_rxq_stats rxq_stats; };struct stmmac_channel {
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +16 -16
@@ -557,14 +557,14 @@ static void stmmac_get_per_qstats(struct pos = data;for (q =0 ; q < tx_cnt; q++) { -struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[q]; +struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[q];struct stmmac_txq_stats snapshot; data = pos;do { - start =u64_stats_fetch_begin (&tx_q->txq_stats.syncp); - snapshot = tx_q->txq_stats; - }while (u64_stats_fetch_retry (&tx_q->txq_stats.syncp, start)); + start =u64_stats_fetch_begin (&txq_stats->syncp); + snapshot = *txq_stats; + }while (u64_stats_fetch_retry (&txq_stats->syncp, start)); p = (char *)&snapshot + offsetof(struct stmmac_txq_stats , tx_pkt_n);for (stat =0 ; stat <STMMAC_TXQ_STATS ; stat++) {
@@ -575,14 +575,14 @@ static void stmmac_get_per_qstats(struct pos = data;for (q =0 ; q < rx_cnt; q++) { -struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[q]; +struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[q];struct stmmac_rxq_stats snapshot; data = pos;do { - start =u64_stats_fetch_begin (&rx_q->rxq_stats.syncp); - snapshot = rx_q->rxq_stats; - }while (u64_stats_fetch_retry (&rx_q->rxq_stats.syncp, start)); + start =u64_stats_fetch_begin (&rxq_stats->syncp); + snapshot = *rxq_stats; + }while (u64_stats_fetch_retry (&rxq_stats->syncp, start)); p = (char *)&snapshot + offsetof(struct stmmac_rxq_stats , rx_pkt_n);for (stat =0 ; stat <STMMAC_RXQ_STATS ; stat++) {
@@ -646,14 +646,14 @@ static void stmmac_get_ethtool_stats(str pos = j;for (i =0 ; i < rx_queues_count; i++) { -struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[i]; +struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[i];struct stmmac_rxq_stats snapshot; j = pos;do { - start =u64_stats_fetch_begin (&rx_q->rxq_stats.syncp); - snapshot = rx_q->rxq_stats; - }while (u64_stats_fetch_retry (&rx_q->rxq_stats.syncp, start)); + start =u64_stats_fetch_begin (&rxq_stats->syncp); + snapshot = *rxq_stats; + }while (u64_stats_fetch_retry (&rxq_stats->syncp, start)); data[j++] += snapshot.rx_pkt_n; data[j++] += snapshot.rx_normal_irq_n;
@@ -663,14 +663,14 @@ static void stmmac_get_ethtool_stats(str pos = j;for (i =0 ; i < tx_queues_count; i++) { -struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[i]; +struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[i];struct stmmac_txq_stats snapshot; j = pos;do { - start =u64_stats_fetch_begin (&tx_q->txq_stats.syncp); - snapshot = tx_q->txq_stats; - }while (u64_stats_fetch_retry (&tx_q->txq_stats.syncp, start)); + start =u64_stats_fetch_begin (&txq_stats->syncp); + snapshot = *txq_stats; + }while (u64_stats_fetch_retry (&txq_stats->syncp, start)); data[j++] += snapshot.tx_pkt_n; data[j++] += snapshot.tx_normal_irq_n;
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +68 -59
285 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 631/634 net: stmmac: fix ethtool per-queue statistics
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Petr Tesarik <[email protected]>
commit 61921bdaa132b580b6db6858e6d7dcdb870df5fe upstream.
Fix per-queue statistics for devices with more than one queue.
The output data pointer is currently reset in each loop iteration, effectively summing all queue statistics in the first four u64 values.
The summary values are not even labeled correctly. For example, if eth0 has 2 queues, ethtool -S eth0 shows:
q0_tx_pkt_n: 374 (actually tx_pkt_n over all queues)
q0_tx_irq_n: 23 (actually tx_normal_irq_n over all queues)
q1_tx_pkt_n: 462 (actually rx_pkt_n over all queues)
q1_tx_irq_n: 446 (actually rx_normal_irq_n over all queues)
q0_rx_pkt_n: 0
q0_rx_irq_n: 0
q1_rx_pkt_n: 0
q1_rx_irq_n: 0
--- drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +2 -7
@@ -552,15 +552,12 @@ static void stmmac_get_per_qstats(structu32 rx_cnt = priv->plat->rx_queues_to_use;unsigned int start;int q, stat; -u64 *pos;char *p; - pos = data;for (q =0 ; q < tx_cnt; q++) {struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[q];struct stmmac_txq_stats snapshot; - data = pos; do { start = u64_stats_fetch_begin(&txq_stats->syncp); snapshot = *txq_stats;
@@ -568,17 +565,15 @@ static void stmmac_get_per_qstats(struct p = (char *)&snapshot + offsetof(struct stmmac_txq_stats , tx_pkt_n);for (stat =0 ; stat <STMMAC_TXQ_STATS ; stat++) { - *data++ += (*(u64 *)p); + *data++ = (*(u64 *)p); p +=sizeof (u64); } } - pos = data;for (q =0 ; q < rx_cnt; q++) {struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[q];struct stmmac_rxq_stats snapshot; - data = pos; do { start = u64_stats_fetch_begin(&rxq_stats->syncp); snapshot = *rxq_stats;
@@ -586,7 +581,7 @@ static void stmmac_get_per_qstats(struct p = (char *)&snapshot + offsetof(struct stmmac_rxq_stats , rx_pkt_n);for (stat =0 ; stat <STMMAC_RXQ_STATS ; stat++) { - *data++ += (*(u64 *)p); + *data++ = (*(u64 *)p); p +=sizeof (u64); } }
Greg Kroah-Hartman
maintainerPATCH 632/634 net: stmmac: protect updates of 64-bit statistics counters
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Petr Tesarik <[email protected]>
commit 38cc3c6dcc09dc3a1800b5ec22aef643ca11eab8 upstream.
As explained by a comment in <linux/u64_stats_sync.h>, write side of struct u64_stats_sync must ensure mutual exclusion, or one seqcount update could be lost on 32-bit platforms, thus blocking readers forever. Such lockups have been observed in real world after stmmac_xmit() on one CPU raced with stmmac_napi_poll_tx() on another CPU.
To fix the issue without introducing a new lock, split the statics into three parts:
1. fields updated only under the tx queue lock,
2. fields updated only during NAPI poll,
3. fields updated only from interrupt context,
Updates to fields in the first two groups are already serialized through other locks. It is sufficient to split the existing struct u64_stats_sync so that each group has its own.
Note that tx_set_ic_bit is updated from both contexts. Split this counter so that each context gets its own, and calculate their sum to get the total value in stmmac_get_ethtool_stats().
For the third group, multiple interrupts may be processed by different CPUs at the same time, but interrupts on the same CPU will not nest. Move fields from this group to a newly created per-cpu struct stmmac_pcpu_stats.
--- drivers/net/ethernet/stmicro/stmmac/common.h | 56 +++++--- drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 15 +- drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c | 15 +- drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c | 15 +- drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 15 +- drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 129 ++++++++++++------ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 133 +++++++++---------- 7 files changed, 221 insertions(+), 157 deletions(-)
drivers/net/ethernet/stmicro/stmmac/common.h +40 -16
@@ -58,28 +58,51 @@#undef FRAME_FILTER_DEBUG/* #define FRAME_FILTER_DEBUG */ +struct stmmac_q_tx_stats { +u64_stats_t tx_bytes; +u64_stats_t tx_set_ic_bit; +u64_stats_t tx_tso_frames; +u64_stats_t tx_tso_nfrags; +}; + +struct stmmac_napi_tx_stats { +u64_stats_t tx_packets; +u64_stats_t tx_pkt_n; +u64_stats_t poll; +u64_stats_t tx_clean; +u64_stats_t tx_set_ic_bit; +}; +struct stmmac_txq_stats { -u64 tx_bytes; -u64 tx_packets; -u64 tx_pkt_n; -u64 tx_normal_irq_n; -u64 napi_poll; -u64 tx_clean; -u64 tx_set_ic_bit; -u64 tx_tso_frames; -u64 tx_tso_nfrags; -struct u64_stats_sync syncp; +/* Updates protected by tx queue lock. */ +struct u64_stats_sync q_syncp; +struct stmmac_q_tx_stats q; + +/* Updates protected by NAPI poll logic. */ +struct u64_stats_sync napi_syncp; +struct stmmac_napi_tx_stats napi; }____cacheline_aligned_in_smp ; +struct stmmac_napi_rx_stats { +u64_stats_t rx_bytes; +u64_stats_t rx_packets; +u64_stats_t rx_pkt_n; +u64_stats_t poll; +}; +struct stmmac_rxq_stats { -u64 rx_bytes; -u64 rx_packets; -u64 rx_pkt_n; -u64 rx_normal_irq_n; -u64 napi_poll; -struct u64_stats_sync syncp; +/* Updates protected by NAPI poll logic. */ +struct u64_stats_sync napi_syncp; +struct stmmac_napi_rx_stats napi; }____cacheline_aligned_in_smp ; +/* Updates on each CPU protected by not allowing nested irqs. */ +struct stmmac_pcpu_stats { +struct u64_stats_sync syncp; +u64_stats_t rx_normal_irq_n[MTL_MAX_TX_QUEUES ]; +u64_stats_t tx_normal_irq_n[MTL_MAX_RX_QUEUES ]; +}; +/* Extra statistic and debug information exposed by ethtool */ struct stmmac_extra_stats {/* Transmit errors */
@@ -204,6 +227,7 @@ struct stmmac_extra_stats {/* per queue statistics */ struct stmmac_txq_stats txq_stats[MTL_MAX_TX_QUEUES ];struct stmmac_rxq_stats rxq_stats[MTL_MAX_RX_QUEUES ]; +struct stmmac_pcpu_stats __percpu *pcpu_stats;unsigned long rx_dropped;unsigned long rx_errors;unsigned long tx_dropped;
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +7 -8
@@ -440,8 +440,7 @@ static int sun8i_dwmac_dma_interrupt(str struct stmmac_extra_stats *x, u32 chan, u32 dir) { - struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan]; -struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan]; + struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats);int ret =0 ;u32 v;
@@ -454,9 +453,9 @@ static int sun8i_dwmac_dma_interrupt(strif (v &EMAC_TX_INT ) { ret |= handle_tx; -u64_stats_update_begin (&txq_stats->syncp); - txq_stats->tx_normal_irq_n++; -u64_stats_update_end (&txq_stats->syncp); +u64_stats_update_begin (&stats->syncp); +u64_stats_inc (&stats->tx_normal_irq_n[chan]); +u64_stats_update_end (&stats->syncp); }if (v &EMAC_TX_DMA_STOP_INT )
@@ -478,9 +477,9 @@ static int sun8i_dwmac_dma_interrupt(strif (v &EMAC_RX_INT ) { ret |= handle_rx; -u64_stats_update_begin (&rxq_stats->syncp); - rxq_stats->rx_normal_irq_n++; -u64_stats_update_end (&rxq_stats->syncp); +u64_stats_update_begin (&stats->syncp); +u64_stats_inc (&stats->rx_normal_irq_n[chan]); +u64_stats_update_end (&stats->syncp); }if (v &EMAC_RX_BUF_UA_INT )
drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c +7 -8
@@ -171,8 +171,7 @@ int dwmac4_dma_interrupt(struct stmmac_pconst struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;u32 intr_status =readl (ioaddr +DMA_CHAN_STATUS (dwmac4_addrs, chan));u32 intr_en =readl (ioaddr +DMA_CHAN_INTR_ENA (dwmac4_addrs, chan)); -struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan]; -struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan]; +struct stmmac_pcpu_stats *stats =this_cpu_ptr (priv->xstats.pcpu_stats);int ret =0 ;if (dir ==DMA_DIR_RX )
@@ -201,15 +200,15 @@ int dwmac4_dma_interrupt(struct stmmac_p }/* TX/RX NORMAL interrupts */ if (likely (intr_status &DMA_CHAN_STATUS_RI )) { -u64_stats_update_begin (&rxq_stats->syncp); - rxq_stats->rx_normal_irq_n++; -u64_stats_update_end (&rxq_stats->syncp); +u64_stats_update_begin (&stats->syncp); +u64_stats_inc (&stats->rx_normal_irq_n[chan]); +u64_stats_update_end (&stats->syncp); ret |= handle_rx; }if (likely (intr_status &DMA_CHAN_STATUS_TI )) { -u64_stats_update_begin (&txq_stats->syncp); - txq_stats->tx_normal_irq_n++; -u64_stats_update_end (&txq_stats->syncp); +u64_stats_update_begin (&stats->syncp); +u64_stats_inc (&stats->tx_normal_irq_n[chan]); +u64_stats_update_end (&stats->syncp); ret |= handle_tx; }
drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c +7 -8
@@ -162,8 +162,7 @@ static void show_rx_process_state(unsignint dwmac_dma_interrupt (struct stmmac_priv *priv,void __iomem *ioaddr,struct stmmac_extra_stats *x,u32 chan,u32 dir) { -struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan]; -struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan]; +struct stmmac_pcpu_stats *stats =this_cpu_ptr (priv->xstats.pcpu_stats);int ret =0 ;/* read the status register (CSR5) */ u32 intr_status =readl (ioaddr +DMA_STATUS );
@@ -215,16 +214,16 @@ int dwmac_dma_interrupt(struct stmmac_pru32 value =readl (ioaddr +DMA_INTR_ENA );/* to schedule NAPI on real RIE event. */ if (likely (value &DMA_INTR_ENA_RIE )) { -u64_stats_update_begin (&rxq_stats->syncp); - rxq_stats->rx_normal_irq_n++; -u64_stats_update_end (&rxq_stats->syncp); +u64_stats_update_begin (&stats->syncp); +u64_stats_inc (&stats->rx_normal_irq_n[chan]); +u64_stats_update_end (&stats->syncp); ret |= handle_rx; } }if (likely (intr_status &DMA_STATUS_TI )) { -u64_stats_update_begin (&txq_stats->syncp); - txq_stats->tx_normal_irq_n++; -u64_stats_update_end (&txq_stats->syncp); +u64_stats_update_begin (&stats->syncp); +u64_stats_inc (&stats->tx_normal_irq_n[chan]); +u64_stats_update_end (&stats->syncp); ret |= handle_tx; }if (unlikely (intr_status &DMA_STATUS_ERI ))
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +7 -8
@@ -333,8 +333,7 @@ static int dwxgmac2_dma_interrupt(struct struct stmmac_extra_stats *x, u32 chan, u32 dir) { - struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan]; -struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan]; + struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats);u32 intr_status =readl (ioaddr +XGMAC_DMA_CH_STATUS (chan));u32 intr_en =readl (ioaddr +XGMAC_DMA_CH_INT_EN (chan));int ret =0 ;
@@ -363,15 +362,15 @@ static int dwxgmac2_dma_interrupt(struct/* TX/RX NORMAL interrupts */ if (likely (intr_status &XGMAC_NIS )) {if (likely (intr_status &XGMAC_RI )) { -u64_stats_update_begin (&rxq_stats->syncp); - rxq_stats->rx_normal_irq_n++; -u64_stats_update_end (&rxq_stats->syncp); +u64_stats_update_begin (&stats->syncp); +u64_stats_inc (&stats->rx_normal_irq_n[chan]); +u64_stats_update_end (&stats->syncp); ret |= handle_rx; }if (likely (intr_status & (XGMAC_TI |XGMAC_TBU ))) { -u64_stats_update_begin (&txq_stats->syncp); - txq_stats->tx_normal_irq_n++; -u64_stats_update_end (&txq_stats->syncp); +u64_stats_update_begin (&stats->syncp); +u64_stats_inc (&stats->tx_normal_irq_n[chan]); +u64_stats_update_end (&stats->syncp); ret |= handle_tx; } }
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +87 -42
170 lines not on this page · raw message
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +66 -67
273 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 633/634 wifi: nl80211: fix puncturing bitmap policy
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
commit b27f07c50a73e34eefb6b1030b235192b7ded850 upstream.
This was meant to be a u32, and while applying the patch I tried to use policy validation for it. However, not only did I copy/paste it to u8 instead of u32, but also used the policy range erroneously. Fix both of these issues.
--- net/wireless/nl80211.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
net/wireless/nl80211.c +7 -1
@@ -467,6 +467,11 @@ static struct netlink_range_validation q .max = INT_MAX, }; +static struct netlink_range_validation nl80211_punct_bitmap_range = { + .min =0 , + .max =0xffff , +}; +static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR ] = { [0 ] = { .strict_start_type =NL80211_ATTR_HE_OBSS_PD }, [NL80211_ATTR_WIPHY ] = { .type =NLA_U32 },
@@ -810,7 +815,8 @@ static const struct nla_policy nl80211_p [NL80211_ATTR_MLD_ADDR] = NLA_POLICY_EXACT_LEN(ETH_ALEN), [NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG }, [NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_REJECT }, - [NL80211_ATTR_PUNCT_BITMAP] = NLA_POLICY_RANGE(NLA_U8, 0, 0xffff), + [NL80211_ATTR_PUNCT_BITMAP ] = + NLA_POLICY_FULL_RANGE(NLA_U32, &nl80211_punct_bitmap_range), [NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS] = { .type = NLA_U16 }, [NL80211_ATTR_HW_TIMESTAMP_ENABLED] = { .type = NLA_FLAG },
Greg Kroah-Hartman
maintainerPATCH 634/634 wifi: mac80211: fix switch count in EMA beacons
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aditya Kumar Singh <[email protected]>
commit 1afa18e9e72396d1e1aedd6dbb34681f2413316b upstream.
Currently, whenever an EMA beacon is formed, due to is_template argument being false from the caller, the switch count is always decremented once which is wrong.
Also if switch count is equal to profile periodicity, this makes the switch count to reach till zero which triggers a WARN_ON_ONCE.
[ 261.593915] CPU: 1 PID: 800 Comm: kworker/u8:3 Not tainted 5.4.213 #0 [ 261.616143] Hardware name: Qualcomm Technologies, Inc. IPQ9574 [ 261.622666] Workqueue: phy0 ath12k_get_link_bss_conf [ath12k] [ 261.629771] pstate: 60400005 (nZCv daif +PAN -UAO) [ 261.635595] pc : ieee80211_next_txq+0x1ac/0x1b8 [mac80211] [ 261.640282] lr : ieee80211_beacon_update_cntdwn+0x64/0xb4 [mac80211] [...] [ 261.729683] Call trace: [ 261.734986] ieee80211_next_txq+0x1ac/0x1b8 [mac80211] [ 261.737156] ieee80211_beacon_cntdwn_is_complete+0xa28/0x1194 [mac80211] [ 261.742365] ieee80211_beacon_cntdwn_is_complete+0xef4/0x1194 [mac80211] [ 261.749224] ieee80211_beacon_get_template_ema_list+0x38/0x5c [mac80211] [ 261.755908] ath12k_get_link_bss_conf+0xf8/0x33b4 [ath12k] [ 261.762590] ath12k_get_link_bss_conf+0x390/0x33b4 [ath12k] [ 261.767881] process_one_work+0x194/0x270 [ 261.773346] worker_thread+0x200/0x314 [ 261.777514] kthread+0x140/0x150 [ 261.781158] ret_from_fork+0x10/0x18
Fix this issue by making the is_template argument as true when fetching the EMA beacons.
--- net/mac80211/tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/mac80211/tx.c +1 -1
@@ -5456,7 +5456,7 @@ ieee80211_beacon_get_template_ema_list(s {struct ieee80211_ema_beacons *ema_beacons =NULL ; -WARN_ON (__ieee80211_beacon_get (hw, vif,NULL , false, link_id,0 , +WARN_ON (__ieee80211_beacon_get (hw, vif,NULL , true, link_id,0 , &ema_beacons));return ema_beacons;
# Librecast Test Results
020/020 [ OK ] liblcrq
010/010 [ OK ] libmld
120/120 [ OK ] liblibrecast
CPU/kernel: Linux auntie 6.1.160-rc1-00635-gb40085af0da5 #1 SMP PREEMPT_DYNAMIC Fri Jan 9 18:35:00 -00 2026 x86_64 AMD Ryzen 9 9950X 16-Core Processor AuthenticAMD GNU/Linux
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.1.160 release. There are 634 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 Sun, 11 Jan 2026 11:19:41 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.1.160-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.1.y
and the diffstat can be found below.thanks,
greg k-h
On ARCH_BRCMSTB using 32-bit and 64-bit ARM kernels, build tested on BMIPS_GENERIC:
Signature · 1 line
Florian
Quoted 8 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.1.160 release. There are 634 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 Sun, 11 Jan 2026 11:19:41 +0000. Anything received after that time might be too late.
6.1.160-rc1 built and run on my x86_64 test system (AMD Ryzen 9 9900X, System76 thelio-mira-r4-n3). No errors or regressions.
Thanks,
Slade
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.1.160 release. There are 634 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 Sun, 11 Jan 2026 11:19:41 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 9 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.1.160-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.1.y
and the diffstat can be found below.thanks,
greg k-h
Compiled and booted on my test system. No dmesg regressions.
thanks,
-- Shuah
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.1.160 release. There are 634 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 Sun, 11 Jan 2026 11:19:41 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.1.160-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.1.y
and the diffstat can be found below.thanks,
greg k-h
Built and booted successfully on RISC-V RV64 (HiFive Unmatched).
Am 09.01.2026 um 12:34 schrieb Greg Kroah-Hartman:
Quoted 4 lines
This is the start of the stable review cycle for the 6.1.160 release. There are 634 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.
Builds, boots and works on my 2-socket Ivy Bridge Xeon E5-2697 v2 server. No dmesg oddities or regressions found.
Beste Grüße,
Peter Schneider
Signature · 8 lines
Climb the mountain not to plant your flag, but to embrace the challenge, enjoy the air and behold the view. Climb it so you can see the world, not so the world can see you. -- David McCullough Jr. OpenPGP: 0xA3828BD796CCE11A8CADE8866E3A92C92C3FF244 Download: https://www.peters-netzplatz.de/download/pschneider1968_pub.asc https://keys.mailvelope.com/pks/lookup?op=get&[email protected] https://keys.mailvelope.com/pks/lookup?op=get&[email protected]
Quoted 4 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.1.160 release. There are 634 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.
It seems this introduces a regression on Verdin i.MX8MP compared to 6.1.159.
[ 10.209496] Unable to handle kernel paging request at virtual address ffff8001f537c000 [ 10.217443] Mem abort info: [ 10.220242] ESR = 0x0000000096000005 [ 10.223997] EC = 0x25: DABT (current EL), IL = 32 bits [ 10.229317] SET = 0, FnV = 0 [ 10.232376] EA = 0, S1PTW = 0 [ 10.235522] FSC = 0x05: level 1 translation fault [ 10.240404] Data abort info: [ 10.243288] ISV = 0, ISS = 0x00000005 [ 10.247127] CM = 0, WnR = 0 [ 10.250099] swapper pgtable: 4k pages, 48-bit VAs, pgdp=0000000049c42000 [ 10.256806] [ffff8001f537c000] pgd=100000023ffff003, p4d=100000023ffff003, pud=0000000000000000 [ 10.265525] Internal error: Oops: 0000000096000005 [#1] PREEMPT SMP [ 10.271801] Modules linked in: 8021q garp mrp stp llc spidev caam_jr caamhash_desc caamalg_desc bluetooth crypto_engine rng_core authenc libdes ecdh_generic ecc mwifiex_sdio dwmac_imx stmmac_platform stmmac mwifiex cfg80211 imx_sdma pcs_xpcs crct10dif_ce fsl_imx8_ddr_perf etnaviv rfkill gpu_sched governor_userspace imx_bus ina2xx ti_ads1015 snvs_pwrkey industrialio_triggered_buffer lm75 rtc_ds1307 kfifo_buf rtc_snvs flexcan can_dev caam error spi_imx imx8mm_thermal pwm_imx27 imx_cpufreq_dt libcomposite fuse drm ipv6 [ 10.317785] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G W 6.1.160-rc1-6.8.5-devel+git.b40085af0da5 #1 [ 10.328155] Hardware name: Toradex Verdin iMX8M Plus WB on Dahlia Board (DT) [ 10.335215] pstate: 200000c5 (nzCv daIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 10.342195] pc : dwmac4_dma_interrupt+0x120/0x270 [stmmac] [ 10.347750] lr : stmmac_napi_check+0x50/0x1e0 [stmmac] [ 10.352941] sp : ffff800008003e40 [ 10.356262] x29: ffff800008003e40 x28: ffff80000a253f80 x27: 00000000fff0e80c [ 10.363419] x26: ffff80000a253f80 x25: ffff8000097d3c50 x24: ffff80000a5cc07d [ 10.370575] x23: 0000000000000005 x22: 0000000000000005 x21: ffff800008003ea8 [ 10.377729] x20: 0000000000000000 x19: ffff0000c6cc0900 x18: 0000000000000000 [ 10.384885] x17: ffff8001f537c000 x16: ffff800008000000 x15: 0000aaaaf065c7c0 [ 10.392036] x14: 0000001a92b60e94 x13: 0000000000000128 x12: 0000000000000001 [ 10.399190] x11: 0000000000000000 x10: 0000000000000000 x9 : 0000000000000000 [ 10.406345] x8 : 0000000000000000 x7 : ffff8001f537c000 x6 : 000000000000d041 [ 10.413498] x5 : 0000000000008040 x4 : ffff8001f537c000 x3 : 0000000000000000 [ 10.420653] x2 : ffff0000c6cc4540 x1 : ffff80000b330000 x0 : 0000000000000000 [ 10.427811] Call trace: [ 10.430266] dwmac4_dma_interrupt+0x120/0x270 [stmmac] [ 10.435460] stmmac_interrupt+0xb0/0x150 [stmmac] [ 10.440218] __handle_irq_event_percpu+0x5c/0x170 [ 10.444942] handle_irq_event+0x4c/0xc0 [ 10.448791] handle_fasteoi_irq+0xa4/0x1a0 [ 10.452901] handle_irq_desc+0x40/0x60 [ 10.456663] generic_handle_domain_irq+0x1c/0x30 [ 10.461295] gic_handle_irq+0x50/0x130 [ 10.465059] call_on_irq_stack+0x30/0x48 [ 10.468990] do_interrupt_handler+0x80/0x90 [ 10.473185] el1_interrupt+0x34/0x70 [ 10.476780] el1h_64_irq_handler+0x18/0x30 [ 10.480895] el1h_64_irq+0x64/0x68 [ 10.484310] arch_cpu_idle+0x18/0x30 [ 10.487899] default_idle_call+0x30/0x6c [ 10.491831] do_idle+0x248/0x2c0 [ 10.495071] cpu_startup_entry+0x34/0x40 [ 10.499004] rest_init+0xe4/0xf0 [ 10.502246] arch_post_acpi_subsys_init+0x0/0x18 [ 10.506873] start_kernel+0x688/0x6cc [ 10.510551] __primary_switched+0xbc/0xc4 [ 10.514576] Code: 35ffffab 321d0000 17ffffec f9800091 (c85f7c8c) [ 10.520687] ---[ end trace 0000000000000000 ]--- [ 10.525316] Kernel panic - not syncing: Oops: Fatal exception in interrupt [ 10.532199] SMP: stopping secondary CPUs [ 10.536132] Kernel Offset: disabled [ 10.539628] CPU features: 0x000000,00800084,0000421b [ 10.544602] Memory Limit: none [ 10.547664] ---[ end Kernel panic - not syncing: Oops: Fatal exception in interrupt ]---
Thanks,
Francesco
Greg Kroah-Hartman
maintainerQuoted 60 lines · Francesco Dolcini
Quoted 4 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.1.160 release. There are 634 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.
It seems this introduces a regression on Verdin i.MX8MP compared to 6.1.159.
[ 10.209496] Unable to handle kernel paging request at virtual address ffff8001f537c000 [ 10.217443] Mem abort info: [ 10.220242] ESR = 0x0000000096000005 [ 10.223997] EC = 0x25: DABT (current EL), IL = 32 bits [ 10.229317] SET = 0, FnV = 0 [ 10.232376] EA = 0, S1PTW = 0 [ 10.235522] FSC = 0x05: level 1 translation fault [ 10.240404] Data abort info: [ 10.243288] ISV = 0, ISS = 0x00000005 [ 10.247127] CM = 0, WnR = 0 [ 10.250099] swapper pgtable: 4k pages, 48-bit VAs, pgdp=0000000049c42000 [ 10.256806] [ffff8001f537c000] pgd=100000023ffff003, p4d=100000023ffff003, pud=0000000000000000 [ 10.265525] Internal error: Oops: 0000000096000005 [#1] PREEMPT SMP [ 10.271801] Modules linked in: 8021q garp mrp stp llc spidev caam_jr caamhash_desc caamalg_desc bluetooth crypto_engine rng_core authenc libdes ecdh_generic ecc mwifiex_sdio dwmac_imx stmmac_platform stmmac mwifiex cfg80211 imx_sdma pcs_xpcs crct10dif_ce fsl_imx8_ddr_perf etnaviv rfkill gpu_sched governor_userspace imx_bus ina2xx ti_ads1015 snvs_pwrkey industrialio_triggered_buffer lm75 rtc_ds1307 kfifo_buf rtc_snvs flexcan can_dev caam error spi_imx imx8mm_thermal pwm_imx27 imx_cpufreq_dt libcomposite fuse drm ipv6 [ 10.317785] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G W 6.1.160-rc1-6.8.5-devel+git.b40085af0da5 #1 [ 10.328155] Hardware name: Toradex Verdin iMX8M Plus WB on Dahlia Board (DT) [ 10.335215] pstate: 200000c5 (nzCv daIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 10.342195] pc : dwmac4_dma_interrupt+0x120/0x270 [stmmac] [ 10.347750] lr : stmmac_napi_check+0x50/0x1e0 [stmmac] [ 10.352941] sp : ffff800008003e40 [ 10.356262] x29: ffff800008003e40 x28: ffff80000a253f80 x27: 00000000fff0e80c [ 10.363419] x26: ffff80000a253f80 x25: ffff8000097d3c50 x24: ffff80000a5cc07d [ 10.370575] x23: 0000000000000005 x22: 0000000000000005 x21: ffff800008003ea8 [ 10.377729] x20: 0000000000000000 x19: ffff0000c6cc0900 x18: 0000000000000000 [ 10.384885] x17: ffff8001f537c000 x16: ffff800008000000 x15: 0000aaaaf065c7c0 [ 10.392036] x14: 0000001a92b60e94 x13: 0000000000000128 x12: 0000000000000001 [ 10.399190] x11: 0000000000000000 x10: 0000000000000000 x9 : 0000000000000000 [ 10.406345] x8 : 0000000000000000 x7 : ffff8001f537c000 x6 : 000000000000d041 [ 10.413498] x5 : 0000000000008040 x4 : ffff8001f537c000 x3 : 0000000000000000 [ 10.420653] x2 : ffff0000c6cc4540 x1 : ffff80000b330000 x0 : 0000000000000000 [ 10.427811] Call trace: [ 10.430266] dwmac4_dma_interrupt+0x120/0x270 [stmmac] [ 10.435460] stmmac_interrupt+0xb0/0x150 [stmmac] [ 10.440218] __handle_irq_event_percpu+0x5c/0x170 [ 10.444942] handle_irq_event+0x4c/0xc0 [ 10.448791] handle_fasteoi_irq+0xa4/0x1a0 [ 10.452901] handle_irq_desc+0x40/0x60 [ 10.456663] generic_handle_domain_irq+0x1c/0x30 [ 10.461295] gic_handle_irq+0x50/0x130 [ 10.465059] call_on_irq_stack+0x30/0x48 [ 10.468990] do_interrupt_handler+0x80/0x90 [ 10.473185] el1_interrupt+0x34/0x70 [ 10.476780] el1h_64_irq_handler+0x18/0x30 [ 10.480895] el1h_64_irq+0x64/0x68 [ 10.484310] arch_cpu_idle+0x18/0x30 [ 10.487899] default_idle_call+0x30/0x6c [ 10.491831] do_idle+0x248/0x2c0 [ 10.495071] cpu_startup_entry+0x34/0x40 [ 10.499004] rest_init+0xe4/0xf0 [ 10.502246] arch_post_acpi_subsys_init+0x0/0x18 [ 10.506873] start_kernel+0x688/0x6cc [ 10.510551] __primary_switched+0xbc/0xc4
Quoted 8 lines
[ 10.514576] Code: 35ffffab 321d0000 17ffffec f9800091 (c85f7c8c) [ 10.520687] ---[ end trace 0000000000000000 ]--- [ 10.525316] Kernel panic - not syncing: Oops: Fatal exception in interrupt [ 10.532199] SMP: stopping secondary CPUs [ 10.536132] Kernel Offset: disabled [ 10.539628] CPU features: 0x000000,00800084,0000421b [ 10.544602] Memory Limit: none [ 10.547664] ---[ end Kernel panic - not syncing: Oops: Fatal exception in interrupt ]---
Can you run git bisect to find the offending commit?
thanks,
greg k-h
Quoted 8 lines · Greg Kroah-Hartman
Quoted 4 lines · Francesco Dolcini
[ 10.427811] Call trace: [ 10.430266] dwmac4_dma_interrupt+0x120/0x270 [stmmac] [ 10.435460] stmmac_interrupt+0xb0/0x150 [stmmac] [ 10.440218] __handle_irq_event_percpu+0x5c/0x170Can you run git bisect to find the offending commit?
I've got that board as well and am seeing the issue too, the bisect comes out at:
[c657c6cbac472125a03d7bfb6137e6e23ebb7081] net: stmmac: protect updates of 64-bit statistics counters
I'm also seeing bisects of similar boot failures pointing to the same commit on at least i.MX8MP-EVK and Libretech Potato. Bisect log for the board Francesco originally reported, the others all look the same:
# bad: [b40085af0da566f50bdc006adfb80480c7a967be] Linux 6.1.160-rc1
# good: [50cbba13faa294918f0e1a9cb2b0aba19f4e6fba] Linux 6.1.159
git bisect start 'b40085af0da566f50bdc006adfb80480c7a967be' '50cbba13faa294918f0e1a9cb2b0aba19f4e6fba'
# test job: [b40085af0da566f50bdc006adfb80480c7a967be] https://lava.sirena.org.uk/scheduler/job/2358072 # bad: [b40085af0da566f50bdc006adfb80480c7a967be] Linux 6.1.160-rc1 git bisect bad b40085af0da566f50bdc006adfb80480c7a967be # test job: [0eef340004c728d5ed9289b8355b85fd0f746adb] https://lava.sirena.org.uk/scheduler/job/2358118 # good: [0eef340004c728d5ed9289b8355b85fd0f746adb] vhost/vsock: improve RCU read sections around vhost_vsock_get() git bisect good 0eef340004c728d5ed9289b8355b85fd0f746adb # test job: [1bc9e80077c9c82a192884190b47e256fd5c2e04] https://lava.sirena.org.uk/scheduler/job/2358164 # good: [1bc9e80077c9c82a192884190b47e256fd5c2e04] fbdev: pxafb: Fix multiple clamped values in pxafb_adjust_timing git bisect good 1bc9e80077c9c82a192884190b47e256fd5c2e04 # test job: [9a848f3440f502df433309c9bf0e8734a76e8cac] https://lava.sirena.org.uk/scheduler/job/2358225 # good: [9a848f3440f502df433309c9bf0e8734a76e8cac] f2fs: fix to avoid updating compression context during writeback git bisect good 9a848f3440f502df433309c9bf0e8734a76e8cac # test job: [c153ef089aa70781cb00b747f8eb078a95c7286a] https://lava.sirena.org.uk/scheduler/job/2358441 # good: [c153ef089aa70781cb00b747f8eb078a95c7286a] net: Remove RTNL dance for SIOCBRADDIF and SIOCBRDELIF. git bisect good c153ef089aa70781cb00b747f8eb078a95c7286a # test job: [cb3c86df8622d286df0325ac0398a5923afda0b8] https://lava.sirena.org.uk/scheduler/job/2358497 # good: [cb3c86df8622d286df0325ac0398a5923afda0b8] sched/fair: Small cleanup to sched_balance_newidle() git bisect good cb3c86df8622d286df0325ac0398a5923afda0b8 # test job: [c5f4e3a377a77899380d01338b945a843ba4d3c0] https://lava.sirena.org.uk/scheduler/job/2358521 # good: [c5f4e3a377a77899380d01338b945a843ba4d3c0] Revert "iommu/amd: Skip enabling command/event buffers for kdump" git bisect good c5f4e3a377a77899380d01338b945a843ba4d3c0 # test job: [320c50b6fcb19466f63a964c11ef4d5ca0c792d3] https://lava.sirena.org.uk/scheduler/job/2358630 # good: [320c50b6fcb19466f63a964c11ef4d5ca0c792d3] net: stmmac: fix incorrect rxq|txq_stats reference git bisect good 320c50b6fcb19466f63a964c11ef4d5ca0c792d3 # test job: [c657c6cbac472125a03d7bfb6137e6e23ebb7081] https://lava.sirena.org.uk/scheduler/job/2358871 # bad: [c657c6cbac472125a03d7bfb6137e6e23ebb7081] net: stmmac: protect updates of 64-bit statistics counters git bisect bad c657c6cbac472125a03d7bfb6137e6e23ebb7081 # test job: [0c900ef4d40a90b1f0995ac3fbee15b9a0771a4b] https://lava.sirena.org.uk/scheduler/job/2358897 # good: [0c900ef4d40a90b1f0995ac3fbee15b9a0771a4b] net: stmmac: fix ethtool per-queue statistics git bisect good 0c900ef4d40a90b1f0995ac3fbee15b9a0771a4b # first bad commit: [c657c6cbac472125a03d7bfb6137e6e23ebb7081] net: stmmac: protect updates of 64-bit statistics counters
Quoted 3 lines · Mark Brown
I'm also seeing bisects of similar boot failures pointing to the same commit on at least i.MX8MP-EVK and Libretech Potato. Bisect log for the board Francesco originally reported, the others all look the same:
Pine64 Plus, Aveneger 96 and Libretech Tritium are also affected.
Jon Hunter
maintainerQuoted 7 lines · Mark Brown
Quoted 3 lines · Mark Brown
I'm also seeing bisects of similar boot failures pointing to the same commit on at least i.MX8MP-EVK and Libretech Potato. Bisect log for the board Francesco originally reported, the others all look the same:
Pine64 Plus, Aveneger 96 and Libretech Tritium are also affected.
This is impacting some Tegra boards too.
Jon
Signature · 1 line
nvpublic
Greg Kroah-Hartman
maintainerQuoted 4 lines · Jon Hunter
Quoted 2 lines · Mark Brown
On Sat, Jan 10, 2026 at 11:23:20AM +0000, Mark Brown wrote:
Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
I'm also seeing bisects of similar boot failures pointing to the same commit on at least i.MX8MP-EVK and Libretech Potato. Bisect log for the board Francesco originally reported, the others all look the same:
Pine64 Plus, Aveneger 96 and Libretech Tritium are also affected.
This is impacting some Tegra boards too.
Odd, that commit is in released 6.6 and newer kernels. I'll go drop this now and push out a new -rc release, thanks everyone for letting me know!
greg k-h
hello
Compiled and booted 6.1.160-rc1+
No typical new regressions from dmesg.
As per dmidecode command.
Version: AMD Ryzen 3 3250U with Radeon Graphics
Processor Information
Socket Designation: FP5
Type: Central Processor
Family: Zen
Manufacturer: Advanced Micro Devices, Inc.
ID: 81 0F 81 00 FF FB 8B 17
Signature: Family 23, Model 24, Stepping 1
--
software engineer
rajagiri school of engineering and technology
Hi!
Quoted 4 lines
This is the start of the stable review cycle for the 6.1.160 release. There are 634 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.
CIP testing did not find any problems here:
https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/tree/linux-6.1.y
Best regards,
Pavel
Signature · 1 line
In cooperation with Nabla.