5.19.17-rc1 review
Subsystems (9)
Greg Kroah-Hartman
maintainerPATCH 128/717 ext4: unconditionally enable the i_version counter
In reply to Greg Kroah-HartmanFrom: Jeff Layton <[email protected]>
commit 1ff20307393e17dc57fde62226df625a3a3c36e9 upstream.
The original i_version implementation was pretty expensive, requiring a log flush on every change. Because of this, it was gated behind a mount option (implemented via the MS_I_VERSION mountoption flag).
Commit ae5e165d855d (fs: new API for handling inode->i_version) made the i_version flag much less expensive, so there is no longer a performance penalty from enabling it. xfs and btrfs already enable it unconditionally when the on-disk format can support it.
Have ext4 ignore the SB_I_VERSION flag, and just enable it unconditionally. While we're in here, mark the i_version mount option Opt_removed.
[ Removed leftover bits of i_version from ext4_apply_options() since it
now can't ever be set in ctx->mask_s_flags -- lczerner ]
--- fs/ext4/inode.c | 5 ++--- fs/ext4/super.c | 22 +++++----------------- 2 files changed, 7 insertions(+), 20 deletions(-)
fs/ext4/inode.c +2 -3
@@ -5425,7 +5425,7 @@ int ext4_setattr(struct user_namespace *return -EINVAL ; } -if (IS_I_VERSION (inode) && attr->ia_size != inode->i_size) +if (attr->ia_size != inode->i_size)inode_inc_iversion (inode);if (shrink) {
@@ -5735,8 +5735,7 @@ int ext4_mark_iloc_dirty(handle_t *handl* ea_inodes are using i_version for storing reference count, don't * mess with it */ -if (IS_I_VERSION (inode) && - !(EXT4_I (inode)->i_flags &EXT4_EA_INODE_FL )) +if (!(EXT4_I (inode)->i_flags &EXT4_EA_INODE_FL ))inode_inc_iversion (inode);/* the do_update_inode consumes one bh->b_count */
fs/ext4/super.c +5 -17
@@ -1585,7 +1585,7 @@ enum { Opt_inlinecrypt, Opt_usrjquota, Opt_grpjquota, Opt_quota, Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err, - Opt_usrquota, Opt_grpquota, Opt_prjquota, Opt_i_version, + Opt_usrquota, Opt_grpquota, Opt_prjquota, Opt_dax, Opt_dax_always, Opt_dax_inode, Opt_dax_never, Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_warn_on_error, Opt_nowarn_on_error, Opt_mblk_io_submit, Opt_debug_want_extra_isize,
@@ -1694,7 +1694,7 @@ static const struct fs_parameter_spec exfsparam_flag ("barrier" , Opt_barrier),fsparam_u32 ("barrier" , Opt_barrier),fsparam_flag ("nobarrier" , Opt_nobarrier), -fsparam_flag ("i_version" , Opt_i_version), +fsparam_flag ("i_version" , Opt_removed),fsparam_flag ("dax" , Opt_dax),fsparam_enum ("dax" , Opt_dax_type, ext4_param_dax), fsparam_u32 ("stripe", Opt_stripe),
@@ -2140,11 +2140,6 @@ static int ext4_parse_param(struct fs_cocase Opt_abort:ctx_set_mount_flag (ctx,EXT4_MF_FS_ABORTED );return 0 ; -case Opt_i_version: -ext4_msg (NULL ,KERN_WARNING , deprecated_msg, param->key,"5.20" ); -ext4_msg (NULL ,KERN_WARNING ,"Use iversion instead\n" ); -ctx_set_flags (ctx,SB_I_VERSION ); -return 0 ;case Opt_inlinecrypt:#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT ctx_set_flags (ctx,SB_INLINECRYPT );
@@ -2814,14 +2809,6 @@ static void ext4_apply_options(struct fs sb->s_flags &= ~ctx->mask_s_flags; sb->s_flags |= ctx->vals_s_flags; -/* -* i_version differs from common mount option iversion so we have -* to let vfs know that it was set, otherwise it would get cleared -* on remount -*/ -if (ctx->mask_s_flags &SB_I_VERSION ) - fc->sb_flags |=SB_I_VERSION ; -#define APPLY (X ) ({ if (ctx->spec & EXT4_SPEC_##X) sbi->X = ctx->X; })APPLY (s_commit_interval);APPLY (s_stripe);
@@ -2970,8 +2957,6 @@ static int _ext4_show_options(struct seqSEQ_OPTS_PRINT ("min_batch_time=%u" , sbi->s_min_batch_time);if (nodefs || sbi->s_max_batch_time !=EXT4_DEF_MAX_BATCH_TIME )SEQ_OPTS_PRINT ("max_batch_time=%u" , sbi->s_max_batch_time); -if (sb->s_flags &SB_I_VERSION ) -SEQ_OPTS_PUTS ("i_version" );if (nodefs || sbi->s_stripe)SEQ_OPTS_PRINT ("stripe=%lu" , sbi->s_stripe); if (nodefs || EXT4_MOUNT_DATA_FLAGS &
@@ -4631,6 +4616,9 @@ static int __ext4_fill_super(struct fs_c sb->s_flags = (sb->s_flags & ~SB_POSIXACL ) | (test_opt (sb,POSIX_ACL ) ?SB_POSIXACL :0 ); +/* i_version is always enabled now */ + sb->s_flags |=SB_I_VERSION ; + if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV && (ext4_has_compat_features(sb) || ext4_has_ro_compat_features(sb) ||
Greg Kroah-Hartman
maintainerPATCH 129/717 ext4: ext4_read_bh_lock() should submit IO if the buffer isnt uptodate
In reply to Greg Kroah-HartmanFrom: Zhang Yi <[email protected]>
commit 0b73284c564d3ae4feef4bc920292f004acf4980 upstream.
Recently we notice that ext4 filesystem would occasionally fail to read metadata from disk and report error message, but the disk and block layer looks fine. After analyse, we lockon commit 88dbcbb3a484 ("blkdev: avoid migration stalls for blkdev pages"). It provide a migration method for the bdev, we could move page that has buffers without extra users now, but it lock the buffers on the page, which breaks the fragile metadata read operation on ext4 filesystem, ext4_read_bh_lock() was copied from ll_rw_block(), it depends on the assumption of that locked buffer means it is under IO. So it just trylock the buffer and skip submit IO if it lock failed, after wait_on_buffer() we conclude IO error because the buffer is not uptodate.
This issue could be easily reproduced by add some delay just after buffer_migrate_lock_buffers() in __buffer_migrate_folio() and do fsstress on ext4 filesystem.
EXT4-fs error (device pmem1): __ext4_find_entry:1658: inode #73193:
comm fsstress: reading directory lblock 0
EXT4-fs error (device pmem1): __ext4_find_entry:1658: inode #75334:
comm fsstress: reading directory lblock 0
Fix it by removing the trylock logic in ext4_read_bh_lock(), just lock the buffer and submit IO if it's not uptodate, and also leave over readahead helper.
--- fs/ext4/super.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-)
fs/ext4/super.c +5 -11
@@ -205,19 +205,12 @@ int ext4_read_bh(struct buffer_head *bh,int ext4_read_bh_lock (struct buffer_head *bh,int op_flags,bool wait) { -if (trylock_buffer (bh)) { -if (wait) -return ext4_read_bh (bh, op_flags,NULL ); +lock_buffer (bh); +if (!wait) {ext4_read_bh_nowait (bh, op_flags,NULL );return 0 ; } -if (wait) { -wait_on_buffer (bh); -if (buffer_uptodate (bh)) -return 0 ; -return -EIO ; - } -return 0 ; +return ext4_read_bh (bh, op_flags,NULL ); }/*
@@ -264,7 +257,8 @@ void ext4_sb_breadahead_unmovable(structstruct buffer_head *bh =sb_getblk_gfp (sb, block,0 );if (likely (bh)) { -ext4_read_bh_lock (bh,REQ_RAHEAD , false); +if (trylock_buffer (bh)) +ext4_read_bh_nowait (bh,REQ_RAHEAD ,NULL );brelse (bh); } }
Greg Kroah-Hartman
maintainerPATCH 130/717 ext4: place buffer head allocation before handle start
In reply to Greg Kroah-HartmanFrom: Jinke Han <[email protected]>
commit d1052d236eddf6aa851434db1897b942e8db9921 upstream.
In our product environment, we encounter some jbd hung waiting handles to stop while several writters were doing memory reclaim for buffer head allocation in delay alloc write path. Ext4 do buffer head allocation with holding transaction handle which may be blocked too long if the reclaim works not so smooth. According to our bcc trace, the reclaim time in buffer head allocation can reach 258s and the jbd transaction commit also take almost the same time meanwhile. Except for these extreme cases, we often see several seconds delays for cgroup memory reclaim on our servers. This is more likely to happen considering docker environment.
One thing to note, the allocation of buffer heads is as often as page allocation or more often when blocksize less than page size. Just like page cache allocation, we should also place the buffer head allocation before startting the handle.
--- fs/ext4/inode.c | 7 +++++++ 1 file changed, 7 insertions(+)
fs/ext4/inode.c +7 -0
@@ -1188,6 +1188,13 @@ retry_grab: page =grab_cache_page_write_begin (mapping, index);if (!page)return -ENOMEM ; +/* +* The same as page allocation, we prealloc buffer heads before +* starting the handle. +*/ +if (!page_has_buffers (page)) +create_empty_buffers (page, inode->i_sb->s_blocksize,0 ); +unlock_page (page); retry_journal:
Greg Kroah-Hartman
maintainerPATCH 131/717 ext4: fix i_version handling in ext4
In reply to Greg Kroah-HartmanFrom: Jeff Layton <[email protected]>
commit a642c2c0827f5604a93f9fa1e5701eecdce4ae22 upstream.
ext4 currently updates the i_version counter when the atime is updated during a read. This is less than ideal as it can cause unnecessary cache invalidations with NFSv4 and unnecessary remeasurements for IMA.
The increment in ext4_mark_iloc_dirty is also problematic since it can corrupt the i_version counter for ea_inodes. We aren't bumping the file times in ext4_mark_iloc_dirty, so changing the i_version there seems wrong, and is the cause of both problems.
Remove that callsite and add increments to the setattr, setxattr and ioctl codepaths, at the same times that we update the ctime. The i_version bump that already happens during timestamp updates should take care of the rest.
In ext4_move_extents, increment the i_version on both inodes, and also add in missing ctime updates.
[ Some minor updates since we've already enabled the i_version counter
unconditionally already via another patch series. -- TYT ]
--- fs/ext4/inode.c | 14 +++++--------- fs/ext4/ioctl.c | 4 ++++ fs/ext4/xattr.c | 1 + 3 files changed, 10 insertions(+), 9 deletions(-)
fs/ext4/inode.c +5 -9
@@ -5347,6 +5347,7 @@ int ext4_setattr(struct user_namespace *int error, rc =0 ;int orphan =0 ;const unsigned int ia_valid = attr->ia_valid; +bool inc_ivers = true;if (unlikely (ext4_forced_shutdown (EXT4_SB (inode->i_sb))))return -EIO ;
@@ -5432,8 +5433,8 @@ int ext4_setattr(struct user_namespace *return -EINVAL ; } -if (attr->ia_size != inode->i_size) -inode_inc_iversion (inode); +if (attr->ia_size == inode->i_size) + inc_ivers = false;if (shrink) {if (ext4_should_order_data (inode)) {
@@ -5535,6 +5536,8 @@ out_mmap_sem: }if (!error) { +if (inc_ivers) +inode_inc_iversion (inode);setattr_copy (mnt_userns, inode, attr);mark_inode_dirty (inode); }
@@ -5738,13 +5741,6 @@ int ext4_mark_iloc_dirty(handle_t *handl }ext4_fc_track_inode (handle, inode); -/* -* ea_inodes are using i_version for storing reference count, don't -* mess with it -*/ -if (!(EXT4_I (inode)->i_flags &EXT4_EA_INODE_FL )) -inode_inc_iversion (inode); -/* the do_update_inode consumes one bh->b_count */ get_bh (iloc->bh);
fs/ext4/ioctl.c +4 -0
@@ -442,6 +442,7 @@ static long swap_inode_boot_loader(strucswap_inode_data (inode, inode_bl); inode->i_ctime = inode_bl->i_ctime =current_time (inode); +inode_inc_iversion (inode); inode->i_generation =prandom_u32 (); inode_bl->i_generation =prandom_u32 ();
@@ -655,6 +656,7 @@ static int ext4_ioctl_setflags(struct inext4_set_inode_flags (inode, false); inode->i_ctime =current_time (inode); +inode_inc_iversion (inode); err =ext4_mark_iloc_dirty (handle, inode, &iloc); flags_err:
@@ -765,6 +767,7 @@ static int ext4_ioctl_setproject(structEXT4_I (inode)->i_projid = kprojid; inode->i_ctime =current_time (inode); +inode_inc_iversion (inode); out_dirty: rc =ext4_mark_iloc_dirty (handle, inode, &iloc);if (!err)
@@ -1178,6 +1181,7 @@ static long __ext4_ioctl(struct file *fi err =ext4_reserve_inode_write (handle, inode, &iloc);if (err ==0 ) { inode->i_ctime =current_time (inode); +inode_inc_iversion (inode); inode->i_generation = generation; err =ext4_mark_iloc_dirty (handle, inode, &iloc); }
fs/ext4/xattr.c +1 -0
@@ -2412,6 +2412,7 @@ retry_inode:if (!error) {ext4_xattr_update_super_block (handle, inode->i_sb); inode->i_ctime =current_time (inode); +inode_inc_iversion (inode);if (!value) no_expand =0 ; error =ext4_mark_iloc_dirty (handle, inode, &is.iloc);
Greg Kroah-Hartman
maintainerPATCH 132/717 ext4: fix dir corruption when ext4_dx_add_entry() fails
In reply to Greg Kroah-HartmanFrom: Zhihao Cheng <[email protected]>
commit 7177dd009c7c04290891e9a534cd47d1b620bd04 upstream.
Following process may lead to fs corruption:
1. ext4_create(dir/foo)
ext4_add_nondir
ext4_add_entry
ext4_dx_add_entry
a. add_dirent_to_buf
ext4_mark_inode_dirty
ext4_handle_dirty_metadata // dir inode bh is recorded into journal
b. ext4_append // dx_get_count(entries) == dx_get_limit(entries)
ext4_bread(EXT4_GET_BLOCKS_CREATE)
ext4_getblk
ext4_map_blocks
ext4_ext_map_blocks
ext4_mb_new_blocks
dquot_alloc_block
dquot_alloc_space_nodirty
inode_add_bytes // update dir's i_blocks
ext4_ext_insert_extent
ext4_ext_dirty // record extent bh into journal
ext4_handle_dirty_metadata(bh)
// record new block into journal
inode->i_size += inode->i_sb->s_blocksize // new size(in mem)
c. ext4_handle_dirty_dx_node(bh2)
// record dir's new block(dx_node) into journal
d. ext4_handle_dirty_dx_node((frame - 1)->bh)
e. ext4_handle_dirty_dx_node(frame->bh)
f. do_split // ret err!
g. add_dirent_to_buf
ext4_mark_inode_dirty(dir) // update raw_inode on disk(skipped)2. fsck -a /dev/sdb
drop last block(dx_node) which beyonds dir's i_size.
/dev/sdb: recovering journal
/dev/sdb contains a file system with errors, check forced. /dev/sdb: Inode 12, end of extent exceeds allowed value
(logical block 128, physical block 3938, len 1)
3. fsck -fn /dev/sdb
dx_node->entry[i].blk > dir->i_size
Pass 2: Checking directory structure
Problem in HTREE directory inode 12 (/dir): bad block number 128. Clear HTree index? no
Problem in HTREE directory inode 12: block #3 has invalid depth (2) Problem in HTREE directory inode 12: block #3 has bad max hash Problem in HTREE directory inode 12: block #3 not referenced
Fix it by marking inode dirty directly inside ext4_append(). Fetch a reproducer in [Link].
--- fs/ext4/namei.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-)
fs/ext4/namei.c +10 -5
@@ -85,15 +85,20 @@ static struct buffer_head *ext4_append(hreturn bh; inode->i_size += inode->i_sb->s_blocksize;EXT4_I (inode)->i_disksize = inode->i_size; + err =ext4_mark_inode_dirty (handle, inode); +if (err) + goto out;BUFFER_TRACE (bh,"get_write_access" ); err =ext4_journal_get_write_access (handle, inode->i_sb, bh,EXT4_JTR_NONE ); -if (err) { -brelse (bh); -ext4_std_error (inode->i_sb, err); -return ERR_PTR (err); - } +if (err) + goto out;return bh; + +out: +brelse (bh); +ext4_std_error (inode->i_sb, err); +return ERR_PTR (err); } static int ext4_dx_csum_verify(struct inode *inode,
Greg Kroah-Hartman
maintainerPATCH 133/717 ext4: fix miss release buffer head in ext4_fc_write_inode
In reply to Greg Kroah-HartmanFrom: Ye Bin <[email protected]>
commit ccbf8eeb39f2ff00b54726a2b20b35d788c4ecb5 upstream.
In 'ext4_fc_write_inode' function first call 'ext4_get_inode_loc' get 'iloc', after use it miss release 'iloc.bh'.
So just release 'iloc.bh' before 'ext4_fc_write_inode' return.
--- fs/ext4/fast_commit.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)
fs/ext4/fast_commit.c +9 -6
@@ -874,22 +874,25 @@ static int ext4_fc_write_inode(struct in tl.fc_tag =cpu_to_le16 (EXT4_FC_TAG_INODE ); tl.fc_len =cpu_to_le16 (inode_len +sizeof (fc_inode.fc_ino)); + ret = -ECANCELED ; dst =ext4_fc_reserve_space (inode->i_sb,sizeof (tl) + inode_len +sizeof (fc_inode.fc_ino), crc);if (!dst) -return -ECANCELED ; + goto err;if (!ext4_fc_memcpy (inode->i_sb, dst, &tl,sizeof (tl), crc)) -return -ECANCELED ; + goto err; dst +=sizeof (tl);if (!ext4_fc_memcpy (inode->i_sb, dst, &fc_inode,sizeof (fc_inode), crc)) -return -ECANCELED ; + goto err; dst +=sizeof (fc_inode);if (!ext4_fc_memcpy (inode->i_sb, dst, (u8 *)ext4_raw_inode (&iloc), inode_len, crc)) -return -ECANCELED ; - -return 0 ; + goto err; + ret =0 ; +err: +brelse (iloc.bh); +return ret; }/*
Greg Kroah-Hartman
maintainerPATCH 134/717 ext4: fix potential memory leak in ext4_fc_record_modified_inode()
In reply to Greg Kroah-HartmanFrom: Ye Bin <[email protected]>
commit 9305721a309fa1bd7c194e0d4a2335bf3b29dca4 upstream.
As krealloc may return NULL, in this case 'state->fc_modified_inodes' may not be freed by krealloc, but 'state->fc_modified_inodes' already set NULL. Then will lead to 'state->fc_modified_inodes' memory leak.
--- fs/ext4/fast_commit.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
fs/ext4/fast_commit.c +5 -3
@@ -1494,13 +1494,15 @@ static int ext4_fc_record_modified_inodeif (state->fc_modified_inodes[i] == ino)return 0 ;if (state->fc_modified_inodes_used == state->fc_modified_inodes_size) { - state->fc_modified_inodes =krealloc ( - state->fc_modified_inodes, +int *fc_modified_inodes; + + fc_modified_inodes =krealloc (state->fc_modified_inodes,sizeof (int ) * (state->fc_modified_inodes_size +EXT4_FC_REPLAY_REALLOC_INCREMENT ),GFP_KERNEL ); -if (!state->fc_modified_inodes) +if (!fc_modified_inodes)return -ENOMEM ; + state->fc_modified_inodes = fc_modified_inodes; state->fc_modified_inodes_size +=EXT4_FC_REPLAY_REALLOC_INCREMENT ; }
Greg Kroah-Hartman
maintainerPATCH 135/717 ext4: fix potential memory leak in ext4_fc_record_regions()
In reply to Greg Kroah-HartmanFrom: Ye Bin <[email protected]>
commit 7069d105c1f15c442b68af43f7fde784f3126739 upstream.
As krealloc may return NULL, in this case 'state->fc_regions' may not be freed by krealloc, but 'state->fc_regions' already set NULL. Then will lead to 'state->fc_regions' memory leak.
--- fs/ext4/fast_commit.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
fs/ext4/fast_commit.c +8 -6
@@ -1687,15 +1687,17 @@ int ext4_fc_record_regions(struct super_if (replay && state->fc_regions_used != state->fc_regions_valid) state->fc_regions_used = state->fc_regions_valid;if (state->fc_regions_used == state->fc_regions_size) { +struct ext4_fc_alloc_region *fc_regions; + state->fc_regions_size +=EXT4_FC_REPLAY_REALLOC_INCREMENT ; - state->fc_regions =krealloc ( - state->fc_regions, - state->fc_regions_size * -sizeof (struct ext4_fc_alloc_region ), -GFP_KERNEL ); -if (!state->fc_regions) + fc_regions =krealloc (state->fc_regions, + state->fc_regions_size * +sizeof (struct ext4_fc_alloc_region ), +GFP_KERNEL ); +if (!fc_regions)return -ENOMEM ; + state->fc_regions = fc_regions; } region = &state->fc_regions[state->fc_regions_used++]; region->ino = ino;
Greg Kroah-Hartman
maintainerPATCH 136/717 ext4: update state->fc_regions_size after successful memory allocation
In reply to Greg Kroah-HartmanFrom: Ye Bin <[email protected]>
commit 27cd49780381c6ccbf248798e5e8fd076200ffba upstream.
To avoid to 'state->fc_regions_size' mismatch with 'state->fc_regions' when fail to reallocate 'fc_reqions',only update 'state->fc_regions_size' after 'state->fc_regions' is allocated successfully.
--- fs/ext4/fast_commit.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
fs/ext4/fast_commit.c +5 -4
@@ -1689,14 +1689,15 @@ int ext4_fc_record_regions(struct super_if (state->fc_regions_used == state->fc_regions_size) {struct ext4_fc_alloc_region *fc_regions; - state->fc_regions_size += -EXT4_FC_REPLAY_REALLOC_INCREMENT ; fc_regions =krealloc (state->fc_regions, - state->fc_regions_size * -sizeof (struct ext4_fc_alloc_region ), +sizeof (struct ext4_fc_alloc_region ) * + (state->fc_regions_size + +EXT4_FC_REPLAY_REALLOC_INCREMENT ),GFP_KERNEL );if (!fc_regions)return -ENOMEM ; + state->fc_regions_size += +EXT4_FC_REPLAY_REALLOC_INCREMENT ; state->fc_regions = fc_regions; } region = &state->fc_regions[state->fc_regions_used++];
Greg Kroah-Hartman
maintainerPATCH 137/717 livepatch: fix race between fork and KLP transition
In reply to Greg Kroah-HartmanFrom: Rik van Riel <[email protected]>
commit 747f7a2901174c9afa805dddfb7b24db6f65e985 upstream.
The KLP transition code depends on the TIF_PATCH_PENDING and the task->patch_state to stay in sync. On a normal (forward) transition, TIF_PATCH_PENDING will be set on every task in the system, while on a reverse transition (after a failed forward one) first TIF_PATCH_PENDING will be cleared from every task, followed by it being set on tasks that need to be transitioned back to the original code.
However, the fork code copies over the TIF_PATCH_PENDING flag from the parent to the child early on, in dup_task_struct and setup_thread_stack. Much later, klp_copy_process will set child->patch_state to match that of the parent.
However, the parent's patch_state may have been changed by KLP loading or unloading since it was initially copied over into the child.
This results in the KLP code occasionally hitting this warning in klp_complete_transition:
for_each_process_thread(g, task) {
WARN_ON_ONCE(test_tsk_thread_flag(task, TIF_PATCH_PENDING));
task->patch_state = KLP_UNDEFINED;
}Set, or clear, the TIF_PATCH_PENDING flag in the child task depending on whether or not it is needed at the time klp_copy_process is called, at a point in copy_process where the tasklist_lock is held exclusively, preventing races with the KLP code.
The KLP code does have a few places where the state is changed without the tasklist_lock held, but those should not cause problems because klp_update_patch_state(current) cannot be called while the current task is in the middle of fork, klp_check_and_switch_task() which is called under the pi_lock, which prevents rescheduling, and manipulation of the patch state of idle tasks, which do not fork.
This should prevent this warning from triggering again in the future, and close the race for both normal and reverse transitions.
--- kernel/livepatch/transition.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-)
kernel/livepatch/transition.c +16 -2
@@ -610,9 +610,23 @@ void klp_reverse_transition(void)/* Called from copy_process() during fork */ void klp_copy_process (struct task_struct *child) { - child->patch_state = current->patch_state; -/* TIF_PATCH_PENDING gets copied in setup_thread_stack() */ +/* +* The parent process may have gone through a KLP transition since +* the thread flag was copied in setup_thread_stack earlier. Bring +* the task flag up to date with the parent here. +* +* The operation is serialized against all klp_*_transition() +* operations by the tasklist_lock. The only exception is +* klp_update_patch_state(current), but we cannot race with +* that because we are current. +*/ +if (test_tsk_thread_flag (current,TIF_PATCH_PENDING )) +set_tsk_thread_flag (child,TIF_PATCH_PENDING ); +else +clear_tsk_thread_flag (child,TIF_PATCH_PENDING ); + + child->patch_state = current->patch_state; }/*
Greg Kroah-Hartman
maintainerPATCH 138/717 ftrace: Properly unset FTRACE_HASH_FL_MOD
In reply to Greg Kroah-HartmanFrom: Zheng Yejian <[email protected]>
commit 0ce0638edf5ec83343302b884fa208179580700a upstream.
When executing following commands like what document said, but the log "#### all functions enabled ####" was not shown as expect:
1. Set a 'mod' filter:
$ echo 'write*:mod:ext3' > /sys/kernel/tracing/set_ftrace_filter
2. Invert above filter:
$ echo '!write*:mod:ext3' >> /sys/kernel/tracing/set_ftrace_filter
3. Read the file:
$ cat /sys/kernel/tracing/set_ftrace_filterBy some debugging, I found that flag FTRACE_HASH_FL_MOD was not unset after inversion like above step 2 and then result of ftrace_hash_empty() is incorrect.
--- kernel/trace/ftrace.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
kernel/trace/ftrace.c +6 -2
@@ -6037,8 +6037,12 @@ int ftrace_regex_release(struct inode *iif (filter_hash) { orig_hash = &iter->ops->func_hash->filter_hash; -if (iter->tr && !list_empty (&iter->tr->mod_trace)) - iter->hash->flags |=FTRACE_HASH_FL_MOD ; +if (iter->tr) { +if (list_empty (&iter->tr->mod_trace)) + iter->hash->flags &= ~FTRACE_HASH_FL_MOD ; +else + iter->hash->flags |=FTRACE_HASH_FL_MOD ; + } }else orig_hash = &iter->ops->func_hash->notrace_hash;
Greg Kroah-Hartman
maintainerPATCH 139/717 ftrace: Still disable enabled records marked as disabled
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (Google) <[email protected]>
commit cf04f2d5df0037741207382ac8fe289e8bf84ced upstream.
Weak functions started causing havoc as they showed up in the "available_filter_functions" and this confused people as to why some functions marked as "notrace" were listed, but when enabled they did nothing. This was because weak functions can still have fentry calls, and these addresses get added to the "available_filter_functions" file. kallsyms is what converts those addresses to names, and since the weak functions are not listed in kallsyms, it would just pick the function before that.
To solve this, there was a trick to detect weak functions listed, and these records would be marked as DISABLED so that they do not get enabled and are mostly ignored. As the processing of the list of all functions to figure out what is weak or not can take a long time, this process is put off into a kernel thread and run in parallel with the rest of start up.
Now the issue happens whet function tracing is enabled via the kernel command line. As it starts very early in boot up, it can be enabled before the records that are weak are marked to be disabled. This causes an issue in the accounting, as the weak records are enabled by the command line function tracing, but after boot up, they are not disabled.
The ftrace records have several accounting flags and a ref count. The DISABLED flag is just one. If the record is enabled before it is marked DISABLED it will get an ENABLED flag and also have its ref counter incremented. After it is marked for DISABLED, neither the ENABLED flag nor the ref counter is cleared. There's sanity checks on the records that are performed after an ftrace function is registered or unregistered, and this detected that there were records marked as ENABLED with ref counter that should not have been.
Note, the module loading code uses the DISABLED flag as well to keep its functions from being modified while its being loaded and some of these flags may get set in this process. So changing the verification code to ignore DISABLED records is a no go, as it still needs to verify that the module records are working too.
Also, the weak functions still are calling a trampoline. Even though they should never be called, it is dangerous to leave these weak functions calling a trampoline that is freed, so they should still be set back to nops.
There's two places that need to not skip records that have the ENABLED and the DISABLED flags set. That is where the ftrace_ops is processed and sets the records ref counts, and then later when the function itself is to be updated, and the ENABLED flag gets removed. Add a helper function "skip_record()" that returns true if the record has the DISABLED flag set but not the ENABLED flag.
--- kernel/trace/ftrace.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-)
kernel/trace/ftrace.c +16 -4
@@ -1644,6 +1644,18 @@ ftrace_find_tramp_ops_any_other(struct dstatic struct ftrace_ops *ftrace_find_tramp_ops_next (struct dyn_ftrace *rec,struct ftrace_ops *ops); +static bool skip_record (struct dyn_ftrace *rec) +{ +/* +* At boot up, weak functions are set to disable. Function tracing +* can be enabled before they are, and they still need to be disabled now. +* If the record is disabled, still continue if it is marked as already +* enabled (this is needed to keep the accounting working). +*/ +return rec->flags &FTRACE_FL_DISABLED && + !(rec->flags &FTRACE_FL_ENABLED ); +} +static bool __ftrace_hash_rec_update (struct ftrace_ops *ops,int filter_hash,bool inc)
@@ -1693,7 +1705,7 @@ static bool __ftrace_hash_rec_update(strint in_hash =0 ;int match =0 ; -if (rec->flags &FTRACE_FL_DISABLED ) +if (skip_record (rec))continue ;if (all) {
@@ -2090,7 +2102,7 @@ static int ftrace_check_record(struct dy ftrace_bug_type =FTRACE_BUG_UNKNOWN ; -if (rec->flags &FTRACE_FL_DISABLED ) +if (skip_record (rec))return FTRACE_UPDATE_IGNORE ;/*
@@ -2205,7 +2217,7 @@ static int ftrace_check_record(struct dyif (update) {/* If there's no more users, clear all flags */ if (!ftrace_rec_count (rec)) - rec->flags =0 ; + rec->flags &=FTRACE_FL_DISABLED ;else /* * Just disable the record, but keep the ops TRAMP
@@ -2599,7 +2611,7 @@ void __weak ftrace_replace_code(int mod_do_for_each_ftrace_rec (pg, rec) { -if (rec->flags &FTRACE_FL_DISABLED ) +if (skip_record (rec))continue ; failed =__ftrace_replace_code (rec, enable);
Greg Kroah-Hartman
maintainerPATCH 140/717 ring-buffer: Allow splice to read previous partially read pages
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (Google) <[email protected]>
commit fa8f4a89736b654125fb254b0db753ac68a5fced upstream.
If a page is partially read, and then the splice system call is run against the ring buffer, it will always fail to read, no matter how much is in the ring buffer. That's because the code path for a partial read of the page does will fail if the "full" flag is set.
The splice system call wants full pages, so if the read of the ring buffer is not yet full, it should return zero, and the splice will block. But if a previous read was done, where the beginning has been consumed, it should still be given to the splice caller if the rest of the page has been written to.
This caused the splice command to never consume data in this scenario, and let the ring buffer just fill up and lose events.
--- kernel/trace/ring_buffer.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
kernel/trace/ring_buffer.c +9 -1
@@ -5616,7 +5616,15 @@ int ring_buffer_read_page(struct trace_bunsigned int pos =0 ;unsigned int size; -if (full) +/* +* If a full page is expected, this can still be returned +* if there's been a previous partial read and the +* rest of the page can be read and the commit page is off +* the reader page. +*/ +if (full && + (!read || (len < (commit - read)) || + cpu_buffer->reader_page == cpu_buffer->commit_page)) goto out_unlock;if (len > (commit - read))
Greg Kroah-Hartman
maintainerPATCH 141/717 ring-buffer: Have the shortest_full queue be the shortest not longest
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (Google) <[email protected]>
commit 3b19d614b61b93a131f463817e08219c9ce1fee3 upstream.
The logic to know when the shortest waiters on the ring buffer should be woken up or not has uses a less than instead of a greater than compare, which causes the shortest_full to actually be the longest.
--- kernel/trace/ring_buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/trace/ring_buffer.c +1 -1
@@ -1011,7 +1011,7 @@ int ring_buffer_wait(struct trace_buffer nr_pages = cpu_buffer->nr_pages; dirty =ring_buffer_nr_dirty_pages (buffer, cpu);if (!cpu_buffer->shortest_full || - cpu_buffer->shortest_full < full) + cpu_buffer->shortest_full > full) cpu_buffer->shortest_full = full;raw_spin_unlock_irqrestore (&cpu_buffer->reader_lock, flags); if (!pagebusy &&
Greg Kroah-Hartman
maintainerPATCH 142/717 ring-buffer: Check pending waiters when doing wake ups as well
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (Google) <[email protected]>
commit ec0bbc5ec5664dcee344f79373852117dc672c86 upstream.
The wake up waiters only checks the "wakeup_full" variable and not the "full_waiters_pending". The full_waiters_pending is set when a waiter is added to the wait queue. The wakeup_full is only set when an event is triggered, and it clears the full_waiters_pending to avoid multiple calls to irq_work_queue().
The irq_work callback really needs to check both wakeup_full as well as full_waiters_pending such that this code can be used to wake up waiters when a file is closed that represents the ring buffer and the waiters need to be woken up.
--- kernel/trace/ring_buffer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/trace/ring_buffer.c +2 -1
@@ -917,8 +917,9 @@ static void rb_wake_up_waiters(struct ir struct rb_irq_work *rbwork = container_of(work, struct rb_irq_work, work);wake_up_all (&rbwork->waiters); -if (rbwork->wakeup_full) { +if (rbwork->full_waiters_pending || rbwork->wakeup_full) { rbwork->wakeup_full = false; + rbwork->full_waiters_pending = false;wake_up_all (&rbwork->full_waiters); } }
Greg Kroah-Hartman
maintainerPATCH 143/717 ring-buffer: Add ring_buffer_wake_waiters()
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (Google) <[email protected]>
commit 7e9fbbb1b776d8d7969551565bc246f74ec53b27 upstream.
On closing of a file that represents a ring buffer or flushing the file, there may be waiters on the ring buffer that needs to be woken up and exit the ring_buffer_wait() function.
Add ring_buffer_wake_waiters() to wake up the waiters on the ring buffer and allow them to exit the wait loop.
--- include/linux/ring_buffer.h | 2 +- kernel/trace/ring_buffer.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-)
include/linux/ring_buffer.h +1 -1
@@ -101,7 +101,7 @@ __ring_buffer_alloc(unsigned long size,int ring_buffer_wait (struct trace_buffer *buffer,int cpu,int full);__poll_t ring_buffer_poll_wait (struct trace_buffer *buffer,int cpu,struct file *filp,poll_table *poll_table); - +void ring_buffer_wake_waiters (struct trace_buffer *buffer,int cpu);#define RING_BUFFER_ALL_CPUS -1
kernel/trace/ring_buffer.c +39 -0
@@ -413,6 +413,7 @@ struct rb_irq_work {struct irq_work work;wait_queue_head_t waiters;wait_queue_head_t full_waiters; +long wait_index;bool waiters_pending;bool full_waiters_pending;bool wakeup_full;
@@ -925,6 +926,37 @@ static void rb_wake_up_waiters(struct ir }/** +* ring_buffer_wake_waiters - wake up any waiters on this ring buffer +* @buffer: The ring buffer to wake waiters on +* +* In the case of a file that represents a ring buffer is closing, +* it is prudent to wake up any waiters that are on this. +*/ +void ring_buffer_wake_waiters (struct trace_buffer *buffer,int cpu) +{ +struct ring_buffer_per_cpu *cpu_buffer; +struct rb_irq_work *rbwork; + +if (cpu ==RING_BUFFER_ALL_CPUS ) { + +/* Wake up individual ones too. One level recursion */ +for_each_buffer_cpu (buffer, cpu) +ring_buffer_wake_waiters (buffer, cpu); + + rbwork = &buffer->irq_work; + }else { + cpu_buffer = buffer->buffers[cpu]; + rbwork = &cpu_buffer->irq_work; + } + + rbwork->wait_index++; +/* make sure the waiters see the new index */ +smp_wmb (); + +rb_wake_up_waiters (&rbwork->work); +} + +/** * ring_buffer_wait - wait for input to the ring buffer * @buffer: buffer to wait on * @cpu: the cpu buffer to wait on
@@ -939,6 +971,7 @@ int ring_buffer_wait(struct trace_bufferstruct ring_buffer_per_cpu *cpu_buffer;DEFINE_WAIT (wait);struct rb_irq_work *work; +long wait_index;int ret =0 ;/*
@@ -957,6 +990,7 @@ int ring_buffer_wait(struct trace_buffer work = &cpu_buffer->irq_work; } + wait_index =READ_ONCE (work->wait_index);while (true) {if (full)
@@ -1021,6 +1055,11 @@ int ring_buffer_wait(struct trace_buffer }schedule (); + +/* Make sure to see the new wait index */ +smp_rmb (); +if (wait_index != work->wait_index) +break ; }if (full)
Greg Kroah-Hartman
maintainerPATCH 144/717 ring-buffer: Fix race between reset page and reading page
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (Google) <[email protected]>
commit a0fcaaed0c46cf9399d3a2d6e0c87ddb3df0e044 upstream.
The ring buffer is broken up into sub buffers (currently of page size). Each sub buffer has a pointer to its "tail" (the last event written to the sub buffer). When a new event is requested, the tail is locally incremented to cover the size of the new event. This is done in a way that there is no need for locking.
If the tail goes past the end of the sub buffer, the process of moving to the next sub buffer takes place. After setting the current sub buffer to the next one, the previous one that had the tail go passed the end of the sub buffer needs to be reset back to the original tail location (before the new event was requested) and the rest of the sub buffer needs to be "padded".
The race happens when a reader takes control of the sub buffer. As readers do a "swap" of sub buffers from the ring buffer to get exclusive access to the sub buffer, it replaces the "head" sub buffer with an empty sub buffer that goes back into the writable portion of the ring buffer. This swap can happen as soon as the writer moves to the next sub buffer and before it updates the last sub buffer with padding.
Because the sub buffer can be released to the reader while the writer is still updating the padding, it is possible for the reader to see the event that goes past the end of the sub buffer. This can cause obvious issues.
To fix this, add a few memory barriers so that the reader definitely sees the updates to the sub buffer, and also waits until the writer has put back the "tail" of the sub buffer back to the last event that was written on it.
To be paranoid, it will only spin for 1 second, otherwise it will warn and shutdown the ring buffer code. 1 second should be enough as the writer does have preemption disabled. If the writer doesn't move within 1 second (with preemption disabled) something is horribly wrong. No interrupt should last 1 second!
--- kernel/trace/ring_buffer.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)
kernel/trace/ring_buffer.c +33 -0
@@ -2648,6 +2648,9 @@ rb_reset_tail(struct ring_buffer_per_cpu/* Mark the rest of the page with padding */ rb_event_set_padding (event); +/* Make sure the padding is visible before the write update */ +smp_wmb (); +/* Set the write back to the previous setting */ local_sub (length, &tail_page->write);return ;
@@ -2659,6 +2662,9 @@ rb_reset_tail(struct ring_buffer_per_cpu/* time delta must be non zero */ event->time_delta =1 ; +/* Make sure the padding is visible before the tail_page->write update */ +smp_wmb (); +/* Set write to end of buffer */ length = (tail + length) -BUF_PAGE_SIZE ;local_sub (length, &tail_page->write);
@@ -4627,6 +4633,33 @@ rb_get_reader_page(struct ring_buffer_pearch_spin_unlock (&cpu_buffer->lock);local_irq_restore (flags); +/* +* The writer has preempt disable, wait for it. But not forever +* Although, 1 second is pretty much "forever" +*/ +#define USECS_WAIT 1000000 +for (nr_loops =0 ; nr_loops <USECS_WAIT ; nr_loops++) { +/* If the write is past the end of page, a writer is still updating it */ +if (likely (!reader ||rb_page_write (reader) <=BUF_PAGE_SIZE )) +break ; + +udelay (1 ); + +/* Get the latest version of the reader write value */ +smp_rmb (); + } + +/* The writer is not moving forward? Something is wrong */ +if (RB_WARN_ON (cpu_buffer, nr_loops ==USECS_WAIT )) + reader =NULL ; + +/* +* Make sure we see any padding after the write update +* (see rb_reset_tail()) +*/ +smp_rmb (); + +return reader; }
Greg Kroah-Hartman
maintainerPATCH 145/717 tracing: Disable interrupt or preemption before acquiring arch_spinlock_t
In reply to Greg Kroah-HartmanFrom: Waiman Long <[email protected]>
commit c0a581d7126c0bbc96163276f585fd7b4e4d8d0e upstream.
It was found that some tracing functions in kernel/trace/trace.c acquire an arch_spinlock_t with preemption and irqs enabled. An example is the tracing_saved_cmdlines_size_read() function which intermittently causes a "BUG: using smp_processor_id() in preemptible" warning when the LTP read_all_proc test is run.
That can be problematic in case preemption happens after acquiring the lock. Add the necessary preemption or interrupt disabling code in the appropriate places before acquiring an arch_spinlock_t.
The convention here is to disable preemption for trace_cmdline_lock and interupt for max_lock.
--- kernel/trace/trace.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
kernel/trace/trace.c +23 -0
@@ -1193,12 +1193,14 @@ void *tracing_cond_snapshot_data(struct {void *cond_data =NULL ; +local_irq_disable ();arch_spin_lock (&tr->max_lock);if (tr->cond_snapshot) cond_data = tr->cond_snapshot->cond_data;arch_spin_unlock (&tr->max_lock); +local_irq_enable ();return cond_data; }
@@ -1334,9 +1336,11 @@ int tracing_snapshot_cond_enable(struct goto fail_unlock; } +local_irq_disable ();arch_spin_lock (&tr->max_lock); tr->cond_snapshot = cond_snapshot;arch_spin_unlock (&tr->max_lock); +local_irq_enable ();mutex_unlock (&trace_types_lock);
@@ -1363,6 +1367,7 @@ int tracing_snapshot_cond_disable(struct {int ret =0 ; +local_irq_disable ();arch_spin_lock (&tr->max_lock);if (!tr->cond_snapshot)
@@ -1373,6 +1378,7 @@ int tracing_snapshot_cond_disable(struct }arch_spin_unlock (&tr->max_lock); +local_irq_enable ();return ret; }
@@ -2200,6 +2206,11 @@ static size_t tgid_map_max;#define SAVED_CMDLINES_DEFAULT 128#define NO_CMDLINE_MAP UINT_MAX +/* +* Preemption must be disabled before acquiring trace_cmdline_lock. +* The various trace_arrays' max_lock must be acquired in a context +* where interrupt is disabled. +*/ static arch_spinlock_t trace_cmdline_lock = __ARCH_SPIN_LOCK_UNLOCKED;struct saved_cmdlines_buffer {unsigned map_pid_to_cmdline[PID_MAX_DEFAULT +1 ];
@@ -2412,7 +2423,11 @@ static int trace_save_cmdline(struct tas* the lock, but we also don't want to spin * nor do we want to disable interrupts, * so if we miss here, then better luck next time. +* +* This is called within the scheduler and wake up, so interrupts +* had better been disabled and run queue lock been held. */ +lockdep_assert_preemption_disabled ();if (!arch_spin_trylock (&trace_cmdline_lock))return 0 ;
@@ -5890,9 +5905,11 @@ tracing_saved_cmdlines_size_read(structchar buf[64 ];int r; +preempt_disable ();arch_spin_lock (&trace_cmdline_lock); r =scnprintf (buf,sizeof (buf),"%u\n" , savedcmd->cmdline_num);arch_spin_unlock (&trace_cmdline_lock); +preempt_enable ();return simple_read_from_buffer (ubuf, cnt, ppos, buf, r); }
@@ -5917,10 +5934,12 @@ static int tracing_resize_saved_cmdlinesreturn -ENOMEM ; } +preempt_disable ();arch_spin_lock (&trace_cmdline_lock); savedcmd_temp = savedcmd; savedcmd = s;arch_spin_unlock (&trace_cmdline_lock); +preempt_enable ();free_saved_cmdlines_buffer (savedcmd_temp);return 0 ;
@@ -6373,10 +6392,12 @@ int tracing_set_tracer(struct trace_arra#ifdef CONFIG_TRACER_SNAPSHOT if (t->use_max_tr) { +local_irq_disable ();arch_spin_lock (&tr->max_lock);if (tr->cond_snapshot) ret = -EBUSY ;arch_spin_unlock (&tr->max_lock); +local_irq_enable ();if (ret) goto out; }
@@ -7436,10 +7457,12 @@ tracing_snapshot_write(struct file *filp goto out; } +local_irq_disable ();arch_spin_lock (&tr->max_lock);if (tr->cond_snapshot) ret = -EBUSY ;arch_spin_unlock (&tr->max_lock); +local_irq_enable ();if (ret) goto out;
Greg Kroah-Hartman
maintainerPATCH 146/717 tracing: Wake up ring buffer waiters on closing of the file
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (Google) <[email protected]>
commit f3ddb74ad0790030c9592229fb14d8c451f4e9a8 upstream.
When the file that represents the ring buffer is closed, there may be waiters waiting on more input from the ring buffer. Call ring_buffer_wake_waiters() to wake up any waiters when the file is closed.
--- include/linux/trace_events.h | 1 + kernel/trace/trace.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+)
include/linux/trace_events.h +1 -0
@@ -92,6 +92,7 @@ struct trace_iterator {unsigned int temp_size;char *fmt;/* modified format holder */ unsigned int fmt_size; +long wait_index;/* trace_seq for __print_flags() and __print_symbolic() etc. */ struct trace_seq tmp_seq;
kernel/trace/trace.c +15 -0
@@ -8160,6 +8160,12 @@ static int tracing_buffers_release(struc__trace_array_put (iter->tr); + iter->wait_index++; +/* Make sure the waiters see the new wait_index */ +smp_wmb (); + +ring_buffer_wake_waiters (iter->array_buffer->buffer, iter->cpu_file); +if (info->spare)ring_buffer_free_read_page (iter->array_buffer->buffer, info->spare_cpu, info->spare);
@@ -8313,6 +8319,8 @@ tracing_buffers_splice_read(struct file/* did we read anything? */ if (!spd.nr_pages) { +long wait_index; +if (ret) goto out;
@@ -8320,10 +8328,17 @@ tracing_buffers_splice_read(struct fileif ((file->f_flags &O_NONBLOCK ) || (flags &SPLICE_F_NONBLOCK )) goto out; + wait_index =READ_ONCE (iter->wait_index); + ret =wait_on_pipe (iter, iter->tr->buffer_percent);if (ret) goto out; +/* Make sure we see the new wait_index */ +smp_rmb (); +if (wait_index != iter->wait_index) + goto out; + goto again; }
Greg Kroah-Hartman
maintainerPATCH 147/717 tracing: Wake up waiters when tracing is disabled
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (Google) <[email protected]>
commit 2b0fd9a59b7990c161fa1cb7b79edb22847c87c2 upstream.
When tracing is disabled, there's no reason that waiters should stay waiting, wake them up, otherwise tasks get stuck when they should be flushing the buffers.
--- kernel/trace/trace.c | 6 ++++++ 1 file changed, 6 insertions(+)
kernel/trace/trace.c +6 -0
@@ -8334,6 +8334,10 @@ tracing_buffers_splice_read(struct fileif (ret) goto out; +/* No need to wait after waking up when tracing is off */ +if (!tracer_tracing_is_on (iter->tr)) + goto out; +/* Make sure we see the new wait_index */ smp_rmb ();if (wait_index != iter->wait_index)
@@ -9043,6 +9047,8 @@ rb_simple_write(struct file *filp, consttracer_tracing_off (tr);if (tr->current_trace->stop) tr->current_trace->stop (tr); +/* Wake up any waiters */ +ring_buffer_wake_waiters (buffer,RING_BUFFER_ALL_CPUS ); }mutex_unlock (&trace_types_lock); }
Greg Kroah-Hartman
maintainerPATCH 148/717 tracing: Add ioctl() to force ring buffer waiters to wake up
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (Google) <[email protected]>
commit 01b2a52171735c6eea80ee2f355f32bea6c41418 upstream.
If a process is waiting on the ring buffer for data, there currently isn't a clean way to force it to wake up. Add an ioctl call that will force any tasks that are waiting on the trace_pipe_raw file to wake up.
--- kernel/trace/trace.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
kernel/trace/trace.c +22 -0
@@ -8353,12 +8353,34 @@ out:return ret; } +/* An ioctl call with cmd 0 to the ring buffer file will wake up all waiters */ +static long tracing_buffers_ioctl (struct file *file,unsigned int cmd,unsigned long arg) +{ +struct ftrace_buffer_info *info = file->private_data; +struct trace_iterator *iter = &info->iter; + +if (cmd) +return -ENOIOCTLCMD ; + +mutex_lock (&trace_types_lock); + + iter->wait_index++; +/* Make sure the waiters see the new wait_index */ +smp_wmb (); + +ring_buffer_wake_waiters (iter->array_buffer->buffer, iter->cpu_file); + +mutex_unlock (&trace_types_lock); +return 0 ; +} +static const struct file_operations tracing_buffers_fops = { .open = tracing_buffers_open, .read = tracing_buffers_read, .poll = tracing_buffers_poll, .release = tracing_buffers_release, .splice_read = tracing_buffers_splice_read, + .unlocked_ioctl = tracing_buffers_ioctl, .llseek = no_llseek, };
Greg Kroah-Hartman
maintainerPATCH 149/717 tracing: Do not free snapshot if tracer is on cmdline
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (Google) <[email protected]>
commit a541a9559bb0a8ecc434de01d3e4826c32e8bb53 upstream.
The ftrace_boot_snapshot and alloc_snapshot cmdline options allocate the snapshot buffer at boot up for use later. The ftrace_boot_snapshot in particular requires the snapshot to be allocated because it will take a snapshot at the end of boot up allowing to see the traces that happened during boot so that it's not lost when user space takes over.
When a tracer is registered (started) there's a path that checks if it requires the snapshot buffer or not, and if it does not and it was allocated it will do a synchronization and free the snapshot buffer.
This is only required if the previous tracer was using it for "max latency" snapshots, as it needs to make sure all max snapshots are complete before freeing. But this is only needed if the previous tracer was using the snapshot buffer for latency (like irqoff tracer and friends). But it does not make sense to free it, if the previous tracer was not using it, and the snapshot was allocated by the cmdline parameters. This basically takes away the point of allocating it in the first place!
Note, the allocated snapshot worked fine for just trace events, but fails when a tracer is enabled on the cmdline.
Further investigation, this goes back even further and it does not require a tracer on the cmdline to fail. Simply enable snapshots and then enable a tracer, and it will remove the snapshot.
--- kernel/trace/trace.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
kernel/trace/trace.c +6 -4
@@ -6428,12 +6428,12 @@ int tracing_set_tracer(struct trace_arraif (tr->current_trace->reset) tr->current_trace->reset (tr); +#ifdef CONFIG_TRACER_MAX_TRACE + had_max_tr = tr->current_trace->use_max_tr; +/* Current trace needs to be nop_trace before synchronize_rcu */ tr->current_trace = &nop_trace; -#ifdef CONFIG_TRACER_MAX_TRACE - had_max_tr = tr->allocated_snapshot; -if (had_max_tr && !t->use_max_tr) {/* * We need to make sure that the update_max_tr sees that
@@ -6446,11 +6446,13 @@ int tracing_set_tracer(struct trace_arra free_snapshot(tr); } -if (t->use_max_tr && !had_max_tr) { +if (t->use_max_tr && !tr->allocated_snapshot) { ret =tracing_alloc_snapshot_instance (tr);if (ret <0 ) goto out; } +#else + tr->current_trace = &nop_trace;#endif if (t->init) {
Greg Kroah-Hartman
maintainerPATCH 150/717 tracing: Move duplicate code of trace_kprobe/eprobe.c into header
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (Google) <[email protected]>
commit f1d3cbfaafc10464550c6d3a125f4fc802bbaed5 upstream.
The functions:
fetch_store_strlen_user()
fetch_store_strlen()
fetch_store_string_user()
fetch_store_string()
are identical in both trace_kprobe.c and trace_eprobe.c. Move them into a new header file trace_probe_kernel.h to share it. This code will later be used by the synthetic events as well.
Marked for stable as a fix for a crash in synthetic events requires it.
--- kernel/trace/trace_eprobe.c | 60 +---------------------- kernel/trace/trace_kprobe.c | 60 +---------------------- kernel/trace/trace_probe_kernel.h | 96 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 110 deletions(-) create mode 100644 kernel/trace/trace_probe_kernel.h
kernel/trace/trace_eprobe.c +5 -55
@@ -16,6 +16,7 @@#include "trace_dynevent.h" #include "trace_probe.h" #include "trace_probe_tmpl.h" +#include "trace_probe_kernel.h" #define EPROBE_EVENT_SYSTEM "eprobes"
@@ -452,29 +453,14 @@ NOKPROBE_SYMBOL(process_fetch_insn) static nokprobe_inline intfetch_store_strlen_user (unsigned long addr) { -const void __user *uaddr = (__force const void __user *)addr; - -return strnlen_user_nofault (uaddr,MAX_STRING_SIZE ); +return kern_fetch_store_strlen_user (addr); }/* Return the length of string -- including null terminal byte */ static nokprobe_inline intfetch_store_strlen (unsigned long addr) { -int ret, len =0 ; -u8 c; - -#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE -if (addr <TASK_SIZE ) -return fetch_store_strlen_user (addr); -#endif - -do { - ret =copy_from_kernel_nofault (&c, (u8 *)addr + len,1 ); - len++; - }while (c && ret ==0 && len <MAX_STRING_SIZE ); - -return (ret <0 ) ? ret : len; +return kern_fetch_store_strlen (addr); }/*
@@ -484,21 +470,7 @@ fetch_store_strlen(unsigned long addr) static nokprobe_inline intfetch_store_string_user (unsigned long addr,void *dest,void *base) { -const void __user *uaddr = (__force const void __user *)addr; -int maxlen =get_loc_len (*(u32 *)dest); -void *__dest; -long ret; - -if (unlikely (!maxlen)) -return -ENOMEM ; - - __dest =get_loc_data (dest, base); - - ret =strncpy_from_user_nofault (__dest, uaddr, maxlen); -if (ret >=0 ) - *(u32 *)dest =make_data_loc (ret, __dest - base); - -return ret; +return kern_fetch_store_string_user (addr, dest, base); }/*
@@ -508,29 +480,7 @@ fetch_store_string_user(unsigned long ad static nokprobe_inline intfetch_store_string (unsigned long addr,void *dest,void *base) { -int maxlen =get_loc_len (*(u32 *)dest); -void *__dest; -long ret; - -#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE -if ((unsigned long )addr <TASK_SIZE ) -return fetch_store_string_user (addr, dest, base); -#endif - -if (unlikely (!maxlen)) -return -ENOMEM ; - - __dest =get_loc_data (dest, base); - -/* -* Try to get string again, since the string can be changed while -* probing. -*/ - ret =strncpy_from_kernel_nofault (__dest, (void *)addr, maxlen); -if (ret >=0 ) - *(u32 *)dest =make_data_loc (ret, __dest - base); - -return ret; +return kern_fetch_store_string (addr, dest, base); }static nokprobe_inline int
kernel/trace/trace_kprobe.c +5 -55
90 lines not on this page · raw message
kernel/trace/trace_probe_kernel.h new file +96 -0
96 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 151/717 tracing: Add "(fault)" name injection to kernel probes
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (Google) <[email protected]>
commit 2e9906f84fc7c99388bb7123ade167250d50f1c0 upstream.
Have the specific functions for kernel probes that read strings to inject the "(fault)" name directly. trace_probes.c does this too (for uprobes) but as the code to read strings are going to be used by synthetic events (and perhaps other utilities), it simplifies the code by making sure those other uses do not need to implement the "(fault)" name injection as well.
--- kernel/trace/trace_probe_kernel.h | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-)
kernel/trace/trace_probe_kernel.h +25 -6
@@ -2,6 +2,8 @@#ifndef __TRACE_PROBE_KERNEL_H_#define __TRACE_PROBE_KERNEL_H_ +#define FAULT_STRING "(fault)" +/* * This depends on trace_probe.h, but can not include it due to * the way trace_probe_tmpl.h is used by trace_kprobe.c and trace_eprobe.c.
@@ -13,8 +15,16 @@ static nokprobe_inline int kern_fetch_store_strlen_user(unsigned long addr) {const void __user *uaddr = (__force const void __user *)addr; +int ret; -return strnlen_user_nofault (uaddr,MAX_STRING_SIZE ); + ret =strnlen_user_nofault (uaddr,MAX_STRING_SIZE ); +/* +* strnlen_user_nofault returns zero on fault, insert the +* FAULT_STRING when that occurs. +*/ +if (ret <=0 ) +return strlen (FAULT_STRING ) +1 ; +return ret; }/* Return the length of string -- including null terminal byte */
@@ -34,7 +44,18 @@ kern_fetch_store_strlen(unsigned long ad len++; }while (c && ret ==0 && len <MAX_STRING_SIZE ); -return (ret <0 ) ? ret : len; +/* For faults, return enough to hold the FAULT_STRING */ +return (ret <0 ) ?strlen (FAULT_STRING ) +1 : len; +} + +static nokprobe_inline void set_data_loc(int ret, void *dest, void *__dest, void *base, int len) +{ +if (ret >=0 ) { + *(u32 *)dest =make_data_loc (ret, __dest - base); + }else { +strscpy (__dest,FAULT_STRING , len); + ret =strlen (__dest) +1 ; + } }/*
@@ -55,8 +76,7 @@ kern_fetch_store_string_user(unsigned lo __dest =get_loc_data (dest, base); ret =strncpy_from_user_nofault (__dest, uaddr, maxlen); -if (ret >=0 ) - *(u32 *)dest =make_data_loc (ret, __dest - base); +set_data_loc (ret, dest, __dest, base, maxlen);return ret; }
@@ -87,8 +107,7 @@ kern_fetch_store_string(unsigned long ad* probing. */ ret =strncpy_from_kernel_nofault (__dest, (void *)addr, maxlen); -if (ret >=0 ) - *(u32 *)dest =make_data_loc (ret, __dest - base); +set_data_loc (ret, dest, __dest, base, maxlen);return ret; }
Greg Kroah-Hartman
maintainerPATCH 152/717 tracing: Fix reading strings from synthetic events
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (Google) <[email protected]>
commit 0934ae9977c27133449b6dd8c6213970e7eece38 upstream.
The follow commands caused a crash:
# cd /sys/kernel/tracing # echo 's:open char file[]' > dynamic_events # echo 'hist:keys=common_pid:file=filename:onchange($file).trace(open,$file)' > events/syscalls/sys_enter_openat/trigger' # echo 1 > events/synthetic/open/enable
BOOM!
The problem is that the synthetic event field "char file[]" will read the value given to it as a string without any memory checks to make sure the address is valid. The above example will pass in the user space address and the sythetic event code will happily call strlen() on it and then strscpy() where either one will cause an oops when accessing user space addresses.
Use the helper functions from trace_kprobe and trace_eprobe that can read strings safely (and actually succeed when the address is from user space and the memory is mapped in).
Now the above can show:
packagekitd-1721 [000] ...2. 104.597170: open: file=/usr/lib/rpm/fileattrs/cmake.attr
in:imjournal-978 [006] ...2. 104.599642: open: file=/var/lib/rsyslog/imjournal.state.tmp
packagekitd-1721 [000] ...2. 104.626308: open: file=/usr/lib/rpm/fileattrs/debuginfo.attr--- kernel/trace/trace_events_synth.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-)
kernel/trace/trace_events_synth.c +17 -6
@@ -17,6 +17,8 @@/* for gfp flag names */ #include <linux/trace_events.h> #include <trace/events/mmflags.h> +#include "trace_probe.h" +#include "trace_probe_kernel.h" #include "trace_synth.h"
@@ -409,6 +411,7 @@ static unsigned int trace_string(struct {unsigned int len =0 ;char *str_field; +int ret;if (is_dynamic) {u32 data_offset;
@@ -417,19 +420,27 @@ static unsigned int trace_string(struct data_offset += event->n_u64 *sizeof (u64); data_offset += data_size; - str_field = (char *)entry + data_offset; - - len =strlen (str_val) +1 ; -strscpy (str_field, str_val, len); + len =kern_fetch_store_strlen ((unsigned long )str_val); data_offset |= len <<16 ; *(u32 *)&entry->fields[*n_u64] = data_offset; + ret =kern_fetch_store_string ((unsigned long )str_val, &entry->fields[*n_u64], entry); + (*n_u64)++; }else { str_field = (char *)&entry->fields[*n_u64]; -strscpy (str_field, str_val,STR_VAR_LEN_MAX ); +#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE +if ((unsigned long )str_val <TASK_SIZE ) + ret =strncpy_from_user_nofault (str_field, str_val,STR_VAR_LEN_MAX ); + else +#endif + ret =strncpy_from_kernel_nofault (str_field, str_val,STR_VAR_LEN_MAX ); + +if (ret <0 ) +strcpy (str_field,FAULT_STRING ); + (*n_u64) +=STR_VAR_LEN_MAX /sizeof (u64); }
@@ -462,7 +473,7 @@ static notrace void trace_event_raw_even val_idx = var_ref_idx[field_pos]; str_val = (char *)(long )var_ref_vals[val_idx]; - len =strlen (str_val) +1 ; + len =kern_fetch_store_strlen ((unsigned long )str_val); fields_size += len; }
Greg Kroah-Hartman
maintainerPATCH 153/717 rpmsg: char: Avoid double destroy of default endpoint
In reply to Greg Kroah-HartmanFrom: Shengjiu Wang <[email protected]>
commit 467233a4ac29b215d492843d067a9f091e6bf0c5 upstream.
The rpmsg_dev_remove() in rpmsg_core is the place for releasing this default endpoint.
So need to avoid destroying the default endpoint in rpmsg_chrdev_eptdev_destroy(), this should be the same as rpmsg_eptdev_release(). Otherwise there will be double destroy issue that ept->refcount report warning:
refcount_t: underflow; use-after-free.
Call trace: refcount_warn_saturate+0xf8/0x150 virtio_rpmsg_destroy_ept+0xd4/0xec rpmsg_dev_remove+0x60/0x70
The issue can be reproduced by stopping remoteproc before closing the /dev/rpmsgX.
--- drivers/rpmsg/rpmsg_char.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/rpmsg/rpmsg_char.c +3 -1
@@ -76,7 +76,9 @@ int rpmsg_chrdev_eptdev_destroy(struct dmutex_lock (&eptdev->ept_lock);if (eptdev->ept) { -rpmsg_destroy_ept (eptdev->ept); +/* The default endpoint is released by the rpmsg core */ +if (!eptdev->default_ept) +rpmsg_destroy_ept (eptdev->ept); eptdev->ept =NULL ; }mutex_unlock (&eptdev->ept_lock);
Greg Kroah-Hartman
maintainerPATCH 154/717 thunderbolt: Explicitly enable lane adapter hotplug events at startup
In reply to Greg Kroah-HartmanFrom: Mario Limonciello <[email protected]>
commit 5d2569cb4a65c373896ec0217febdf88739ed295 upstream.
Software that has run before the USB4 CM in Linux runs may have disabled hotplug events for a given lane adapter.
Other CMs such as that one distributed with Windows 11 will enable hotplug events. Do the same thing in the Linux CM which fixes hotplug events on "AMD Pink Sardine".
--- drivers/thunderbolt/switch.c | 24 ++++++++++++++++++++++++ drivers/thunderbolt/tb.h | 1 + drivers/thunderbolt/tb_regs.h | 1 + drivers/thunderbolt/usb4.c | 20 ++++++++++++++++++++ 4 files changed, 46 insertions(+)
drivers/thunderbolt/switch.c +24 -0
@@ -2822,6 +2822,26 @@ static void tb_switch_credits_init(structb_sw_info (sw,"failed to determine preferred buffer allocation, using defaults\n" ); } +static int tb_switch_port_hotplug_enable (struct tb_switch *sw) +{ +struct tb_port *port; + +if (tb_switch_is_icm (sw)) +return 0 ; + +tb_switch_for_each_port (sw, port) { +int res; + +if (!port->cap_usb4) +continue ; + + res =usb4_port_hotplug_enable (port); +if (res) +return res; + } +return 0 ; +} +/** * tb_switch_add() - Add a switch to the domain * @sw: Switch to add
@@ -2891,6 +2911,10 @@ int tb_switch_add(struct tb_switch *sw)return ret; } + ret =tb_switch_port_hotplug_enable (sw); +if (ret) +return ret; + ret =device_add (&sw->dev);if (ret) {dev_err (&sw->dev,"failed to add device: %d\n" , ret);
drivers/thunderbolt/tb.h +1 -0
@@ -1170,6 +1170,7 @@ int usb4_switch_add_ports(struct tb_switvoid usb4_switch_remove_ports (struct tb_switch *sw);int usb4_port_unlock (struct tb_port *port); +int usb4_port_hotplug_enable (struct tb_port *port);int usb4_port_configure (struct tb_port *port);void usb4_port_unconfigure (struct tb_port *port);int usb4_port_configure_xdomain (struct tb_port *port);
drivers/thunderbolt/tb_regs.h +1 -0
@@ -302,6 +302,7 @@ struct tb_regs_port_header {#define ADP_CS_5 0x05#define ADP_CS_5_LCA_MASK GENMASK(28, 22)#define ADP_CS_5_LCA_SHIFT 22 +#define ADP_CS_5_DHP BIT(31)/* TMU adapter registers */ #define TMU_ADP_CS_3 0x03
drivers/thunderbolt/usb4.c +20 -0
@@ -1046,6 +1046,26 @@ int usb4_port_unlock(struct tb_port *porreturn tb_port_write (port, &val,TB_CFG_PORT ,ADP_CS_4 ,1 ); } +/** +* usb4_port_hotplug_enable() - Enables hotplug for a port +* @port: USB4 port to operate on +* +* Enables hot plug events on a given port. This is only intended +* to be used on lane, DP-IN, and DP-OUT adapters. +*/ +int usb4_port_hotplug_enable (struct tb_port *port) +{ +int ret; +u32 val; + + ret =tb_port_read (port, &val,TB_CFG_PORT ,ADP_CS_5 ,1 ); +if (ret) +return ret; + + val &= ~ADP_CS_5_DHP ; +return tb_port_write (port, &val,TB_CFG_PORT ,ADP_CS_5 ,1 ); +} +static int usb4_port_set_configured (struct tb_port *port,bool configured) {int ret;
Greg Kroah-Hartman
maintainerPATCH 155/717 efi: libstub: drop pointless get_memory_map() call
In reply to Greg Kroah-HartmanFrom: Ard Biesheuvel <[email protected]>
commit d80ca810f096ff66f451e7a3ed2f0cd9ef1ff519 upstream.
Currently, the non-x86 stub code calls get_memory_map() redundantly, given that the data it returns is never used anywhere. So drop the call.
--- drivers/firmware/efi/libstub/fdt.c | 8 -------- 1 file changed, 8 deletions(-)
drivers/firmware/efi/libstub/fdt.c +0 -8
@@ -280,14 +280,6 @@ efi_status_t allocate_new_fdt_and_exit_b goto fail; } -/* -* Now that we have done our final memory allocation (and free) -* we can get the memory map key needed for exit_boot_services(). -*/ - status =efi_get_memory_map (&map); -if (status !=EFI_SUCCESS ) - goto fail_free_new_fdt; - status =update_fdt ((void *)fdt_addr, fdt_size, (void *)*new_fdt_addr,MAX_FDT_SIZE , cmdline_ptr, initrd_addr, initrd_size);
Greg Kroah-Hartman
maintainerPATCH 156/717 media: cedrus: Set the platform driver data earlier
In reply to Greg Kroah-HartmanFrom: Dmitry Osipenko <[email protected]>
commit 708938f8495147fe2e77a9a3e1015d8e6899323e upstream.
The cedrus_hw_resume() crashes with NULL deference on driver probe if runtime PM is disabled because it uses platform data that hasn't been set up yet. Fix this by setting the platform data earlier during probe.
--- drivers/staging/media/sunxi/cedrus/cedrus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/staging/media/sunxi/cedrus/cedrus.c +2 -2
@@ -422,6 +422,8 @@ static int cedrus_probe(struct platform_if (!dev)return -ENOMEM ; +platform_set_drvdata (pdev, dev); + dev->vfd = cedrus_video_device; dev->dev = &pdev->dev; dev->pdev = pdev;
@@ -495,8 +497,6 @@ static int cedrus_probe(struct platform_ goto err_m2m_mc; } -platform_set_drvdata (pdev, dev); -return 0 ; err_m2m_mc:
Greg Kroah-Hartman
maintainerPATCH 157/717 media: cedrus: Fix endless loop in cedrus_h265_skip_bits()
In reply to Greg Kroah-HartmanFrom: Dmitry Osipenko <[email protected]>
commit 91db7a3fc7fe670cf1770a398a43bb4a1f776bf1 upstream.
The busy status bit may never de-assert if number of programmed skip bits is incorrect, resulting in a kernel hang because the bit is polled endlessly in the code. Fix it by adding timeout for the bit-polling. This problem is reproducible by setting the data_bit_offset field of the HEVC slice params to a wrong value by userspace.
--- drivers/staging/media/sunxi/cedrus/cedrus_h265.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/staging/media/sunxi/cedrus/cedrus_h265.c +3 -2
@@ -234,8 +234,9 @@ static void cedrus_h265_skip_bits(structcedrus_write (dev,VE_DEC_H265_TRIGGER ,VE_DEC_H265_TRIGGER_FLUSH_BITS |VE_DEC_H265_TRIGGER_TYPE_N_BITS (tmp)); -while (cedrus_read (dev,VE_DEC_H265_STATUS ) &VE_DEC_H265_STATUS_VLD_BUSY ) -udelay (1 ); + +if (cedrus_wait_for (dev,VE_DEC_H265_STATUS ,VE_DEC_H265_STATUS_VLD_BUSY )) +dev_err_ratelimited (dev->dev,"timed out waiting to skip bits\n" ); count += tmp; }
Greg Kroah-Hartman
maintainerPATCH 158/717 blk-throttle: fix that io throttle can only work for single bio
In reply to Greg Kroah-HartmanFrom: Yu Kuai <[email protected]>
commit 320fb0f91e55ba248d4bad106b408e59099cfa89 upstream.
Test scripts:
cd /sys/fs/cgroup/blkio/
echo "8:0 1024" > blkio.throttle.write_bps_device echo $$ > cgroup.procs
dd if=/dev/zero of=/dev/sda bs=10k count=1 oflag=direct & dd if=/dev/zero of=/dev/sda bs=10k count=1 oflag=direct &
Test result:
10240 bytes (10 kB, 10 KiB) copied, 10.0134 s, 1.0 kB/s 10240 bytes (10 kB, 10 KiB) copied, 10.0135 s, 1.0 kB/s
The problem is that the second bio is finished after 10s instead of 20s.
Root cause:
1) second bio will be flagged:
__blk_throtl_bio
while (true) {
...
if (sq->nr_queued[rw]) -> some bio is throttled already
break
};
bio_set_flag(bio, BIO_THROTTLED); -> flag the bio
2) flagged bio will be dispatched without waiting:
throtl_dispatch_tg
tg_may_dispatch
tg_with_in_bps_limit
if (bps_limit == U64_MAX || bio_flagged(bio, BIO_THROTTLED))
*wait = 0; -> wait time is zero
return true;commit 9f5ede3c01f9 ("block: throttle split bio in case of iops limit") support to count split bios for iops limit, thus it adds flagged bio checking in tg_with_in_bps_limit() so that split bios will only count once for bps limit, however, it introduce a new problem that io throttle won't work if multiple bios are throttled.
In order to fix the problem, handle iops/bps limit in different ways:
1) for iops limit, there is no flag to record if the bio is throttled, and iops is always applied.
2) for bps limit, original bio will be flagged with BIO_BPS_THROTTLED, and io throttle will ignore bio with the flag.
Noted this patch also remove the code to set flag in __bio_clone(), it's introduced in commit 111be8839817 ("block-throttle: avoid double charge"), and author thinks split bio can be resubmited and throttled again, which is wrong because split bio will continue to dispatch from caller.
--- block/bio.c | 2 -- block/blk-throttle.c | 20 ++++++-------------- block/blk-throttle.h | 2 +- include/linux/bio.h | 2 +- include/linux/blk_types.h | 2 +- 5 files changed, 9 insertions(+), 19 deletions(-)
block/bio.c +0 -2
@@ -760,8 +760,6 @@ EXPORT_SYMBOL(bio_put);static int __bio_clone (struct bio *bio,struct bio *bio_src,gfp_t gfp) {bio_set_flag (bio,BIO_CLONED ); -if (bio_flagged (bio_src,BIO_THROTTLED )) -bio_set_flag (bio,BIO_THROTTLED ); bio->bi_ioprio = bio_src->bi_ioprio; bio->bi_iter = bio_src->bi_iter;
block/blk-throttle.c +6 -14
@@ -811,7 +811,7 @@ static bool tg_with_in_bps_limit(structunsigned int bio_size =throtl_bio_data_size (bio);/* no need to throttle if this bio's bytes have been accounted */ -if (bps_limit ==U64_MAX ||bio_flagged (bio,BIO_THROTTLED )) { +if (bps_limit ==U64_MAX ||bio_flagged (bio,BIO_BPS_THROTTLED )) {if (wait) *wait =0 ;return true;
@@ -921,22 +921,13 @@ static void throtl_charge_bio(struct thrunsigned int bio_size =throtl_bio_data_size (bio);/* Charge the bio to the group */ -if (!bio_flagged (bio,BIO_THROTTLED )) { +if (!bio_flagged (bio,BIO_BPS_THROTTLED )) { tg->bytes_disp[rw] += bio_size; tg->last_bytes_disp[rw] += bio_size; } tg->io_disp[rw]++; tg->last_io_disp[rw]++; - -/* -* BIO_THROTTLED is used to prevent the same bio to be throttled -* more than once as a throttled bio will go through blk-throtl the -* second time when it eventually gets issued. Set it when a bio -* is being charged to a tg. -*/ -if (!bio_flagged (bio,BIO_THROTTLED )) -bio_set_flag (bio,BIO_THROTTLED ); }/**
@@ -1026,6 +1017,7 @@ static void tg_dispatch_one_bio(struct t sq->nr_queued[rw]--;throtl_charge_bio (tg, bio); +bio_set_flag (bio,BIO_BPS_THROTTLED );/* * If our parent is another tg, we just need to transfer @bio to
@@ -2159,8 +2151,10 @@ again: qn = &tg->qnode_on_parent[rw]; sq = sq->parent_sq; tg =sq_to_tg (sq); -if (!tg) +if (!tg) { +bio_set_flag (bio,BIO_BPS_THROTTLED ); goto out_unlock; + } }/* out-of-limit, queue to @tg */
@@ -2189,8 +2183,6 @@ again: } out_unlock: -bio_set_flag (bio,BIO_THROTTLED ); -#ifdef CONFIG_BLK_DEV_THROTTLING_LOW if (throttled || !td->track_bio_latency) bio->bi_issue.value |=BIO_ISSUE_THROTL_SKIP_LATENCY ;
block/blk-throttle.h +1 -1
@@ -175,7 +175,7 @@ static inline bool blk_throtl_bio(structstruct throtl_grp *tg =blkg_to_tg (bio->bi_blkg);/* no need to throttle bps any more if the bio has been throttled */ -if (bio_flagged (bio,BIO_THROTTLED ) && +if (bio_flagged (bio,BIO_BPS_THROTTLED ) && !(tg->flags &THROTL_TG_HAS_IOPS_LIMIT ))return false;
include/linux/bio.h +1 -1
@@ -509,7 +509,7 @@ static inline void bio_set_dev(struct bi {bio_clear_flag (bio,BIO_REMAPPED );if (bio->bi_bdev != bdev) -bio_clear_flag (bio,BIO_THROTTLED ); +bio_clear_flag (bio,BIO_BPS_THROTTLED ); bio->bi_bdev = bdev;bio_associate_blkg (bio); }
include/linux/blk_types.h +1 -1
@@ -323,7 +323,7 @@ enum {BIO_QUIET ,/* Make BIO Quiet */ BIO_CHAIN ,/* chained bio, ->bi_remaining in effect */ BIO_REFFED ,/* bio has elevated ->bi_cnt */ -BIO_THROTTLED ,/* This bio has already been subjected to +BIO_BPS_THROTTLED ,/* This bio has already been subjected to * throttling rules. Don't do it again. */ BIO_TRACE_COMPLETION, /* bio_endio() should trace the final completion* of this bio. */
Greg Kroah-Hartman
maintainerPATCH 159/717 blk-wbt: call rq_qos_add() after wb_normal is initialized
In reply to Greg Kroah-HartmanFrom: Yu Kuai <[email protected]>
commit 8c5035dfbb9475b67c82b3fdb7351236525bf52b upstream.
Our test found a problem that wbt inflight counter is negative, which will cause io hang(noted that this problem doesn't exist in mainline):
t1: device create t2: issue ioadd_disk
blk_register_queue
wbt_enable_default
wbt_init
rq_qos_add
// wb_normal is still 0
/*
* in mainline, disk can't be opened before
* bdev_add(), however, in old kernels, disk
* can be opened before blk_register_queue().
*/
blkdev_issue_flush
// disk size is 0, however, it's not checked
submit_bio_wait
submit_bio
blk_mq_submit_bio
rq_qos_throttle
wbt_wait
bio_to_wbt_flags
rwb_enabled
// wb_normal is 0, inflight is not increased
wbt_queue_depth_changed(&rwb->rqos);
wbt_update_limits
// wb_normal is initialized
rq_qos_track
wbt_track
rq->wbt_flags |= bio_to_wbt_flags(rwb, bio);
// wb_normal is not 0,wbt_flags will be sett3: io completionblk_mq_free_request
rq_qos_done
wbt_done
wbt_is_tracked
// return true
__wbt_done
wbt_rqw_done
atomic_dec_return(&rqw->inflight);
// inflight is decreasedcommit 8235b5c1e8c1 ("block: call bdev_add later in device_add_disk") can avoid this problem, however it's better to fix this problem in wbt:
1) Lower kernel can't backport this patch due to lots of refactor.
2) Root cause is that wbt call rq_qos_add() before wb_normal is initialized.
--- block/blk-wbt.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
block/blk-wbt.c +4 -5
@@ -843,6 +843,10 @@ int wbt_init(struct request_queue *q) rwb->enable_state =WBT_STATE_ON_DEFAULT ; rwb->wc =1 ; rwb->rq_depth.default_depth =RWB_DEF_DEPTH ; + rwb->min_lat_nsec =wbt_default_latency_nsec (q); + +wbt_queue_depth_changed (&rwb->rqos); +wbt_set_write_cache (q,test_bit (QUEUE_FLAG_WC , &q->queue_flags));/* * Assign rwb and add the stats callback.
@@ -853,11 +857,6 @@ int wbt_init(struct request_queue *q)blk_stat_add_callback (q, rwb->cb); - rwb->min_lat_nsec =wbt_default_latency_nsec (q); - -wbt_queue_depth_changed (&rwb->rqos); -wbt_set_write_cache (q,test_bit (QUEUE_FLAG_WC , &q->queue_flags)); -return 0 ; err_free:
Greg Kroah-Hartman
maintainerPATCH 160/717 KVM: x86/emulator: Fix handing of POP SS to correctly set interruptibility
In reply to Greg Kroah-HartmanFrom: Michal Luczaj <[email protected]>
commit 6aa5c47c351b22c21205c87977c84809cd015fcf upstream.
The emulator checks the wrong variable while setting the CPU interruptibility state, the target segment is embedded in the instruction opcode, not the ModR/M register. Fix the condition.
--- arch/x86/kvm/emulate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kvm/emulate.c +1 -1
@@ -1955,7 +1955,7 @@ static int em_pop_sreg(struct x86_emulatif (rc !=X86EMUL_CONTINUE )return rc; -if (ctxt->modrm_reg ==VCPU_SREG_SS ) +if (seg ==VCPU_SREG_SS ) ctxt->interruptibility =KVM_X86_SHADOW_INT_MOV_SS ;if (ctxt->op_bytes >2 )rsp_increment (ctxt, ctxt->op_bytes -2 );
Greg Kroah-Hartman
maintainerPATCH 161/717 KVM: nVMX: Unconditionally purge queued/injected events on nested "exit"
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit d953540430c5af57f5de97ea9e36253908204027 upstream.
Drop pending exceptions and events queued for re-injection when leaving nested guest mode, even if the "exit" is due to VM-Fail, SMI, or forced by host userspace. Failure to purge events could result in an event belonging to L2 being injected into L1.
This _should_ never happen for VM-Fail as all events should be blocked by nested_run_pending, but it's possible if KVM, not the L1 hypervisor, is the source of VM-Fail when running vmcs02.
SMI is a nop (barring unknown bugs) as recognition of SMI and thus entry to SMM is blocked by pending exceptions and re-injected events.
Forced exit is definitely buggy, but has likely gone unnoticed because userspace probably follows the forced exit with KVM_SET_VCPU_EVENTS (or some other ioctl() that purges the queue).
--- arch/x86/kvm/vmx/nested.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-)
arch/x86/kvm/vmx/nested.c +11 -8
@@ -4264,14 +4264,6 @@ static void prepare_vmcs12(struct kvm_vcnested_vmx_abort (vcpu,VMX_ABORT_SAVE_GUEST_MSR_FAIL ); } - -/* -* Drop what we picked up for L2 via vmx_complete_interrupts. It is -* preserved above and would only end up incorrectly in L1. -*/ - vcpu->arch.nmi_injected = false; -kvm_clear_exception_queue (vcpu); -kvm_clear_interrupt_queue (vcpu); }/*
@@ -4611,6 +4603,17 @@ void nested_vmx_vmexit(struct kvm_vcpu *WARN_ON_ONCE (nested_early_check); } +/* +* Drop events/exceptions that were queued for re-injection to L2 +* (picked up via vmx_complete_interrupts()), as well as exceptions +* that were pending for L2. Note, this must NOT be hoisted above +* prepare_vmcs12(), events/exceptions queued for re-injection need to +* be captured in vmcs12 (see vmcs12_save_pending_event()). +*/ + vcpu->arch.nmi_injected = false; +kvm_clear_exception_queue (vcpu); +kvm_clear_interrupt_queue (vcpu); +vmx_switch_vmcs (vcpu, &vmx->vmcs01);/* Update any VMCS fields that might have changed while L2 ran */
Greg Kroah-Hartman
maintainerPATCH 162/717 KVM: nVMX: Dont propagate vmcs12s PERF_GLOBAL_CTRL settings to vmcs02
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit def9d705c05eab3fdedeb10ad67907513b12038e upstream.
Don't propagate vmcs12's VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL to vmcs02. KVM doesn't disallow L1 from using VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL even when KVM itself doesn't use the control, e.g. due to the various CPU errata that where the MSR can be corrupted on VM-Exit.
Preserve KVM's (vmcs01) setting to hopefully avoid having to toggle the bit in vmcs02 at a later point. E.g. if KVM is loading PERF_GLOBAL_CTRL when running L1, then odds are good KVM will also load the MSR when running L2.
--- arch/x86/kvm/vmx/nested.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
arch/x86/kvm/vmx/nested.c +6 -1
@@ -2322,9 +2322,14 @@ static void prepare_vmcs02_early(struct* are emulated by vmx_set_efer() in prepare_vmcs02(), but speculate * on the related bits (if supported by the CPU) in the hope that * we can avoid VMWrites during vmx_set_efer(). +* +* Similarly, take vmcs01's PERF_GLOBAL_CTRL in the hope that if KVM is +* loading PERF_GLOBAL_CTRL via the VMCS for L1, then KVM will want to +* do the same for L2. */ exec_control =__vm_entry_controls_get (vmcs01); - exec_control |= vmcs12->vm_entry_controls; + exec_control |= (vmcs12->vm_entry_controls & + ~VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL ); exec_control &= ~(VM_ENTRY_IA32E_MODE |VM_ENTRY_LOAD_IA32_EFER );if (cpu_has_load_ia32_efer ()) {if (guest_efer &EFER_LMA )
Greg Kroah-Hartman
maintainerPATCH 163/717 KVM: VMX: Drop bits 31:16 when shoving exception error code into VMCS
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit eba9799b5a6efe2993cf92529608e4aa8163d73b upstream.
Deliberately truncate the exception error code when shoving it into the VMCS (VM-Entry field for vmcs01 and vmcs02, VM-Exit field for vmcs12). Intel CPUs are incapable of handling 32-bit error codes and will never generate an error code with bits 31:16, but userspace can provide an arbitrary error code via KVM_SET_VCPU_EVENTS. Failure to drop the bits on exception injection results in failed VM-Entry, as VMX disallows setting bits 31:16. Setting the bits on VM-Exit would at best confuse L1, and at worse induce a nested VM-Entry failure, e.g. if L1 decided to reinject the exception back into L2.
--- arch/x86/kvm/vmx/nested.c | 11 ++++++++++- arch/x86/kvm/vmx/vmx.c | 12 +++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-)
arch/x86/kvm/vmx/nested.c +10 -1
@@ -3839,7 +3839,16 @@ static void nested_vmx_inject_exception_u32 intr_info = nr |INTR_INFO_VALID_MASK ;if (vcpu->arch.exception.has_error_code) { - vmcs12->vm_exit_intr_error_code = vcpu->arch.exception.error_code; +/* +* Intel CPUs do not generate error codes with bits 31:16 set, +* and more importantly VMX disallows setting bits 31:16 in the +* injected error code for VM-Entry. Drop the bits to mimic +* hardware and avoid inducing failure on nested VM-Entry if L1 +* chooses to inject the exception back to L2. AMD CPUs _do_ +* generate "full" 32-bit error codes, so KVM allows userspace +* to inject exception error codes with bits 31:16 set. +*/ + vmcs12->vm_exit_intr_error_code = (u16 )vcpu->arch.exception.error_code; intr_info |=INTR_INFO_DELIVER_CODE_MASK ; }
arch/x86/kvm/vmx/vmx.c +11 -1
@@ -1687,7 +1687,17 @@ static void vmx_queue_exception(struct kkvm_deliver_exception_payload (vcpu);if (has_error_code) { -vmcs_write32 (VM_ENTRY_EXCEPTION_ERROR_CODE , error_code); +/* +* Despite the error code being architecturally defined as 32 +* bits, and the VMCS field being 32 bits, Intel CPUs and thus +* VMX don't actually supporting setting bits 31:16. Hardware +* will (should) never provide a bogus error code, but AMD CPUs +* do generate error codes with bits 31:16 set, and so KVM's +* ABI lets userspace shove in arbitrary 32-bit values. Drop +* the upper bits to avoid VM-Fail, losing information that +* does't really exist is preferable to killing the VM. +*/ +vmcs_write32 (VM_ENTRY_EXCEPTION_ERROR_CODE , (u16 )error_code); intr_info |=INTR_INFO_DELIVER_CODE_MASK ; }
Greg Kroah-Hartman
maintainerPATCH 164/717 staging: greybus: audio_helper: remove unused and wrong debugfs usage
In reply to Greg Kroah-HartmanFrom: Greg Kroah-Hartman <[email protected]>
commit d517cdeb904ddc0cbebcc959d43596426cac40b0 upstream.
In the greybus audio_helper code, the debugfs file for the dapm has the potential to be removed and memory will be leaked. There is also the very real potential for this code to remove ALL debugfs entries from the system, and it seems like this is what will really happen if this code ever runs. This all is very wrong as the greybus audio driver did not create this debugfs file, the sound core did and controls the lifespan of it.
So remove all of the debugfs logic from the audio_helper code as there's no way it could be correct. If this really is needed, it can come back with a fixup for the incorrect usage of the debugfs_lookup() call which is what caused this to be noticed at all.
--- drivers/staging/greybus/audio_helper.c | 11 ----------- 1 file changed, 11 deletions(-)
drivers/staging/greybus/audio_helper.c +0 -11
@@ -3,7 +3,6 @@* Greybus Audio Sound SoC helper APIs */ -#include <linux/debugfs.h> #include <sound/core.h> #include <sound/soc.h> #include <sound/soc-dapm.h>
@@ -116,10 +115,6 @@ int gbaudio_dapm_free_controls(struct sn {int i;struct snd_soc_dapm_widget *w, *next_w; -#ifdef CONFIG_DEBUG_FS -struct dentry *parent = dapm->debugfs_dapm; -struct dentry *debugfs_w =NULL ; -#endif mutex_lock (&dapm->card->dapm_mutex);for (i =0 ; i < num; i++) {
@@ -139,12 +134,6 @@ int gbaudio_dapm_free_controls(struct sncontinue ; } widget++; -#ifdef CONFIG_DEBUG_FS -if (!parent) - debugfs_w =debugfs_lookup (w->name, parent); -debugfs_remove (debugfs_w); - debugfs_w =NULL ; -#endif gbaudio_dapm_free_widget (w); }mutex_unlock (&dapm->card->dapm_mutex);
Greg Kroah-Hartman
maintainerPATCH 165/717 drm/nouveau/kms/nv140-: Disable interlacing
In reply to Greg Kroah-HartmanFrom: Lyude Paul <[email protected]>
commit 8ba9249396bef37cb68be9e8dee7847f1737db9d upstream.
As it turns out: while Nvidia does actually have interlacing knobs on their GPU still pretty much no current GPUs since Volta actually support it. Trying interlacing on these GPUs will result in NVDisplay being quite unhappy like so:
nouveau 0000:1f:00.0: disp: chid 0 stat 00004802 reason 4 [INVALID_ARG] mthd 2008 data 00000001 code 00080000 nouveau 0000:1f:00.0: disp: chid 0 stat 10005080 reason 5 [INVALID_STATE] mthd 0200 data 00000001 code 00000001
So let's fix this by following the same behavior Nvidia's driver does and disable interlacing entirely.
--- drivers/gpu/drm/nouveau/nouveau_connector.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/nouveau/nouveau_connector.c +2 -1
@@ -503,7 +503,8 @@ nouveau_connector_set_encoder(struct drm connector->interlace_allowed = nv_encoder->caps.dp_interlace; else - connector->interlace_allowed = true; + connector->interlace_allowed = + drm->client.device.info.family <NV_DEVICE_INFO_V0_VOLTA ; connector->doublescan_allowed = true; }else if (nv_encoder->dcb->type == DCB_OUTPUT_LVDS ||
Greg Kroah-Hartman
maintainerPATCH 166/717 drm/nouveau: fix a use-after-free in nouveau_gem_prime_import_sg_table()
In reply to Greg Kroah-HartmanFrom: Jianglei Nie <[email protected]>
commit 540dfd188ea2940582841c1c220bd035a7db0e51 upstream.
nouveau_bo_init() is backed by ttm_bo_init() and ferries its return code back to the caller. On failures, ttm will call nouveau_bo_del_ttm() and free the memory.Thus, when nouveau_bo_init() returns an error, the gem object has already been released. Then the call to nouveau_bo_ref() will use the freed "nvbo->bo" and lead to a use-after-free bug.
We should delete the call to nouveau_bo_ref() to avoid the use-after-free.
--- drivers/gpu/drm/nouveau/nouveau_prime.c | 1 - 1 file changed, 1 deletion(-)
drivers/gpu/drm/nouveau/nouveau_prime.c +0 -1
@@ -71,7 +71,6 @@ struct drm_gem_object *nouveau_gem_prime ret =nouveau_bo_init (nvbo, size, align,NOUVEAU_GEM_DOMAIN_GART , sg, robj);if (ret) { -nouveau_bo_ref (NULL , &nvbo); obj =ERR_PTR (ret); goto unlock; }
Greg Kroah-Hartman
maintainerPATCH 167/717 drm/i915/gt: Use i915_vm_put on ppgtt_create error paths
In reply to Greg Kroah-HartmanFrom: Chris Wilson <[email protected]>
commit 20e377e7b2e7c327039f10db80ba5bcc1f6c882d upstream.
Now that the scratch page and page directories have a reference back to the i915_address_space, we cannot do an immediate free of the ppgtt upon error as those buffer objects will perform a later i915_vm_put in their deferred frees.
The downside is that by replacing the onion unwind along the error paths, the ppgtt cleanup must handle a partially constructed vm. This includes ensuring that the vm->cleanup is set prior to the error path.
--- drivers/gpu/drm/i915/gt/gen6_ppgtt.c | 16 ++++----- drivers/gpu/drm/i915/gt/gen8_ppgtt.c | 58 ++++++++++++++++++----------------- drivers/gpu/drm/i915/gt/intel_gtt.c | 3 + 3 files changed, 41 insertions(+), 36 deletions(-)
drivers/gpu/drm/i915/gt/gen6_ppgtt.c +8 -8
@@ -247,6 +247,7 @@ err_scratch1:i915_gem_object_put (vm->scratch[1 ]); err_scratch0:i915_gem_object_put (vm->scratch[0 ]); + vm->scratch[0 ] =NULL ;return ret; }
@@ -268,9 +269,10 @@ static void gen6_ppgtt_cleanup(struct i9gen6_ppgtt_free_pd (ppgtt);free_scratch (vm); -mutex_destroy (&ppgtt->flush); +if (ppgtt->base.pd) +free_pd (&ppgtt->base.vm, ppgtt->base.pd); -free_pd (&ppgtt->base.vm, ppgtt->base.pd); +mutex_destroy (&ppgtt->flush); } static void pd_vma_bind(struct i915_address_space *vm,
@@ -449,19 +451,17 @@ struct i915_ppgtt *gen6_ppgtt_create(str err =gen6_ppgtt_init_scratch (ppgtt);if (err) - goto err_free; + goto err_put; ppgtt->base.pd =gen6_alloc_top_pd (ppgtt);if (IS_ERR (ppgtt->base.pd)) { err =PTR_ERR (ppgtt->base.pd); - goto err_scratch; + goto err_put; }return &ppgtt->base; -err_scratch: -free_scratch (&ppgtt->base.vm); -err_free: -kfree (ppgtt); +err_put: +i915_vm_put (&ppgtt->base.vm);return ERR_PTR (err); }
drivers/gpu/drm/i915/gt/gen8_ppgtt.c +30 -28
101 lines not on this page · raw message
drivers/gpu/drm/i915/gt/intel_gtt.c +3 -0
@@ -405,6 +405,9 @@ void free_scratch(struct i915_address_sp {int i; +if (!vm->scratch[0 ]) +return ; +for (i =0 ; i <= vm->top; i++)i915_gem_object_put (vm->scratch[i]); }
Greg Kroah-Hartman
maintainerPATCH 168/717 drm/i915: Fix watermark calculations for gen12+ RC CCS modifier
In reply to Greg Kroah-HartmanFrom: Ville Syrjälä <[email protected]>
commit c56453a00f19ccddee302f5f9fe96b80e0b47fd3 upstream.
Take the gen12+ RC CCS modifier into account when calculating the watermarks. Othwerwise we'll calculate the watermarks thinking this Y-tiled modifier is linear.
The rc_surface part is actually a nop since that is not used for any glk+ platform.
v2: Split RC CCS vs. MC CCS to separate patches
--- drivers/gpu/drm/i915/intel_pm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/intel_pm.c +4 -2
@@ -5307,10 +5307,12 @@ skl_compute_wm_params(const struct intel modifier ==I915_FORMAT_MOD_4_TILED || modifier == I915_FORMAT_MOD_Yf_TILED || modifier ==I915_FORMAT_MOD_Y_TILED_CCS || - modifier == I915_FORMAT_MOD_Yf_TILED_CCS; + modifier == I915_FORMAT_MOD_Yf_TILED_CCS || + modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ; wp->x_tiled = modifier ==I915_FORMAT_MOD_X_TILED ; wp->rc_surface = modifier ==I915_FORMAT_MOD_Y_TILED_CCS || - modifier == I915_FORMAT_MOD_Yf_TILED_CCS; + modifier == I915_FORMAT_MOD_Yf_TILED_CCS || + modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ; wp->is_planar =intel_format_info_is_yuv_semiplanar (format, modifier); wp->width = width;
Greg Kroah-Hartman
maintainerPATCH 169/717 drm/i915: Fix watermark calculations for gen12+ MC CCS modifier
In reply to Greg Kroah-HartmanFrom: Ville Syrjälä <[email protected]>
commit 484b2b9281000274ef7c5cb0a9ebc5da6f5c281c upstream.
Take the gen12+ MC CCS modifier into account when calculating the watermarks. Othwerwise we'll calculate the watermarks thinking this Y-tiled modifier is linear.
The rc_surface part is actually a nop since that is not used for any glk+ platform.
v2: Split RC CCS vs. MC CCS to separate patches
--- drivers/gpu/drm/i915/intel_pm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/intel_pm.c +4 -2
@@ -5308,11 +5308,13 @@ skl_compute_wm_params(const struct intel modifier == I915_FORMAT_MOD_Yf_TILED || modifier ==I915_FORMAT_MOD_Y_TILED_CCS || modifier == I915_FORMAT_MOD_Yf_TILED_CCS || - modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ; + modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS || + modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS ; wp->x_tiled = modifier ==I915_FORMAT_MOD_X_TILED ; wp->rc_surface = modifier ==I915_FORMAT_MOD_Y_TILED_CCS || modifier == I915_FORMAT_MOD_Yf_TILED_CCS || - modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ; + modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS || + modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS ; wp->is_planar =intel_format_info_is_yuv_semiplanar (format, modifier); wp->width = width;
Greg Kroah-Hartman
maintainerPATCH 170/717 drm/i915: Fix watermark calculations for gen12+ CCS+CC modifier
In reply to Greg Kroah-HartmanFrom: Ville Syrjälä <[email protected]>
commit 070a2855900de17b1e11a0dc35af9794e80f1a28 upstream.
Take the gen12+ CCS+CC modifier into account when calculating the watermarks. Othwerwise we'll calculate the watermarks thinking this Y-tiled modifier is linear.
The rc_surface part is actually a nop since that is not used for any glk+ platform.
--- drivers/gpu/drm/i915/intel_pm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/intel_pm.c +4 -2
@@ -5309,12 +5309,14 @@ skl_compute_wm_params(const struct intel modifier ==I915_FORMAT_MOD_Y_TILED_CCS || modifier == I915_FORMAT_MOD_Yf_TILED_CCS || modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS || - modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS ; + modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS || + modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC ; wp->x_tiled = modifier ==I915_FORMAT_MOD_X_TILED ; wp->rc_surface = modifier ==I915_FORMAT_MOD_Y_TILED_CCS || modifier == I915_FORMAT_MOD_Yf_TILED_CCS || modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS || - modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS ; + modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS || + modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC ; wp->is_planar =intel_format_info_is_yuv_semiplanar (format, modifier); wp->width = width;
Greg Kroah-Hartman
maintainerPATCH 171/717 drm/i915: Fix watermark calculations for DG2 CCS modifiers
In reply to Greg Kroah-HartmanFrom: Ville Syrjälä <[email protected]>
commit ccfa6d35f9233702c924316cdf40c05b6ce88113 upstream.
Take the DG2 CCS modifiers into account when calculating the watermarks. Othwerwise we'll calculate the watermarks thinking these tile-4 modifiers are linear.
The rc_surface part is actually a nop since that is not used for any glk+ platform.
--- drivers/gpu/drm/i915/intel_pm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/intel_pm.c +6 -2
@@ -5310,13 +5310,17 @@ skl_compute_wm_params(const struct intel modifier == I915_FORMAT_MOD_Yf_TILED_CCS || modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS || modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS || - modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC ; + modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC || + modifier ==I915_FORMAT_MOD_4_TILED_DG2_RC_CCS || + modifier ==I915_FORMAT_MOD_4_TILED_DG2_MC_CCS ; wp->x_tiled = modifier ==I915_FORMAT_MOD_X_TILED ; wp->rc_surface = modifier ==I915_FORMAT_MOD_Y_TILED_CCS || modifier == I915_FORMAT_MOD_Yf_TILED_CCS || modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS || modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS || - modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC ; + modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC || + modifier ==I915_FORMAT_MOD_4_TILED_DG2_RC_CCS || + modifier ==I915_FORMAT_MOD_4_TILED_DG2_MC_CCS ; wp->is_planar =intel_format_info_is_yuv_semiplanar (format, modifier); wp->width = width;
Greg Kroah-Hartman
maintainerPATCH 172/717 drm/i915: Fix watermark calculations for DG2 CCS+CC modifier
In reply to Greg Kroah-HartmanFrom: Ville Syrjälä <[email protected]>
commit b2e3a1af8cce4117de06ff1a4eab0749753ede27 upstream.
Take the DG2 CCS+CC modifier into account when calculating the watermarks. Othwerwise we'll calculate the watermarks thinking this tile-4 modifier is linear.
The rc_surface part is actually a nop since that is not used for any glk+ platform.
--- drivers/gpu/drm/i915/intel_pm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/intel_pm.c +4 -2
@@ -5312,7 +5312,8 @@ skl_compute_wm_params(const struct intel modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS || modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC || modifier ==I915_FORMAT_MOD_4_TILED_DG2_RC_CCS || - modifier ==I915_FORMAT_MOD_4_TILED_DG2_MC_CCS ; + modifier ==I915_FORMAT_MOD_4_TILED_DG2_MC_CCS || + modifier ==I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC ; wp->x_tiled = modifier ==I915_FORMAT_MOD_X_TILED ; wp->rc_surface = modifier ==I915_FORMAT_MOD_Y_TILED_CCS || modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
@@ -5320,7 +5321,8 @@ skl_compute_wm_params(const struct intel modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS || modifier ==I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC || modifier ==I915_FORMAT_MOD_4_TILED_DG2_RC_CCS || - modifier ==I915_FORMAT_MOD_4_TILED_DG2_MC_CCS ; + modifier ==I915_FORMAT_MOD_4_TILED_DG2_MC_CCS || + modifier ==I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC ; wp->is_planar =intel_format_info_is_yuv_semiplanar (format, modifier); wp->width = width;
Greg Kroah-Hartman
maintainerPATCH 173/717 drm/amd/display: Fix vblank refcount in vrr transition
In reply to Greg Kroah-HartmanFrom: Yunxiang Li <[email protected]>
commit 8799c0be89ebb99a16098bdf618f49f817bef76a upstream.
manage_dm_interrupts disable/enable vblank using drm_crtc_vblank_off/on which causes drm_crtc_vblank_get in vrr_transition to fail, and later when drm_crtc_vblank_put is called the refcount on vblank will be messed up. Therefore move the call to after manage_dm_interrupts.
--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 55 ++++++++++------------ 1 file changed, 26 insertions(+), 29 deletions(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +26 -29
@@ -9157,15 +9157,15 @@ static void amdgpu_dm_handle_vrr_transit* We also need vupdate irq for the actual core vblank handling * at end of vblank. */ -dm_set_vupdate_irq (new_state->base.crtc, true); -drm_crtc_vblank_get (new_state->base.crtc); +WARN_ON (dm_set_vupdate_irq (new_state->base.crtc, true) !=0 ); +WARN_ON (drm_crtc_vblank_get (new_state->base.crtc) !=0 );DRM_DEBUG_DRIVER ("%s: crtc=%u VRR off->on: Get vblank ref\n" , __func__, new_state->base.crtc->base.id); }else if (old_vrr_active && !new_vrr_active) {/* Transition VRR active -> inactive: * Allow vblank irq disable again for fixed refresh rate. */ -dm_set_vupdate_irq (new_state->base.crtc, false); +WARN_ON (dm_set_vupdate_irq (new_state->base.crtc, false) !=0 );drm_crtc_vblank_put (new_state->base.crtc);DRM_DEBUG_DRIVER ("%s: crtc=%u VRR on->off: Drop vblank ref\n" , __func__, new_state->base.crtc->base.id);
@@ -9916,23 +9916,6 @@ static void amdgpu_dm_atomic_commit_tailmutex_unlock (&dm->dc_lock); } -/* Count number of newly disabled CRTCs for dropping PM refs later. */ -for_each_oldnew_crtc_in_state (state, crtc, old_crtc_state, - new_crtc_state, i) { -if (old_crtc_state->active && !new_crtc_state->active) - crtc_disable_count++; - - dm_new_crtc_state =to_dm_crtc_state (new_crtc_state); - dm_old_crtc_state =to_dm_crtc_state (old_crtc_state); - -/* For freesync config update on crtc state and params for irq */ -update_stream_irq_parameters (dm, dm_new_crtc_state); - -/* Handle vrr on->off / off->on transitions */ -amdgpu_dm_handle_vrr_transition (dm_old_crtc_state, - dm_new_crtc_state); - } -/** * Enable interrupts for CRTCs that are newly enabled or went through * a modeset. It was intentionally deferred until after the front end
@@ -9942,16 +9925,29 @@ static void amdgpu_dm_atomic_commit_tailfor_each_oldnew_crtc_in_state (state, crtc, old_crtc_state, new_crtc_state, i) {struct amdgpu_crtc *acrtc =to_amdgpu_crtc (crtc);#ifdef CONFIG_DEBUG_FS -bool configure_crc = false;enum amdgpu_dm_pipe_crc_source cur_crc_src;#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY ) -struct crc_rd_work *crc_rd_wrk = dm->crc_rd_wrk; +struct crc_rd_work *crc_rd_wrk; +#endif +#endif +/* Count number of newly disabled CRTCs for dropping PM refs later. */ +if (old_crtc_state->active && !new_crtc_state->active) + crtc_disable_count++; + + dm_new_crtc_state =to_dm_crtc_state (new_crtc_state); + dm_old_crtc_state =to_dm_crtc_state (old_crtc_state); + +/* For freesync config update on crtc state and params for irq */ +update_stream_irq_parameters (dm, dm_new_crtc_state); + +#ifdef CONFIG_DEBUG_FS +#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY ) + crc_rd_wrk = dm->crc_rd_wrk;#endif spin_lock_irqsave (&adev_to_drm (adev)->event_lock, flags); cur_crc_src = acrtc->dm_irq_params.crc_src;spin_unlock_irqrestore (&adev_to_drm (adev)->event_lock, flags);#endif - dm_new_crtc_state =to_dm_crtc_state (new_crtc_state); if (new_crtc_state->active && (!old_crtc_state->active ||
@@ -9959,16 +9955,19 @@ static void amdgpu_dm_atomic_commit_taildc_stream_retain (dm_new_crtc_state->stream); acrtc->dm_irq_params.stream = dm_new_crtc_state->stream;manage_dm_interrupts (adev, acrtc, true); + } +/* Handle vrr on->off / off->on transitions */ +amdgpu_dm_handle_vrr_transition (dm_old_crtc_state, dm_new_crtc_state);#ifdef CONFIG_DEBUG_FS +if (new_crtc_state->active && + (!old_crtc_state->active || +drm_atomic_crtc_needs_modeset (new_crtc_state))) {/** * Frontend may have changed so reapply the CRC capture * settings for the stream. */ - dm_new_crtc_state =to_dm_crtc_state (new_crtc_state); -if (amdgpu_dm_is_valid_crc_source (cur_crc_src)) { - configure_crc = true;#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY )if (amdgpu_dm_crc_window_is_activated (crtc)) {spin_lock_irqsave (&adev_to_drm (adev)->event_lock, flags);
@@ -9980,12 +9979,10 @@ static void amdgpu_dm_atomic_commit_tailspin_unlock_irqrestore (&adev_to_drm (adev)->event_lock, flags); }#endif - } - -if (configure_crc)if (amdgpu_dm_crtc_configure_crc_source ( crtc, dm_new_crtc_state, cur_crc_src))DRM_DEBUG_DRIVER ("Failed to configure crc source" ); + }#endif } }
Greg Kroah-Hartman
maintainerPATCH 174/717 drm/amd/display: explicitly disable psr_feature_enable appropriately
In reply to Greg Kroah-HartmanFrom: Shirish S <[email protected]>
commit 6094b9136ca9038b61e9c4b5d25cd5512ce50b34 upstream.
[Why]
If psr_feature_enable is set to true by default, it continues to be enabled for non capable links.
[How]
explicitly disable the feature on links that are not capable of the same.
--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c +6 -2
@@ -60,11 +60,15 @@ static bool link_supports_psrsu(struct d*/ void amdgpu_dm_set_psr_caps (struct dc_link *link) { -if (!(link->connector_signal &SIGNAL_TYPE_EDP )) +if (!(link->connector_signal &SIGNAL_TYPE_EDP )) { + link->psr_settings.psr_feature_enabled = false;return ; + } -if (link->type == dc_connection_none) +if (link->type == dc_connection_none) { + link->psr_settings.psr_feature_enabled = false;return ; + }if (link->dpcd_caps.psr_info.psr_version ==0 ) { link->psr_settings.psr_version =DC_PSR_VERSION_UNSUPPORTED ;
Greg Kroah-Hartman
maintainerPATCH 175/717 smb3: must initialize two ACL struct fields to zero
In reply to Greg Kroah-HartmanFrom: Steve French <[email protected]>
commit f09bd695af3b8ab46fc24e5d6954a24104c38387 upstream.
Coverity spotted that we were not initalizing Stbz1 and Stbz2 to zero in create_sd_buf.
Addresses-Coverity: 1513848 ("Uninitialized scalar variable")
--- fs/cifs/smb2pdu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/cifs/smb2pdu.c +2 -1
@@ -2410,7 +2410,7 @@ create_sd_buf(umode_t mode, bool set_ownunsigned int acelen, acl_size, ace_count;unsigned int owner_offset =0 ;unsigned int group_offset =0 ; -struct smb3_acl acl; +struct smb3_acl acl = {}; *len =roundup (sizeof (struct crt_sd_ctxt ) + (sizeof (struct cifs_ace ) *4 ),8 );
@@ -2483,6 +2483,7 @@ create_sd_buf(umode_t mode, bool set_own acl.AclRevision =ACL_REVISION ;/* See 2.4.4.1 of MS-DTYP */ acl.AclSize =cpu_to_le16 (acl_size); acl.AceCount =cpu_to_le16 (ace_count); +/* acl.Sbz1 and Sbz2 MBZ so are not set here, but initialized above */ memcpy (aclptr, &acl,sizeof (struct smb3_acl )); buf->ccontext.DataLength =cpu_to_le32 (ptr - (__u8 *)&buf->sd);
Greg Kroah-Hartman
maintainerPATCH 176/717 selinux: use "grep -E" instead of "egrep"
In reply to Greg Kroah-HartmanFrom: Greg Kroah-Hartman <[email protected]>
commit c969bb8dbaf2f3628927eae73e7c579a74cf1b6e upstream.
The latest version of grep claims that egrep is now obsolete so the build now contains warnings that look like:
egrep: warning: egrep is obsolescent; using grep -E
fix this by using "grep -E" instead.
--- scripts/selinux/install_policy.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
scripts/selinux/install_policy.sh +1 -1
@@ -78,7 +78,7 @@ cd /etc/selinux/dummy/contexts/files $SF -F file_contexts / mounts=`cat /proc/$$/mounts | \ - egrep "ext[234]|jfs|xfs|reiserfs|jffs2|gfs2|btrfs|f2fs|ocfs2" | \ + grep -E "ext[234]|jfs|xfs|reiserfs|jffs2|gfs2|btrfs|f2fs|ocfs2" | \ awk '{ print $2 '}` $SF -F file_contexts $mounts
Greg Kroah-Hartman
maintainerPATCH 177/717 ima: fix blocking of security.ima xattrs of unsupported algorithms
In reply to Greg Kroah-HartmanFrom: Mimi Zohar <[email protected]>
[ Upstream commit 5926586f291b53cb8a0c9631fc19489be1186e2d ]
Limit validating the hash algorithm to just security.ima xattr, not the security.evm xattr or any of the protected EVM security xattrs, nor posix acls.
--- security/integrity/ima/ima_appraise.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
security/integrity/ima/ima_appraise.c +8 -4
@@ -750,22 +750,26 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,const struct evm_ima_xattr_data *xvalue = xattr_value;int digsig =0 ;int result; +int err; result =ima_protect_xattr (dentry, xattr_name, xattr_value, xattr_value_len);if (result ==1 ) {if (!xattr_value_len || (xvalue->type >=IMA_XATTR_LAST ))return -EINVAL ; + + err =validate_hash_algo (dentry, xvalue, xattr_value_len); +if (err) +return err; + digsig = (xvalue->type ==EVM_IMA_XATTR_DIGSIG ); }else if (!strcmp (xattr_name,XATTR_NAME_EVM ) && xattr_value_len >0 ) { digsig = (xvalue->type ==EVM_XATTR_PORTABLE_DIGSIG ); }if (result ==1 ||evm_revalidate_status (xattr_name)) { - result =validate_hash_algo (dentry, xvalue, xattr_value_len); -if (result) -return result; -ima_reset_appraise_flags (d_backing_inode (dentry), digsig); +if (result ==1 ) + result =0 ; }return result; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 178/717 userfaultfd: open userfaultfds with O_RDONLY
In reply to Greg Kroah-HartmanFrom: Ondrej Mosnacek <[email protected]>
[ Upstream commit abec3d015fdfb7c63105c7e1c956188bf381aa55 ]
Since userfaultfd doesn't implement a write operation, it is more appropriate to open it read-only.
When userfaultfds are opened read-write like it is now, and such fd is passed from one process to another, SELinux will check both read and write permissions for the target process, even though it can't actually do any write operation on the fd later.
Inspired by the following bug report, which has hit the SELinux scenario described above:
https://bugzilla.redhat.com/show_bug.cgi?id=1974559
--- fs/userfaultfd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/userfaultfd.c +2 -2
@@ -991,7 +991,7 @@ static int resolve_userfault_fork(struct userfaultfd_ctx *new,int fd; fd =anon_inode_getfd_secure ("[userfaultfd]" , &userfaultfd_fops, new, -O_RDWR | (new->flags &UFFD_SHARED_FCNTL_FLAGS ), inode); +O_RDONLY | (new->flags &UFFD_SHARED_FCNTL_FLAGS ), inode);if (fd <0 )return fd;
@@ -2096,7 +2096,7 @@ SYSCALL_DEFINE1(userfaultfd, int, flags)mmgrab (ctx->mm); fd =anon_inode_getfd_secure ("[userfaultfd]" , &userfaultfd_fops, ctx, -O_RDWR | (flags &UFFD_SHARED_FCNTL_FLAGS ),NULL ); +O_RDONLY | (flags &UFFD_SHARED_FCNTL_FLAGS ),NULL );if (fd <0 ) {mmdrop (ctx->mm);kmem_cache_free (userfaultfd_ctx_cachep, ctx);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 179/717 ntfs3: rework xattr handlers and switch to POSIX ACL VFS helpers
In reply to Greg Kroah-HartmanFrom: Christian Brauner <[email protected]>
[ Upstream commit a26aa12384158116c0d80d50e0bdc7b3323551e2 ]
The xattr code in ntfs3 is currently a bit confused. For example, it defines a POSIX ACL i_op->set_acl() method but instead of relying on the generic POSIX ACL VFS helpers it defines its own set of xattr helpers with the consequence that i_op->set_acl() is currently dead code.
Switch ntfs3 to rely on the VFS POSIX ACL xattr handlers. Also remove i_op->{g,s}et_acl() methods from symlink inode operations. Symlinks don't support xattrs.
This is a preliminary change for the following patches which move handling idmapped mounts directly in posix_acl_xattr_set().
This survives POSIX ACL xfstests.
--- fs/ntfs3/inode.c | 2 - fs/ntfs3/xattr.c | 102 +++-------------------------------------------- 2 files changed, 6 insertions(+), 98 deletions(-)
fs/ntfs3/inode.c +0 -2
@@ -1941,8 +1941,6 @@ const struct inode_operations ntfs_link_inode_operations = { .setattr = ntfs3_setattr, .listxattr = ntfs_listxattr, .permission = ntfs_permission, - .get_acl = ntfs_get_acl, - .set_acl = ntfs_set_acl, };const struct address_space_operations ntfs_aops = {
fs/ntfs3/xattr.c +6 -96
132 lines not on this page · raw message
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 180/717 thermal: cpufreq_cooling: Check the policy first in cpufreq_cooling_register()
In reply to Greg Kroah-HartmanFrom: Xuewen Yan <[email protected]>
[ Upstream commit cff895277c8558221ba180aefe26799dcb4eec86 ]
Since the policy needs to be accessed first when obtaining cpu devices, first check whether the policy is legal before this.
--- drivers/thermal/cpufreq_cooling.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/thermal/cpufreq_cooling.c +5 -5
@@ -530,17 +530,17 @@ __cpufreq_cooling_register(struct device_node *np,struct thermal_cooling_device_ops *cooling_ops;char *name; +if (IS_ERR_OR_NULL (policy)) { +pr_err ("%s: cpufreq policy isn't valid: %p\n" , __func__, policy); +return ERR_PTR (-EINVAL ); + } + dev =get_cpu_device (policy->cpu);if (unlikely (!dev)) {pr_warn ("No cpu device for cpu %d\n" , policy->cpu);return ERR_PTR (-ENODEV ); } -if (IS_ERR_OR_NULL (policy)) { -pr_err ("%s: cpufreq policy isn't valid: %p\n" , __func__, policy); -return ERR_PTR (-EINVAL ); - } - i =cpufreq_table_count_valid_entries (policy);if (!i) { pr_debug("%s: CPUFreq table not found or has no valid entries\n",
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 181/717 cpufreq: amd-pstate: Fix initial highest_perf value
In reply to Greg Kroah-HartmanFrom: Perry Yuan <[email protected]>
[ Upstream commit bedadcfb011fef55273bd686e8893fdd8911dcdb ]
To avoid some new AMD processors use wrong highest perf when amd pstate driver loaded, this fix will query the highest perf from MSR register MSR_AMD_CPPC_CAP1 and cppc_acpi interface firstly, then compare with the highest perf value got by calling amd_get_highest_perf() function.
The lower value will be the correct highest perf we need to use. Otherwise the CPU max MHz will be incorrect if the amd_get_highest_perf() did not cover the new process family and model ID.
Like this lscpu info, the max frequency is incorrect.
Vendor ID: AuthenticAMD
Socket(s): 1
Stepping: 2
CPU max MHz: 5410.0000
CPU min MHz: 400.0000
BogoMIPS: 5600.54--- drivers/cpufreq/amd-pstate.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
drivers/cpufreq/amd-pstate.c +12 -2
@@ -152,6 +152,7 @@ static inline int amd_pstate_enable(bool enable)static int pstate_init_perf (struct amd_cpudata *cpudata) {u64 cap1; +u32 highest_perf;int ret =rdmsrl_safe_on_cpu (cpudata->cpu,MSR_AMD_CPPC_CAP1 , &cap1);
@@ -163,7 +164,11 @@ static int pstate_init_perf(struct amd_cpudata *cpudata)* * CPPC entry doesn't indicate the highest performance in some ASICs. */ -WRITE_ONCE (cpudata->highest_perf,amd_get_highest_perf ()); + highest_perf =amd_get_highest_perf (); +if (highest_perf >AMD_CPPC_HIGHEST_PERF (cap1)) + highest_perf =AMD_CPPC_HIGHEST_PERF (cap1); + +WRITE_ONCE (cpudata->highest_perf, highest_perf);WRITE_ONCE (cpudata->nominal_perf,AMD_CPPC_NOMINAL_PERF (cap1));WRITE_ONCE (cpudata->lowest_nonlinear_perf,AMD_CPPC_LOWNONLIN_PERF (cap1));
@@ -175,12 +180,17 @@ static int pstate_init_perf(struct amd_cpudata *cpudata)static int cppc_init_perf (struct amd_cpudata *cpudata) {struct cppc_perf_caps cppc_perf; +u32 highest_perf;int ret =cppc_get_perf_caps (cpudata->cpu, &cppc_perf);if (ret)return ret; -WRITE_ONCE (cpudata->highest_perf,amd_get_highest_perf ()); + highest_perf =amd_get_highest_perf (); +if (highest_perf > cppc_perf.highest_perf) + highest_perf = cppc_perf.highest_perf; + +WRITE_ONCE (cpudata->highest_perf, highest_perf);WRITE_ONCE (cpudata->nominal_perf, cppc_perf.nominal_perf); WRITE_ONCE(cpudata->lowest_nonlinear_perf,
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 182/717 sh: machvec: Use char[] for section boundaries
In reply to Greg Kroah-HartmanFrom: Kees Cook <[email protected]>
[ Upstream commit c5783af354688b24abd359f7086c282ec74de993 ]
As done for other sections, define the extern as a character array, which relaxes many of the compiler-time object size checks, which would otherwise assume it's a single long. Solves the following build error:
arch/sh/kernel/machvec.c: error: array subscript 'struct sh_machine_vector[0]' is partly outside array bounds of 'long int[1]' [-Werror=array-bounds]: => 105:33
--- arch/sh/include/asm/sections.h | 2 +- arch/sh/kernel/machvec.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-)
arch/sh/include/asm/sections.h +1 -1
@@ -4,7 +4,7 @@#include <asm-generic/sections.h> -extern long __machvec_start, __machvec_end; +extern char __machvec_start[], __machvec_end[];extern char __uncached_start, __uncached_end;extern char __start_eh_frame[], __stop_eh_frame[];
arch/sh/kernel/machvec.c +5 -5
@@ -20,8 +20,8 @@#define MV_NAME_SIZE 32#define for_each_mv (mv) \ - for ((mv) = (struct sh_machine_vector *)&__machvec_start; \ - (mv) && (unsigned long)(mv) < (unsigned long)&__machvec_end; \ + for ((mv) = (struct sh_machine_vector *)__machvec_start; \ + (mv) && (unsigned long)(mv) < (unsigned long)__machvec_end; \ (mv)++)static struct sh_machine_vector *__init get_mv_byname (const char *name)
@@ -87,8 +87,8 @@ void __init sh_mv_setup(void)if (!machvec_selected) {unsigned long machvec_size; - machvec_size = ((unsigned long )&__machvec_end - - (unsigned long )&__machvec_start); + machvec_size = ((unsigned long )__machvec_end - + (unsigned long )__machvec_start);/* * Sanity check for machvec section alignment. Ensure
@@ -102,7 +102,7 @@ void __init sh_mv_setup(void)* vector (usually the only one) from .machvec.init. */ if (machvec_size >=sizeof (struct sh_machine_vector )) - sh_mv = *(struct sh_machine_vector *)&__machvec_start; + sh_mv = *(struct sh_machine_vector *)__machvec_start; }pr_notice ("Booting machvec: %s\n" ,get_system_type ());
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 183/717 MIPS: SGI-IP30: Fix platform-device leak in bridge_platform_create()
In reply to Greg Kroah-HartmanFrom: Lin Yujun <[email protected]>
[ Upstream commit 1e6d11fe72e311c1989991ee318d239f650fa318 ]
In error case in bridge_platform_create after calling platform_device_add()/platform_device_add_data()/ platform_device_add_resources(), release the failed 'pdev' or it will be leak, call platform_device_put() to fix this problem.
Besides, 'pdev' is divided into 'pdev_wd' and 'pdev_bd', use platform_device_unregister() to release sgi_w1 resources when xtalk-bridge registration fails.
--- arch/mips/sgi-ip30/ip30-xtalk.c | 70 +++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 20 deletions(-)
arch/mips/sgi-ip30/ip30-xtalk.c +50 -20
@@ -40,12 +40,15 @@ static void bridge_platform_create(int widget, int masterwid) {struct xtalk_bridge_platform_data *bd;struct sgi_w1_platform_data *wd; -struct platform_device *pdev; +struct platform_device *pdev_wd; +struct platform_device *pdev_bd;struct resource w1_res; wd =kzalloc (sizeof (*wd),GFP_KERNEL ); -if (!wd) - goto no_mem; +if (!wd) { +pr_warn ("xtalk:%x bridge create out of memory\n" , widget); +return ; + }snprintf (wd->dev_id,sizeof (wd->dev_id),"bridge-%012lx" ,IP30_SWIN_BASE (widget));
@@ -56,24 +59,35 @@ static void bridge_platform_create(int widget, int masterwid) w1_res.end = w1_res.start +3 ; w1_res.flags =IORESOURCE_MEM ; - pdev =platform_device_alloc ("sgi_w1" ,PLATFORM_DEVID_AUTO ); -if (!pdev) { -kfree (wd); - goto no_mem; + pdev_wd =platform_device_alloc ("sgi_w1" ,PLATFORM_DEVID_AUTO ); +if (!pdev_wd) { +pr_warn ("xtalk:%x bridge create out of memory\n" , widget); + goto err_kfree_wd; + } +if (platform_device_add_resources (pdev_wd, &w1_res,1 )) { +pr_warn ("xtalk:%x bridge failed to add platform resources.\n" , widget); + goto err_put_pdev_wd; + } +if (platform_device_add_data (pdev_wd, wd,sizeof (*wd))) { +pr_warn ("xtalk:%x bridge failed to add platform data.\n" , widget); + goto err_put_pdev_wd; + } +if (platform_device_add (pdev_wd)) { +pr_warn ("xtalk:%x bridge failed to add platform device.\n" , widget); + goto err_put_pdev_wd; } -platform_device_add_resources (pdev, &w1_res,1 ); -platform_device_add_data (pdev, wd,sizeof (*wd));/* platform_device_add_data() duplicates the data */ kfree (wd); -platform_device_add (pdev); bd =kzalloc (sizeof (*bd),GFP_KERNEL ); -if (!bd) - goto no_mem; - pdev =platform_device_alloc ("xtalk-bridge" ,PLATFORM_DEVID_AUTO ); -if (!pdev) { -kfree (bd); - goto no_mem; +if (!bd) { +pr_warn ("xtalk:%x bridge create out of memory\n" , widget); + goto err_unregister_pdev_wd; + } + pdev_bd =platform_device_alloc ("xtalk-bridge" ,PLATFORM_DEVID_AUTO ); +if (!pdev_bd) { +pr_warn ("xtalk:%x bridge create out of memory\n" , widget); + goto err_kfree_bd; } bd->bridge_addr =IP30_RAW_SWIN_BASE (widget);
@@ -93,15 +107,31 @@ static void bridge_platform_create(int widget, int masterwid) bd->io.flags =IORESOURCE_IO ; bd->io_offset =IP30_SWIN_BASE (widget); -platform_device_add_data (pdev, bd,sizeof (*bd)); +if (platform_device_add_data (pdev_bd, bd,sizeof (*bd))) { +pr_warn ("xtalk:%x bridge failed to add platform data.\n" , widget); + goto err_put_pdev_bd; + } +if (platform_device_add (pdev_bd)) { +pr_warn ("xtalk:%x bridge failed to add platform device.\n" , widget); + goto err_put_pdev_bd; + }/* platform_device_add_data() duplicates the data */ kfree (bd); -platform_device_add (pdev);pr_info ("xtalk:%x bridge widget\n" , widget);return ; -no_mem: -pr_warn ("xtalk:%x bridge create out of memory\n" , widget); +err_put_pdev_bd: +platform_device_put (pdev_bd); +err_kfree_bd: +kfree (bd); +err_unregister_pdev_wd: +platform_device_unregister (pdev_wd); +return ; +err_put_pdev_wd: +platform_device_put (pdev_wd); +err_kfree_wd: +kfree (wd); +return ; }static unsigned int __init xbow_widget_active (s8 wid)
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 184/717 MIPS: SGI-IP27: Fix platform-device leak in bridge_platform_create()
In reply to Greg Kroah-HartmanFrom: Lin Yujun <[email protected]>
[ Upstream commit 11bec9cba4de06b3c0e9e4041453c2caaa1cbec1 ]
In error case in bridge_platform_create after calling platform_device_add()/platform_device_add_data()/ platform_device_add_resources(), release the failed 'pdev' or it will be leak, call platform_device_put() to fix this problem.
Besides, 'pdev' is divided into 'pdev_wd' and 'pdev_bd', use platform_device_unregister() to release sgi_w1 resources when xtalk-bridge registration fails.
--- arch/mips/sgi-ip27/ip27-xtalk.c | 70 +++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 20 deletions(-)
arch/mips/sgi-ip27/ip27-xtalk.c +50 -20
@@ -27,15 +27,18 @@ static void bridge_platform_create(nasid_t nasid, int widget, int masterwid) {struct xtalk_bridge_platform_data *bd;struct sgi_w1_platform_data *wd; -struct platform_device *pdev; +struct platform_device *pdev_wd; +struct platform_device *pdev_bd;struct resource w1_res;unsigned long offset; offset =NODE_OFFSET (nasid); wd =kzalloc (sizeof (*wd),GFP_KERNEL ); -if (!wd) - goto no_mem; +if (!wd) { +pr_warn ("xtalk:n%d/%x bridge create out of memory\n" , nasid, widget); +return ; + }snprintf (wd->dev_id,sizeof (wd->dev_id),"bridge-%012lx" , offset + (widget <<SWIN_SIZE_BITS ));
@@ -46,24 +49,35 @@ static void bridge_platform_create(nasid_t nasid, int widget, int masterwid) w1_res.end = w1_res.start +3 ; w1_res.flags =IORESOURCE_MEM ; - pdev =platform_device_alloc ("sgi_w1" ,PLATFORM_DEVID_AUTO ); -if (!pdev) { -kfree (wd); - goto no_mem; + pdev_wd =platform_device_alloc ("sgi_w1" ,PLATFORM_DEVID_AUTO ); +if (!pdev_wd) { +pr_warn ("xtalk:n%d/%x bridge create out of memory\n" , nasid, widget); + goto err_kfree_wd; + } +if (platform_device_add_resources (pdev_wd, &w1_res,1 )) { +pr_warn ("xtalk:n%d/%x bridge failed to add platform resources.\n" , nasid, widget); + goto err_put_pdev_wd; + } +if (platform_device_add_data (pdev_wd, wd,sizeof (*wd))) { +pr_warn ("xtalk:n%d/%x bridge failed to add platform data.\n" , nasid, widget); + goto err_put_pdev_wd; + } +if (platform_device_add (pdev_wd)) { +pr_warn ("xtalk:n%d/%x bridge failed to add platform device.\n" , nasid, widget); + goto err_put_pdev_wd; } -platform_device_add_resources (pdev, &w1_res,1 ); -platform_device_add_data (pdev, wd,sizeof (*wd));/* platform_device_add_data() duplicates the data */ kfree (wd); -platform_device_add (pdev); bd =kzalloc (sizeof (*bd),GFP_KERNEL ); -if (!bd) - goto no_mem; - pdev =platform_device_alloc ("xtalk-bridge" ,PLATFORM_DEVID_AUTO ); -if (!pdev) { -kfree (bd); - goto no_mem; +if (!bd) { +pr_warn ("xtalk:n%d/%x bridge create out of memory\n" , nasid, widget); + goto err_unregister_pdev_wd; + } + pdev_bd =platform_device_alloc ("xtalk-bridge" ,PLATFORM_DEVID_AUTO ); +if (!pdev_bd) { +pr_warn ("xtalk:n%d/%x bridge create out of memory\n" , nasid, widget); + goto err_kfree_bd; }
@@ -84,15 +98,31 @@ static void bridge_platform_create(nasid_t nasid, int widget, int masterwid) bd->io.flags =IORESOURCE_IO ; bd->io_offset = offset; -platform_device_add_data (pdev, bd,sizeof (*bd)); +if (platform_device_add_data (pdev_bd, bd,sizeof (*bd))) { +pr_warn ("xtalk:n%d/%x bridge failed to add platform data.\n" , nasid, widget); + goto err_put_pdev_bd; + } +if (platform_device_add (pdev_bd)) { +pr_warn ("xtalk:n%d/%x bridge failed to add platform device.\n" , nasid, widget); + goto err_put_pdev_bd; + }/* platform_device_add_data() duplicates the data */ kfree (bd); -platform_device_add (pdev);pr_info ("xtalk:n%d/%x bridge widget\n" , nasid, widget);return ; -no_mem: -pr_warn ("xtalk:n%d/%x bridge create out of memory\n" , nasid, widget); +err_put_pdev_bd: +platform_device_put (pdev_bd); +err_kfree_bd: +kfree (bd); +err_unregister_pdev_wd: +platform_device_unregister (pdev_wd); +return ; +err_put_pdev_wd: +platform_device_put (pdev_wd); +err_kfree_wd: +kfree (wd); +return ; }static int probe_one_port (nasid_t nasid,int widget,int masterwid)
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 185/717 erofs: fix order >= MAX_ORDER warning due to crafted negative i_size
In reply to Greg Kroah-HartmanFrom: Gao Xiang <[email protected]>
[ Upstream commit 1dd73601a1cba37a0ed5f89a8662c90191df5873 ]
As syzbot reported [1], the root cause is that i_size field is a signed type, and negative i_size is also less than EROFS_BLKSIZ. As a consequence, it's handled as fast symlink unexpectedly.
Let's fall back to the generic path to deal with such unusual i_size.
[1] https://lore.kernel.org/r/[email protected]
--- fs/erofs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/erofs/inode.c +1 -1
@@ -214,7 +214,7 @@ static int erofs_fill_symlink(struct inode *inode, void *kaddr,/* if it cannot be handled with fast symlink scheme */ if (vi->datalayout !=EROFS_INODE_FLAT_INLINE || - inode->i_size >=EROFS_BLKSIZ ) { + inode->i_size >=EROFS_BLKSIZ || inode->i_size <0 ) { inode->i_op = &erofs_symlink_iops;return 0 ; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 186/717 erofs: use kill_anon_super() to kill super in fscache mode
In reply to Greg Kroah-HartmanFrom: Jia Zhu <[email protected]>
[ Upstream commit 1015c1016c231b26d4e2c9b3da65b6c043eb97a3 ]
Use kill_anon_super() instead of generic_shutdown_super() since the mount() in erofs fscache mode uses get_tree_nodev() and associated anon bdev needs to be freed.
--- fs/erofs/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/erofs/super.c +1 -1
@@ -877,7 +877,7 @@ static void erofs_kill_sb(struct super_block *sb)WARN_ON (sb->s_magic !=EROFS_SUPER_MAGIC );if (erofs_is_fscache_mode (sb)) -generic_shutdown_super (sb); +kill_anon_super (sb);else kill_block_super (sb);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 187/717 ARM: 9243/1: riscpc: Unbreak the build
In reply to Greg Kroah-HartmanFrom: Bart Van Assche <[email protected]>
[ Upstream commit 32844a8eecaa4a3e65841c53e43e04a9087d1ef6 ]
This patch fixes the following build error:
In file included from ./include/linux/io.h:13,
from ./arch/arm/mach-rpc/include/mach/uncompress.h:9, from arch/arm/boot/compressed/misc.c:31:./arch/arm/include/asm/io.h:85:22: error: conflicting types for ‘__raw_writeb’
85 | #define __raw_writeb __raw_writeb
| ^~~~~~~~~~~~
./arch/arm/include/asm/io.h:86:20: note: in expansion of macro ‘__raw_writeb’
86 | static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
| ^~~~~~~~~~~~
In file included from arch/arm/boot/compressed/misc.c:26:
arch/arm/boot/compressed/misc-ep93xx.h:13:20: note: previous definition of ‘__raw_writeb’ was here
13 | static inline void __raw_writeb(unsigned char value, unsigned int ptr)
| ^~~~~~~~~~~~To: Russell King <[email protected]>
--- arch/arm/boot/compressed/misc.c | 2 ++ 1 file changed, 2 insertions(+)
arch/arm/boot/compressed/misc.c +2 -0
@@ -23,7 +23,9 @@ unsigned int __machine_arch_type;#include <linux/types.h> #include <linux/linkage.h> #include "misc.h" +#ifdef CONFIG_ARCH_EP93XX #include "misc-ep93xx.h" +#endif static void putstr (const char *ptr);
Signature · 9 lines
2.35.1 _______________________________________________ linux-arm-kernel mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Greg Kroah-Hartman
maintainerPATCH 188/717 ARM: 9244/1: dump: Fix wrong pg_level in walk_pmd()
In reply to Greg Kroah-HartmanFrom: Wang Kefeng <[email protected]>
[ Upstream commit 2ccd19b3ffac07cc7e75a2bd1ed779728bb67197 ]
After ARM supports p4d page tables, the pg_level for note_page() in walk_pmd() should be 4, not 3, fix it.
--- arch/arm/mm/dump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/mm/dump.c +1 -1
@@ -346,7 +346,7 @@ static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start) addr = start + i *PMD_SIZE ; domain =get_domain_name (pmd);if (pmd_none (*pmd) ||pmd_large (*pmd) || !pmd_present (*pmd)) -note_page (st, addr,3 ,pmd_val (*pmd), domain); +note_page (st, addr,4 ,pmd_val (*pmd), domain);else walk_pte (st, pmd, addr, domain);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 189/717 ARM: 9247/1: mm: set readonly for MT_MEMORY_RO with ARM_LPAE
In reply to Greg Kroah-HartmanFrom: Wang Kefeng <[email protected]>
[ Upstream commit 14ca1a4690750bb54e1049e49f3140ef48958a6e ]
MT_MEMORY_RO is introduced by commit 598f0a99fa8a ("ARM: 9210/1:
Mark the FDT_FIXED sections as shareable"), which is a readonly memory type for FDT area, but there are some different between ARM_LPAE and non-ARM_LPAE, we need to setup PMD_SECT_AP2 and L_PMD_SECT_RDONLY for MT_MEMORY_RO when ARM_LAPE enabled.
non-ARM_LPAE 0xff800000-0xffa00000 2M PGD KERNEL ro NX SHDARM_LPAE 0xff800000-0xffc00000 4M PMD RW NX SHD
ARM_LPAE+fix 0xff800000-0xffc00000 4M PMD ro NX SHD
--- arch/arm/mm/mmu.c | 4 ++++ 1 file changed, 4 insertions(+)
arch/arm/mm/mmu.c +4 -0
@@ -300,7 +300,11 @@ static struct mem_type mem_types[] __ro_after_init = { .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_XN | L_PTE_RDONLY, .prot_l1 =PMD_TYPE_TABLE , +#ifdef CONFIG_ARM_LPAE + .prot_sect = PMD_TYPE_SECT | L_PMD_SECT_RDONLY | PMD_SECT_AP2, +#else .prot_sect = PMD_TYPE_SECT, +#endif .domain = DOMAIN_KERNEL, }, [MT_ROM] = {
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 190/717 ACPI: PCC: Release resources on address space setup failure path
In reply to Greg Kroah-HartmanFrom: Rafael Mendonca <[email protected]>
[ Upstream commit f890157e61b85ce8ae01a41ffa375e3b99853698 ]
The allocated memory for the pcc_data struct doesn't get freed under an error path in pcc_mbox_request_channel() or acpi_os_ioremap(). Also, the PCC mailbox channel doesn't get freed under an error path in acpi_os_ioremap().
--- drivers/acpi/acpi_pcc.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/acpi/acpi_pcc.c +3 -0
@@ -63,6 +63,7 @@ acpi_pcc_address_space_setup(acpi_handle region_handle, u32 function,if (IS_ERR (data->pcc_chan)) {pr_err ("Failed to find PCC channel for subspace %d\n" , ctx->subspace_id); +kfree (data);return AE_NOT_FOUND ; }
@@ -72,6 +73,8 @@ acpi_pcc_address_space_setup(acpi_handle region_handle, u32 function,if (!data->pcc_comm_addr) {pr_err ("Failed to ioremap PCC comm region mem for %d\n" , ctx->subspace_id); +pcc_mbox_free_channel (data->pcc_chan); +kfree (data);return AE_NO_MEMORY ; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 191/717 ACPI: PCC: replace wait_for_completion()
In reply to Greg Kroah-HartmanFrom: Huisong Li <[email protected]>
[ Upstream commit 91cefefb699120efd0a5ba345d12626b688f86ce ]
Currently, the function waiting for completion of mailbox operation is 'wait_for_completion()'. The PCC method will be permanently blocked if this mailbox message fails to execute. So this patch replaces it with 'wait_for_completion_timeout()'. And set the timeout interval to an arbitrary retries on top of nominal to prevent the remote processor is slow to respond to PCC commands.
--- drivers/acpi/acpi_pcc.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-)
drivers/acpi/acpi_pcc.c +21 -2
@@ -23,6 +23,12 @@#include <acpi/pcc.h> +/* +* Arbitrary retries in case the remote processor is slow to respond +* to PCC commands +*/ +#define PCC_CMD_WAIT_RETRIES_NUM 500 +struct pcc_data {struct pcc_mbox_chan *pcc_chan;void __iomem *pcc_comm_addr;
@@ -89,6 +95,7 @@ acpi_pcc_address_space_handler(u32 function, acpi_physical_address addr, {int ret;struct pcc_data *data = region_context; +u64 usecs_lat;reinit_completion (&data->done);
@@ -99,8 +106,20 @@ acpi_pcc_address_space_handler(u32 function, acpi_physical_address addr,if (ret <0 )return AE_ERROR ; -if (data->pcc_chan->mchan->mbox->txdone_irq) -wait_for_completion (&data->done); +if (data->pcc_chan->mchan->mbox->txdone_irq) { +/* +* pcc_chan->latency is just a Nominal value. In reality the remote +* processor could be much slower to reply. So add an arbitrary +* amount of wait on top of Nominal. +*/ + usecs_lat =PCC_CMD_WAIT_RETRIES_NUM * data->pcc_chan->latency; + ret =wait_for_completion_timeout (&data->done, +usecs_to_jiffies (usecs_lat)); +if (ret ==0 ) { +pr_err ("PCC command executed timeout!\n" ); +return AE_TIME ; + } + }mbox_client_txdone (data->pcc_chan->mchan, ret);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 192/717 ACPI: PCC: Fix Tx acknowledge in the PCC address space handler
In reply to Greg Kroah-HartmanFrom: Huisong Li <[email protected]>
[ Upstream commit 18729106c26fb97d4c9ae63ba7aba9889a058dc4 ]
Currently, mbox_client_txdone() is called from the PCC address space handler and that expects the user the Tx state machine to be controlled by the client which is not the case and the below warning is thrown:
| PCCT: Client can't run the TX ticker
Let the controller run the state machine and the end of Tx can be acknowledge by calling mbox_chan_txdone() instead.
--- drivers/acpi/acpi_pcc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/acpi_pcc.c +1 -1
@@ -121,7 +121,7 @@ acpi_pcc_address_space_handler(u32 function, acpi_physical_address addr, } } -mbox_client_txdone (data->pcc_chan->mchan, ret); +mbox_chan_txdone (data->pcc_chan->mchan, ret);memcpy_fromio (value, data->pcc_comm_addr, data->ctx.length);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 193/717 objtool: Preserve special st_shndx indexes in elf_update_symbol
In reply to Greg Kroah-HartmanFrom: Sami Tolvanen <[email protected]>
[ Upstream commit 5141d3a06b2da1731ac82091298b766a1f95d3d8 ]
elf_update_symbol fails to preserve the special st_shndx values between [SHN_LORESERVE, SHN_HIRESERVE], which results in it converting SHN_ABS entries into SHN_UNDEF, for example. Explicitly check for the special indexes and ensure these symbols are not marked undefined.
--- tools/objtool/elf.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
tools/objtool/elf.c +6 -1
@@ -619,6 +619,11 @@ static int elf_update_symbol(struct elf *elf, struct section *symtab,Elf64_Xword entsize = symtab->sh.sh_entsize;int max_idx, idx = sym->idx;Elf_Scn *s, *t =NULL ; +bool is_special_shndx = sym->sym.st_shndx >=SHN_LORESERVE && + sym->sym.st_shndx !=SHN_XINDEX ; + +if (is_special_shndx) + shndx = sym->sym.st_shndx; s =elf_getscn (elf->elf, symtab->idx);if (!s) {
@@ -704,7 +709,7 @@ static int elf_update_symbol(struct elf *elf, struct section *symtab, }/* setup extended section index magic and write the symbol */ -if (shndx >=SHN_UNDEF && shndx <SHN_LORESERVE ) { +if ((shndx >=SHN_UNDEF && shndx <SHN_LORESERVE ) || is_special_shndx) { sym->sym.st_shndx = shndx;if (!shndx_data) shndx =0 ;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 194/717 nfsd: Fix a memory leak in an error handling path
In reply to Greg Kroah-HartmanFrom: Christophe JAILLET <[email protected]>
[ Upstream commit fd1ef88049de09bc70d60b549992524cfc0e66ff ]
If this memdup_user() call fails, the memory allocated in a previous call a few lines above should be freed. Otherwise it leaks.
--- fs/nfsd/nfs4recover.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
fs/nfsd/nfs4recover.c +3 -1
@@ -815,8 +815,10 @@ __cld_pipe_inprogress_downcall(const struct cld_msg_v2 __user *cmsg, princhash.data =memdup_user ( &ci->cc_princhash.cp_data, princhashlen); -if (IS_ERR_OR_NULL (princhash.data)) +if (IS_ERR_OR_NULL (princhash.data)) { +kfree (name.data);return -EFAULT ; + } princhash.len = princhashlen; }else princhash.len =0 ;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 195/717 SUNRPC: Fix svcxdr_init_decodes end-of-buffer calculation
In reply to Greg Kroah-HartmanFrom: Chuck Lever <[email protected]>
[ Upstream commit 90bfc37b5ab91c1a6165e3e5cfc49bf04571b762 ]
Ensure that stream-based argument decoding can't go past the actual end of the receive buffer. xdr_init_decode's calculation of the value of xdr->end over-estimates the end of the buffer because the Linux kernel RPC server code does not remove the size of the RPC header from rqstp->rq_arg before calling the upper layer's dispatcher.
The server-side still uses the svc_getnl() macros to decode the RPC call header. These macros reduce the length of the head iov but do not update the total length of the message in the buffer (buf->len).
A proper fix for this would be to replace the use of svc_getnl() and friends in the RPC header decoder, but that would be a large and invasive change that would be difficult to backport.
--- include/linux/sunrpc/svc.h | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-)
include/linux/sunrpc/svc.h +14 -3
@@ -544,16 +544,27 @@ static inline void svc_reserve_auth(struct svc_rqst *rqstp, int space) }/** -* svcxdr_init_decode - Prepare an xdr_stream for svc Call decoding +* svcxdr_init_decode - Prepare an xdr_stream for Call decoding * @rqstp: controlling server RPC transaction context * +* This function currently assumes the RPC header in rq_arg has +* already been decoded. Upon return, xdr->p points to the +* location of the upper layer header. */ static inline void svcxdr_init_decode (struct svc_rqst *rqstp) {struct xdr_stream *xdr = &rqstp->rq_arg_stream; -struct kvec *argv = rqstp->rq_arg.head; +struct xdr_buf *buf = &rqstp->rq_arg; +struct kvec *argv = buf->head; -xdr_init_decode (xdr, &rqstp->rq_arg, argv->iov_base,NULL ); +/* +* svc_getnl() and friends do not keep the xdr_buf's ::len +* field up to date. Refresh that field before initializing +* the argument decoding stream. +*/ + buf->len = buf->head->iov_len + buf->page_len + buf->tail->iov_len; + +xdr_init_decode (xdr, buf, argv->iov_base,NULL );xdr_set_scratch_page (xdr, rqstp->rq_scratch_page); }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 196/717 SUNRPC: Fix svcxdr_init_encodes buflen calculation
In reply to Greg Kroah-HartmanFrom: Chuck Lever <[email protected]>
[ Upstream commit 1242a87da0d8cd2a428e96ca68e7ea899b0f4624 ]
Commit 2825a7f90753 ("nfsd4: allow encoding across page boundaries") added an explicit computation of the remaining length in the rq_res XDR buffer.
The computation appears to suffer from an "off-by-one" bug. Because buflen is too large by one page, XDR encoding can run off the end of the send buffer by eventually trying to use the struct page address in rq_page_end, which always contains NULL.
--- include/linux/sunrpc/svc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/sunrpc/svc.h +1 -1
@@ -587,7 +587,7 @@ static inline void svcxdr_init_encode(struct svc_rqst *rqstp) xdr->end = resv->iov_base +PAGE_SIZE - rqstp->rq_auth_slack; buf->len = resv->iov_len; xdr->page_ptr = buf->pages -1 ; - buf->buflen =PAGE_SIZE * (1 + rqstp->rq_page_end - buf->pages); + buf->buflen =PAGE_SIZE * (rqstp->rq_page_end - buf->pages); buf->buflen -= rqstp->rq_auth_slack; xdr->rqst =NULL ; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 197/717 NFSD: Protect against send buffer overflow in NFSv2 READDIR
In reply to Greg Kroah-HartmanFrom: Chuck Lever <[email protected]>
[ Upstream commit 00b4492686e0497fdb924a9d4c8f6f99377e176c ]
Restore the previous limit on the @count argument to prevent a buffer overflow attack.
--- fs/nfsd/nfsproc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
fs/nfsd/nfsproc.c +2 -3
@@ -557,12 +557,11 @@ static void nfsd_init_dirlist_pages(struct svc_rqst *rqstp,struct xdr_buf *buf = &resp->dirlist;struct xdr_stream *xdr = &resp->xdr; - count =clamp (count, (u32)(XDR_UNIT *2 ),svc_max_payload (rqstp)); -memset (buf,0 ,sizeof (*buf));/* Reserve room for the NULL ptr & eof flag (-2 words) */ - buf->buflen = count -XDR_UNIT *2 ; + buf->buflen =clamp (count, (u32)(XDR_UNIT *2 ), (u32 )PAGE_SIZE ); + buf->buflen -=XDR_UNIT *2 ; buf->pages = rqstp->rq_next_page; rqstp->rq_next_page++;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 198/717 NFSD: Fix handling of oversized NFSv4 COMPOUND requests
In reply to Greg Kroah-HartmanFrom: Chuck Lever <[email protected]>
[ Upstream commit 7518a3dc5ea249d4112156ce71b8b184eb786151 ]
If an NFS server returns NFS4ERR_RESOURCE on the first operation in an NFSv4 COMPOUND, there's no way for a client to know where the problem is and then simplify the compound to make forward progress.
So instead, make NFSD process as many operations in an oversized COMPOUND as it can and then return NFS4ERR_RESOURCE on the first operation it did not process.
pynfs NFSv4.0 COMP6 exercises this case, but checks only for the COMPOUND status code, not whether the server has processed any of the operations.
pynfs NFSv4.1 SEQ6 and SEQ7 exercise the NFSv4.1 case, which detects too many operations per COMPOUND by checking against the limits negotiated when the session was created.
--- fs/nfsd/nfs4proc.c | 19 +++++++++++++------ fs/nfsd/nfs4xdr.c | 12 +++--------- fs/nfsd/xdr4.h | 3 ++- 3 files changed, 18 insertions(+), 16 deletions(-)
fs/nfsd/nfs4proc.c +13 -6
@@ -2663,9 +2663,6 @@ nfsd4_proc_compound(struct svc_rqst *rqstp) status = nfserr_minor_vers_mismatch;if (nfsd_minorversion (nn, args->minorversion,NFSD_TEST ) <=0 ) goto out; - status = nfserr_resource; -if (args->opcnt >NFSD_MAX_OPS_PER_COMPOUND ) - goto out; status =nfs41_check_op_ordering (args);if (status) {
@@ -2678,10 +2675,20 @@ nfsd4_proc_compound(struct svc_rqst *rqstp) rqstp->rq_lease_breaker = (void **)&cstate->clp; -trace_nfsd_compound (rqstp, args->opcnt); +trace_nfsd_compound (rqstp, args->client_opcnt);while (!status && resp->opcnt < args->opcnt) { op = &args->ops[resp->opcnt++]; +if (unlikely (resp->opcnt ==NFSD_MAX_OPS_PER_COMPOUND )) { +/* If there are still more operations to process, +* stop here and report NFS4ERR_RESOURCE. */ +if (cstate->minorversion ==0 && + args->client_opcnt > resp->opcnt) { + op->status = nfserr_resource; + goto encode_op; + } + } +/* * The XDR decode routines may have pre-set op->status; * for example, if there is a miscellaneous XDR error
@@ -2757,8 +2764,8 @@ nfsd4_proc_compound(struct svc_rqst *rqstp) status = op->status; } -trace_nfsd_compound_status (args->opcnt, resp->opcnt, status, -nfsd4_op_name (op->opnum)); +trace_nfsd_compound_status (args->client_opcnt, resp->opcnt, + status,nfsd4_op_name (op->opnum));nfsd4_cstate_clear_replay (cstate);nfsd4_increment_op_stats (op->opnum);
fs/nfsd/nfs4xdr.c +3 -9
@@ -2347,16 +2347,10 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)if (xdr_stream_decode_u32 (argp->xdr, &argp->minorversion) <0 )return false; -if (xdr_stream_decode_u32 (argp->xdr, &argp->opcnt) <0 ) +if (xdr_stream_decode_u32 (argp->xdr, &argp->client_opcnt) <0 )return false; - -/* -* NFS4ERR_RESOURCE is a more helpful error than GARBAGE_ARGS -* here, so we return success at the xdr level so that -* nfsd4_proc can handle this is an NFS-level error. -*/ -if (argp->opcnt >NFSD_MAX_OPS_PER_COMPOUND ) -return true; + argp->opcnt =min_t (u32, argp->client_opcnt, +NFSD_MAX_OPS_PER_COMPOUND );if (argp->opcnt >ARRAY_SIZE (argp->iops)) { argp->ops =kzalloc (argp->opcnt *sizeof (*argp->ops),GFP_KERNEL );
fs/nfsd/xdr4.h +2 -1
@@ -689,9 +689,10 @@ struct nfsd4_compoundargs {struct svcxdr_tmpbuf *to_free;struct svc_rqst *rqstp; -u32 taglen;char * tag; +u32 taglen;u32 minorversion; +u32 client_opcnt;u32 opcnt;struct nfsd4_op *ops;struct nfsd4_op iops[8 ];
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 199/717 x86/paravirt: add extra clobbers with ZERO_CALL_USED_REGS enabled
In reply to Greg Kroah-HartmanFrom: Bill Wendling <[email protected]>
[ Upstream commit 8c86f29bfb18465d15b05cfd26a6454ec787b793 ]
The ZERO_CALL_USED_REGS feature may zero out caller-saved registers before returning.
In spurious_kernel_fault(), the "pte_offset_kernel()" call results in this assembly code:
.Ltmp151:
#APP
# ALT: oldnstr
.Ltmp152:
.Ltmp153:
.Ltmp154:
.section .discard.retpoline_safe,"",@progbits
.quad .Ltmp154
.text
callq *pv_ops+536(%rip).Ltmp155:
.section .parainstructions,"a",@progbits
.p2align 3, 0x0
.quad .Ltmp153
.byte 67
.byte .Ltmp155-.Ltmp153
.short 1
.text.Ltmp156:
# ALT: padding
.zero (-(((.Ltmp157-.Ltmp158)-(.Ltmp156-.Ltmp152))>0))*((.Ltmp157-.Ltmp158)-(.Ltmp156-.Ltmp152)),144
.Ltmp159:
.section .altinstructions,"a",@progbits
.Ltmp160:
.long .Ltmp152-.Ltmp160
.Ltmp161:
.long .Ltmp158-.Ltmp161
.short 33040
.byte .Ltmp159-.Ltmp152
.byte .Ltmp157-.Ltmp158.text
.section .altinstr_replacement,"ax",@progbits
# ALT: replacement 1
.Ltmp158:
movq %rdi, %rax
.Ltmp157:
.text
#NO_APP
.Ltmp162:
testb $-128, %dilThe "testb" here is using %dil, but the %rdi register was cleared before returning from "callq *pv_ops+536(%rip)". Adding the proper constraints results in the use of a different register:
movq %r11, %rdi
# Similar to above.
testb $-128, %r11b--- arch/x86/include/asm/paravirt_types.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
arch/x86/include/asm/paravirt_types.h +10 -1
@@ -414,8 +414,17 @@ int paravirt_disable_iospace(void); "=c" (__ecx)#define PVOP_CALL_CLOBBERS PVOP_VCALL_CLOBBERS, "=a" (__eax) -/* void functions are still allowed [re]ax for scratch */ +/* +* void functions are still allowed [re]ax for scratch. +* +* The ZERO_CALL_USED REGS feature may end up zeroing out callee-saved +* registers. Make sure we model this with the appropriate clobbers. +*/ +#ifdef CONFIG_ZERO_CALL_USED_REGS +#define PVOP_VCALLEE_CLOBBERS "=a" (__eax), PVOP_VCALL_CLOBBERS +#else #define PVOP_VCALLEE_CLOBBERS "=a" (__eax) +#endif #define PVOP_CALLEE_CLOBBERS PVOP_VCALLEE_CLOBBERS#define EXTRA_CLOBBERS , "r8", "r9", "r10", "r11"
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 200/717 wifi: rtlwifi: 8192de: correct checking of IQK reload
In reply to Greg Kroah-HartmanFrom: Ping-Ke Shih <[email protected]>
[ Upstream commit 93fbc1ebd978cf408ef5765e9c1630fce9a8621b ]
Since IQK could spend time, we make a cache of IQK result matrix that looks like iqk_matrix[channel_idx].val[x][y], and we can reload the matrix if we have made a cache. To determine a cache is made, we check iqk_matrix[channel_idx].val[0][0].
The initial commit 7274a8c22980 ("rtlwifi: rtl8192de: Merge phy routines") make a mistake that checks incorrect iqk_matrix[channel_idx].val[0] that is always true, and this mistake is found by commit ee3db469dd31 ("wifi: rtlwifi: remove always-true condition pointed out by GCC 12"), so I recall the vendor driver to find fix and apply the correctness.
--- drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c +4 -5
@@ -2386,11 +2386,10 @@ void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel)rtl_dbg (rtlpriv,COMP_SCAN ,DBG_LOUD ,"Just Read IQK Matrix reg for channel:%d....\n" , channel); -_rtl92d_phy_patha_fill_iqk_matrix (hw, true, - rtlphy->iqk_matrix[ - indexforchannel].value,0 , - (rtlphy->iqk_matrix[ - indexforchannel].value[0 ][2 ] ==0 )); +if (rtlphy->iqk_matrix[indexforchannel].value[0 ][0 ] !=0 ) +_rtl92d_phy_patha_fill_iqk_matrix (hw, true, + rtlphy->iqk_matrix[indexforchannel].value,0 , + rtlphy->iqk_matrix[indexforchannel].value[0 ][2 ] ==0 );if (IS_92D_SINGLEPHY (rtlhal->version)) {if ((rtlphy->iqk_matrix[ indexforchannel].value[0][4] != 0)
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 201/717 wifi: ath10k: add peer map clean up for peer delete in ath10k_sta_state()
In reply to Greg Kroah-HartmanFrom: Wen Gong <[email protected]>
[ Upstream commit f020d9570a04df0762a2ac5c50cf1d8c511c9164 ]
When peer delete failed in a disconnect operation, use-after-free detected by KFENCE in below log. It is because for each vdev_id and address, it has only one struct ath10k_peer, it is allocated in ath10k_peer_map_event(). When connected to an AP, it has more than one HTT_T2H_MSG_TYPE_PEER_MAP reported from firmware, then the array peer_map of struct ath10k will be set muti-elements to the same ath10k_peer in ath10k_peer_map_event(). When peer delete failed in ath10k_sta_state(), the ath10k_peer will be free for the 1st peer id in array peer_map of struct ath10k, and then use-after-free happened for the 2nd peer id because they map to the same ath10k_peer.
And clean up all peers in array peer_map for the ath10k_peer, then user-after-free disappeared
peer map event log:
[ 306.911021] wlan0: authenticate with b0:2a:43:e6:75:0e [ 306.957187] ath10k_pci 0000:01:00.0: mac vdev 0 peer create b0:2a:43:e6:75:0e (new sta) sta 1 / 32 peer 1 / 33 [ 306.957395] ath10k_pci 0000:01:00.0: htt peer map vdev 0 peer b0:2a:43:e6:75:0e id 246 [ 306.957404] ath10k_pci 0000:01:00.0: htt peer map vdev 0 peer b0:2a:43:e6:75:0e id 198 [ 306.986924] ath10k_pci 0000:01:00.0: htt peer map vdev 0 peer b0:2a:43:e6:75:0e id 166
peer unmap event log:
[ 435.715691] wlan0: deauthenticating from b0:2a:43:e6:75:0e by local choice (Reason: 3=DEAUTH_LEAVING) [ 435.716802] ath10k_pci 0000:01:00.0: mac vdev 0 peer delete b0:2a:43:e6:75:0e sta ffff990e0e9c2b50 (sta gone) [ 435.717177] ath10k_pci 0000:01:00.0: htt peer unmap vdev 0 peer b0:2a:43:e6:75:0e id 246 [ 435.717186] ath10k_pci 0000:01:00.0: htt peer unmap vdev 0 peer b0:2a:43:e6:75:0e id 198 [ 435.717193] ath10k_pci 0000:01:00.0: htt peer unmap vdev 0 peer b0:2a:43:e6:75:0e id 166
use-after-free log:
[21705.888627] wlan0: deauthenticating from d0:76:8f:82:be:75 by local choice (Reason: 3=DEAUTH_LEAVING) [21713.799910] ath10k_pci 0000:01:00.0: failed to delete peer d0:76:8f:82:be:75 for vdev 0: -110 [21713.799925] ath10k_pci 0000:01:00.0: found sta peer d0:76:8f:82:be:75 (ptr 0000000000000000 id 102) entry on vdev 0 after it was supposedly removed [21713.799968] ================================================================== [21713.799991] BUG: KFENCE: use-after-free read in ath10k_sta_state+0x265/0xb8a [ath10k_core] [21713.799991] [21713.799997] Use-after-free read at 0x00000000abe1c75e (in kfence-#69): [21713.800010] ath10k_sta_state+0x265/0xb8a [ath10k_core] [21713.800041] drv_sta_state+0x115/0x677 [mac80211] [21713.800059] __sta_info_destroy_part2+0xb1/0x133 [mac80211] [21713.800076] __sta_info_flush+0x11d/0x162 [mac80211] [21713.800093] ieee80211_set_disassoc+0x12d/0x2f4 [mac80211] [21713.800110] ieee80211_mgd_deauth+0x26c/0x29b [mac80211] [21713.800137] cfg80211_mlme_deauth+0x13f/0x1bb [cfg80211] [21713.800153] nl80211_deauthenticate+0xf8/0x121 [cfg80211] [21713.800161] genl_rcv_msg+0x38e/0x3be [21713.800166] netlink_rcv_skb+0x89/0xf7 [21713.800171] genl_rcv+0x28/0x36 [21713.800176] netlink_unicast+0x179/0x24b [21713.800181] netlink_sendmsg+0x3a0/0x40e [21713.800187] sock_sendmsg+0x72/0x76 [21713.800192] ____sys_sendmsg+0x16d/0x1e3 [21713.800196] ___sys_sendmsg+0x95/0xd1 [21713.800200] __sys_sendmsg+0x85/0xbf [21713.800205] do_syscall_64+0x43/0x55 [21713.800210] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [21713.800213] [21713.800219] kfence-#69: 0x000000009149b0d5-0x000000004c0697fb, size=1064, cache=kmalloc-2k [21713.800219] [21713.800224] allocated by task 13 on cpu 0 at 21705.501373s: [21713.800241] ath10k_peer_map_event+0x7e/0x154 [ath10k_core] [21713.800254] ath10k_htt_t2h_msg_handler+0x586/0x1039 [ath10k_core] [21713.800265] ath10k_htt_htc_t2h_msg_handler+0x12/0x28 [ath10k_core] [21713.800277] ath10k_htc_rx_completion_handler+0x14c/0x1b5 [ath10k_core] [21713.800283] ath10k_pci_process_rx_cb+0x195/0x1df [ath10k_pci] [21713.800294] ath10k_ce_per_engine_service+0x55/0x74 [ath10k_core] [21713.800305] ath10k_ce_per_engine_service_any+0x76/0x84 [ath10k_core] [21713.800310] ath10k_pci_napi_poll+0x49/0x144 [ath10k_pci] [21713.800316] net_rx_action+0xdc/0x361 [21713.800320] __do_softirq+0x163/0x29a [21713.800325] asm_call_irq_on_stack+0x12/0x20 [21713.800331] do_softirq_own_stack+0x3c/0x48 [21713.800337] __irq_exit_rcu+0x9b/0x9d [21713.800342] common_interrupt+0xc9/0x14d [21713.800346] asm_common_interrupt+0x1e/0x40 [21713.800351] ksoftirqd_should_run+0x5/0x16 [21713.800357] smpboot_thread_fn+0x148/0x211 [21713.800362] kthread+0x150/0x15f [21713.800367] ret_from_fork+0x22/0x30 [21713.800370] [21713.800374] freed by task 708 on cpu 1 at 21713.799953s: [21713.800498] ath10k_sta_state+0x2c6/0xb8a [ath10k_core] [21713.800515] drv_sta_state+0x115/0x677 [mac80211] [21713.800532] __sta_info_destroy_part2+0xb1/0x133 [mac80211] [21713.800548] __sta_info_flush+0x11d/0x162 [mac80211] [21713.800565] ieee80211_set_disassoc+0x12d/0x2f4 [mac80211] [21713.800581] ieee80211_mgd_deauth+0x26c/0x29b [mac80211] [21713.800598] cfg80211_mlme_deauth+0x13f/0x1bb [cfg80211] [21713.800614] nl80211_deauthenticate+0xf8/0x121 [cfg80211] [21713.800619] genl_rcv_msg+0x38e/0x3be [21713.800623] netlink_rcv_skb+0x89/0xf7 [21713.800628] genl_rcv+0x28/0x36 [21713.800632] netlink_unicast+0x179/0x24b [21713.800637] netlink_sendmsg+0x3a0/0x40e [21713.800642] sock_sendmsg+0x72/0x76 [21713.800646] ____sys_sendmsg+0x16d/0x1e3 [21713.800651] ___sys_sendmsg+0x95/0xd1 [21713.800655] __sys_sendmsg+0x85/0xbf [21713.800659] do_syscall_64+0x43/0x55 [21713.800663] entry_SYSCALL_64_after_hwframe+0x44/0xa9
Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00288-QCARMSWPZ-1
--- drivers/net/wireless/ath/ath10k/mac.c | 54 ++++++++++++++------------- 1 file changed, 29 insertions(+), 25 deletions(-)
drivers/net/wireless/ath/ath10k/mac.c +29 -25
@@ -864,11 +864,36 @@ static int ath10k_peer_delete(struct ath10k *ar, u32 vdev_id, const u8 *addr)return 0 ; } +static void ath10k_peer_map_cleanup (struct ath10k *ar,struct ath10k_peer *peer) +{ +int peer_id, i; + +lockdep_assert_held (&ar->conf_mutex); + +for_each_set_bit (peer_id, peer->peer_ids, +ATH10K_MAX_NUM_PEER_IDS ) { + ar->peer_map[peer_id] =NULL ; + } + +/* Double check that peer is properly un-referenced from +* the peer_map +*/ +for (i =0 ; i <ARRAY_SIZE (ar->peer_map); i++) { +if (ar->peer_map[i] == peer) { +ath10k_warn (ar,"removing stale peer_map entry for %pM (ptr %pK idx %d)\n" , + peer->addr, peer, i); + ar->peer_map[i] =NULL ; + } + } + +list_del (&peer->list); +kfree (peer); + ar->num_peers--; +} +static void ath10k_peer_cleanup (struct ath10k *ar,u32 vdev_id) {struct ath10k_peer *peer, *tmp; -int peer_id; -int i;lockdep_assert_held (&ar->conf_mutex);
@@ -880,25 +905,7 @@ static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id)ath10k_warn (ar,"removing stale peer %pM from vdev_id %d\n" , peer->addr, vdev_id); -for_each_set_bit (peer_id, peer->peer_ids, -ATH10K_MAX_NUM_PEER_IDS ) { - ar->peer_map[peer_id] =NULL ; - } - -/* Double check that peer is properly un-referenced from -* the peer_map -*/ -for (i =0 ; i <ARRAY_SIZE (ar->peer_map); i++) { -if (ar->peer_map[i] == peer) { -ath10k_warn (ar,"removing stale peer_map entry for %pM (ptr %pK idx %d)\n" , - peer->addr, peer, i); - ar->peer_map[i] =NULL ; - } - } - -list_del (&peer->list); -kfree (peer); - ar->num_peers--; +ath10k_peer_map_cleanup (ar, peer); }spin_unlock_bh (&ar->data_lock); }
@@ -7586,10 +7593,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,/* Clean up the peer object as well since we * must have failed to do this above. */ -list_del (&peer->list); - ar->peer_map[i] =NULL ; -kfree (peer); - ar->num_peers--; +ath10k_peer_map_cleanup (ar, peer); } }spin_unlock_bh (&ar->data_lock);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 202/717 bpf: Fix non-static bpf_func_proto struct definitions
In reply to Greg Kroah-HartmanFrom: Joanne Koong <[email protected]>
[ Upstream commit dc368e1c658e4f478a45e8d1d5b0c8392ca87506 ]
This patch does two things:
1) Marks the dynptr bpf_func_proto structs that were added in [1] as static, as pointed out by the kernel test robot in [2].
2) There are some bpf_func_proto structs marked as extern which can instead be statically defined.
[1] https://lore.kernel.org/bpf/[email protected]/
[2] https://lore.kernel.org/bpf/62ab89f2.Pko7sI08RAKdF8R6%[email protected]/
Stable-dep-of: 883743422ced ("bpf: Fix ref_obj_id for dynptr data slices in verifier")
--- include/linux/bpf.h | 3 --- kernel/bpf/helpers.c | 12 ++++++------ kernel/bpf/syscall.c | 2 +- 3 files changed, 7 insertions(+), 10 deletions(-)
include/linux/bpf.h +0 -3
@@ -2273,12 +2273,9 @@ extern const struct bpf_func_proto bpf_for_each_map_elem_proto;extern const struct bpf_func_proto bpf_btf_find_by_name_kind_proto;extern const struct bpf_func_proto bpf_sk_setsockopt_proto;extern const struct bpf_func_proto bpf_sk_getsockopt_proto; -extern const struct bpf_func_proto bpf_kallsyms_lookup_name_proto;extern const struct bpf_func_proto bpf_find_vma_proto;extern const struct bpf_func_proto bpf_loop_proto; -extern const struct bpf_func_proto bpf_strncmp_proto;extern const struct bpf_func_proto bpf_copy_from_user_task_proto; -extern const struct bpf_func_proto bpf_kptr_xchg_proto;const struct bpf_func_proto *tracing_prog_func_proto (enum bpf_func_id func_id,const struct bpf_prog *prog);
kernel/bpf/helpers.c +6 -6
@@ -584,7 +584,7 @@ BPF_CALL_3(bpf_strncmp, const char *, s1, u32, s1_sz, const char *, s2)return strncmp (s1, s2, s1_sz); } -const struct bpf_func_proto bpf_strncmp_proto = { +static const struct bpf_func_proto bpf_strncmp_proto = { .func = bpf_strncmp, .gpl_only = false, .ret_type =RET_INTEGER ,
@@ -1402,7 +1402,7 @@ BPF_CALL_2(bpf_kptr_xchg, void *, map_value, void *, ptr)*/ #define BPF_PTR_POISON ((void *)((0xeB9FUL << 2) + POISON_POINTER_DELTA)) -const struct bpf_func_proto bpf_kptr_xchg_proto = { +static const struct bpf_func_proto bpf_kptr_xchg_proto = { .func = bpf_kptr_xchg, .gpl_only = false, .ret_type =RET_PTR_TO_BTF_ID_OR_NULL ,
@@ -1489,7 +1489,7 @@ BPF_CALL_4(bpf_dynptr_from_mem, void *, data, u32, size, u64, flags, struct bpf_return err; } -const struct bpf_func_proto bpf_dynptr_from_mem_proto = { +static const struct bpf_func_proto bpf_dynptr_from_mem_proto = { .func = bpf_dynptr_from_mem, .gpl_only = false, .ret_type =RET_INTEGER ,
@@ -1516,7 +1516,7 @@ BPF_CALL_5(bpf_dynptr_read, void *, dst, u32, len, struct bpf_dynptr_kern *, srcreturn 0 ; } -const struct bpf_func_proto bpf_dynptr_read_proto = { +static const struct bpf_func_proto bpf_dynptr_read_proto = { .func = bpf_dynptr_read, .gpl_only = false, .ret_type =RET_INTEGER ,
@@ -1544,7 +1544,7 @@ BPF_CALL_5(bpf_dynptr_write, struct bpf_dynptr_kern *, dst, u32, offset, void *,return 0 ; } -const struct bpf_func_proto bpf_dynptr_write_proto = { +static const struct bpf_func_proto bpf_dynptr_write_proto = { .func = bpf_dynptr_write, .gpl_only = false, .ret_type =RET_INTEGER ,
@@ -1572,7 +1572,7 @@ BPF_CALL_3(bpf_dynptr_data, struct bpf_dynptr_kern *, ptr, u32, offset, u32, lenreturn (unsigned long )(ptr->data + ptr->offset + offset); } -const struct bpf_func_proto bpf_dynptr_data_proto = { +static const struct bpf_func_proto bpf_dynptr_data_proto = { .func = bpf_dynptr_data, .gpl_only = false, .ret_type =RET_PTR_TO_DYNPTR_MEM_OR_NULL ,
kernel/bpf/syscall.c +1 -1
@@ -5138,7 +5138,7 @@ BPF_CALL_4(bpf_kallsyms_lookup_name, const char *, name, int, name_sz, int, flagreturn *res ?0 : -ENOENT ; } -const struct bpf_func_proto bpf_kallsyms_lookup_name_proto = { +static const struct bpf_func_proto bpf_kallsyms_lookup_name_proto = { .func = bpf_kallsyms_lookup_name, .gpl_only = false, .ret_type =RET_INTEGER ,
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 203/717 bpf: convert cgroup_bpf.progs to hlist
In reply to Greg Kroah-HartmanFrom: Stanislav Fomichev <[email protected]>
[ Upstream commit 00442143a2ab7f1da46fbf4d2a99c85df767d49a ]
This lets us reclaim some space to be used by new cgroup lsm slots.
Before:
struct cgroup_bpf {
struct bpf_prog_array * effective[23]; /* 0 184 */
/* --- cacheline 2 boundary (128 bytes) was 56 bytes ago --- */
struct list_head progs[23]; /* 184 368 */
/* --- cacheline 8 boundary (512 bytes) was 40 bytes ago --- */
u32 flags[23]; /* 552 92 */
/* XXX 4 bytes hole, try to pack */
/* --- cacheline 10 boundary (640 bytes) was 8 bytes ago --- */
struct list_head storages; /* 648 16 */
struct bpf_prog_array * inactive; /* 664 8 */
struct percpu_ref refcnt; /* 672 16 */
struct work_struct release_work; /* 688 32 */
/* size: 720, cachelines: 12, members: 7 */
/* sum members: 716, holes: 1, sum holes: 4 */
/* last cacheline: 16 bytes */
};After:
struct cgroup_bpf {
struct bpf_prog_array * effective[23]; /* 0 184 */
/* --- cacheline 2 boundary (128 bytes) was 56 bytes ago --- */
struct hlist_head progs[23]; /* 184 184 */
/* --- cacheline 5 boundary (320 bytes) was 48 bytes ago --- */
u8 flags[23]; /* 368 23 */
/* XXX 1 byte hole, try to pack */
/* --- cacheline 6 boundary (384 bytes) was 8 bytes ago --- */
struct list_head storages; /* 392 16 */
struct bpf_prog_array * inactive; /* 408 8 */
struct percpu_ref refcnt; /* 416 16 */
struct work_struct release_work; /* 432 72 */
/* size: 504, cachelines: 8, members: 7 */
/* sum members: 503, holes: 1, sum holes: 1 */
/* last cacheline: 56 bytes */
};Stable-dep-of: 883743422ced ("bpf: Fix ref_obj_id for dynptr data slices in verifier")
--- include/linux/bpf-cgroup-defs.h | 4 +- include/linux/bpf-cgroup.h | 2 +- kernel/bpf/cgroup.c | 76 +++++++++++++++++++-------------- 3 files changed, 47 insertions(+), 35 deletions(-)
include/linux/bpf-cgroup-defs.h +2 -2
@@ -47,8 +47,8 @@ struct cgroup_bpf {* have either zero or one element * when BPF_F_ALLOW_MULTI the list can have up to BPF_CGROUP_MAX_PROGS */ -struct list_head progs[MAX_CGROUP_BPF_ATTACH_TYPE ]; -u32 flags[MAX_CGROUP_BPF_ATTACH_TYPE ]; +struct hlist_head progs[MAX_CGROUP_BPF_ATTACH_TYPE ]; +u8 flags[MAX_CGROUP_BPF_ATTACH_TYPE ];/* list of cgroup shared storages */ struct list_head storages;
include/linux/bpf-cgroup.h +1 -1
@@ -95,7 +95,7 @@ struct bpf_cgroup_link { };struct bpf_prog_list { -struct list_head node; +struct hlist_node node;struct bpf_prog *prog;struct bpf_cgroup_link *link;struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE ];
kernel/bpf/cgroup.c +44 -32
240 lines not on this page · raw message
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 204/717 bpf: Cleanup check_refcount_ok
In reply to Greg Kroah-HartmanFrom: Dave Marchevsky <[email protected]>
[ Upstream commit b2d8ef19c6e7ed71ba5092feb0710063a751834f ]
Discussion around a recently-submitted patch provided historical context for check_refcount_ok [0]. Specifically, the function and its helpers - may_be_acquire_function and arg_type_may_be_refcounted - predate the OBJ_RELEASE type flag and the addition of many more helpers with acquire/release semantics.
The purpose of check_refcount_ok is to ensure:
1) Helper doesn't have multiple uses of return reg's ref_obj_id
2) Helper with release semantics only has one arg needing to be released, since that's tracked using meta->ref_obj_id
With current verifier, it's safe to remove check_refcount_ok and its helpers. Since addition of OBJ_RELEASE type flag, case 2) has been handled by the arg_type_is_release check in check_func_arg. To ensure case 1) won't result in verifier silently prioritizing one use of ref_obj_id, this patch adds a helper_multiple_ref_obj_use check which fails loudly if a helper passes > 1 test for use of ref_obj_id.
[0]: lore.kernel.org/bpf/[email protected]
Stable-dep-of: 883743422ced ("bpf: Fix ref_obj_id for dynptr data slices in verifier")
--- kernel/bpf/verifier.c | 74 +++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 45 deletions(-)
kernel/bpf/verifier.c +29 -45
@@ -467,25 +467,11 @@ static bool type_is_rdonly_mem(u32 type)return type &MEM_RDONLY ; } -static bool arg_type_may_be_refcounted (enum bpf_arg_type type) -{ -return type ==ARG_PTR_TO_SOCK_COMMON ; -} -static bool type_may_be_null (u32 type) {return type &PTR_MAYBE_NULL ; } -static bool may_be_acquire_function (enum bpf_func_id func_id) -{ -return func_id == BPF_FUNC_sk_lookup_tcp || - func_id == BPF_FUNC_sk_lookup_udp || - func_id == BPF_FUNC_skc_lookup_tcp || - func_id == BPF_FUNC_map_lookup_elem || - func_id == BPF_FUNC_ringbuf_reserve; -} -static bool is_acquire_function (enum bpf_func_id func_id,const struct bpf_map *map) {
@@ -518,6 +504,26 @@ static bool is_ptr_cast_function(enum bpf_func_id func_id) func_id == BPF_FUNC_skc_to_tcp_request_sock; } +static bool is_dynptr_acquire_function (enum bpf_func_id func_id) +{ +return func_id == BPF_FUNC_dynptr_data; +} + +static bool helper_multiple_ref_obj_use (enum bpf_func_id func_id, +const struct bpf_map *map) +{ +int ref_obj_uses =0 ; + +if (is_ptr_cast_function (func_id)) + ref_obj_uses++; +if (is_acquire_function (func_id, map)) + ref_obj_uses++; +if (is_dynptr_acquire_function (func_id)) + ref_obj_uses++; + +return ref_obj_uses >1 ; +} +static bool is_cmpxchg_insn (const struct bpf_insn *insn) { return BPF_CLASS(insn->code) == BPF_STX &&
@@ -6456,33 +6462,6 @@ static bool check_arg_pair_ok(const struct bpf_func_proto *fn)return true; } -static bool check_refcount_ok (const struct bpf_func_proto *fn,int func_id) -{ -int count =0 ; - -if (arg_type_may_be_refcounted (fn->arg1_type)) - count++; -if (arg_type_may_be_refcounted (fn->arg2_type)) - count++; -if (arg_type_may_be_refcounted (fn->arg3_type)) - count++; -if (arg_type_may_be_refcounted (fn->arg4_type)) - count++; -if (arg_type_may_be_refcounted (fn->arg5_type)) - count++; - -/* A reference acquiring function cannot acquire -* another refcounted ptr. -*/ -if (may_be_acquire_function (func_id) && count) -return false; - -/* We only support one arg being unreferenced at the moment, -* which is sufficient for the helper functions we have right now. -*/ -return count <=1 ; -} -static bool check_btf_id_ok (const struct bpf_func_proto *fn) {int i;
@@ -6506,8 +6485,7 @@ static int check_func_proto(const struct bpf_func_proto *fn, int func_id, {return check_raw_mode_ok (fn) &&check_arg_pair_ok (fn) && -check_btf_id_ok (fn) && -check_refcount_ok (fn, func_id) ?0 : -EINVAL ; +check_btf_id_ok (fn) ?0 : -EINVAL ; }/* Packet data might have moved, any old PTR_TO_PACKET[_META,_END]
@@ -7410,6 +7388,12 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insnif (type_may_be_null (regs[BPF_REG_0 ].type)) regs[BPF_REG_0 ].id = ++env->id_gen; +if (helper_multiple_ref_obj_use (func_id, meta.map_ptr)) { +verbose (env,"verifier internal error: func %s#%d sets ref_obj_id more than once\n" , +func_id_name (func_id), func_id); +return -EFAULT ; + } +if (is_ptr_cast_function (func_id)) {/* For release_reference() */ regs[BPF_REG_0 ].ref_obj_id = meta.ref_obj_id;
@@ -7422,10 +7406,10 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn regs[BPF_REG_0 ].id = id;/* For release_reference() */ regs[BPF_REG_0 ].ref_obj_id = id; - }else if (func_id == BPF_FUNC_dynptr_data) { + }else if (is_dynptr_acquire_function (func_id)) {int dynptr_id =0 , i; -/* Find the id of the dynptr we're acquiring a reference to */ +/* Find the id of the dynptr we're tracking the reference of */ for (i =0 ; i <MAX_BPF_FUNC_REG_ARGS ; i++) {if (arg_type_is_dynptr (fn->arg_type[i])) {if (dynptr_id) {
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 205/717 leds: lm3601x: Dont use mutex after it was destroyed
In reply to Greg Kroah-HartmanFrom: Uwe Kleine-König <[email protected]>
[ Upstream commit 32f7eed0c763a9b89f6b357ec54b48398fc7b99e ]
The mutex might still be in use until the devm cleanup callback devm_led_classdev_flash_release() is called. This only happens some time after lm3601x_remove() completed.
--- drivers/leds/flash/leds-lm3601x.c | 2 -- 1 file changed, 2 deletions(-)
drivers/leds/flash/leds-lm3601x.c +0 -2
@@ -444,8 +444,6 @@ static int lm3601x_remove(struct i2c_client *client) {struct lm3601x_led *led =i2c_get_clientdata (client); -mutex_destroy (&led->lock); -return regmap_update_bits (led->regmap,LM3601X_ENABLE_REG ,LM3601X_ENABLE_MASK ,LM3601X_MODE_STANDBY );
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 206/717 tsnep: Fix TSNEP_INFO_TX_TIME register define
In reply to Greg Kroah-HartmanFrom: Gerhard Engleder <[email protected]>
[ Upstream commit 7d8dd6b5cd1d67dd96c132f91d7ad29c49ed3c59 ]
Fixed register define is not used, but register definition shall be kept in sync.
--- drivers/net/ethernet/engleder/tsnep_hw.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/net/ethernet/engleder/tsnep_hw.h +1 -2
@@ -92,8 +92,7 @@/* tsnep register */ #define TSNEP_INFO 0x0100 -#define TSNEP_INFO_RX_ASSIGN 0x00010000 -#define TSNEP_INFO_TX_TIME 0x00020000 +#define TSNEP_INFO_TX_TIME 0x00010000#define TSNEP_CONTROL 0x0108#define TSNEP_CONTROL_TX_RESET 0x00000001#define TSNEP_CONTROL_TX_ENABLE 0x00000002
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 207/717 bpf: Fix reference state management for synchronous callbacks
In reply to Greg Kroah-HartmanFrom: Kumar Kartikeya Dwivedi <[email protected]>
[ Upstream commit 9d9d00ac29d0ef7ce426964de46fa6b380357d0a ]
Currently, verifier verifies callback functions (sync and async) as if they will be executed once, (i.e. it explores execution state as if the function was being called once). The next insn to explore is set to start of subprog and the exit from nested frame is handled using curframe > 0 and prepare_func_exit. In case of async callback it uses a customized variant of push_stack simulating a kind of branch to set up custom state and execution context for the async callback.
While this approach is simple and works when callback really will be executed only once, it is unsafe for all of our current helpers which are for_each style, i.e. they execute the callback multiple times.
A callback releasing acquired references of the caller may do so multiple times, but currently verifier sees it as one call inside the frame, which then returns to caller. Hence, it thinks it released some reference that the cb e.g. got access through callback_ctx (register filled inside cb from spilled typed register on stack).
Similarly, it may see that an acquire call is unpaired inside the callback, so the caller will copy the reference state of callback and then will have to release the register with new ref_obj_ids. But again, the callback may execute multiple times, but the verifier will only account for acquired references for a single symbolic execution of the callback, which will cause leaks.
Note that for async callback case, things are different. While currently we have bpf_timer_set_callback which only executes it once, even for multiple executions it would be safe, as reference state is NULL and check_reference_leak would force program to release state before BPF_EXIT. The state is also unaffected by analysis for the caller frame. Hence async callback is safe.
Since we want the reference state to be accessible, e.g. for pointers loaded from stack through callback_ctx's PTR_TO_STACK, we still have to copy caller's reference_state to callback's bpf_func_state, but we enforce that whatever references it adds to that reference_state has been released before it hits BPF_EXIT. This requires introducing a new callback_ref member in the reference state to distinguish between caller vs callee references. Hence, check_reference_leak now errors out if it sees we are in callback_fn and we have not released callback_ref refs. Since there can be multiple nested callbacks, like frame 0 -> cb1 -> cb2 etc. we need to also distinguish between whether this particular ref belongs to this callback frame or parent, and only error for our own, so we store state->frameno (which is always non-zero for callbacks).
In short, callbacks can read parent reference_state, but cannot mutate it, to be able to use pointers acquired by the caller. They must only undo their changes (by releasing their own acquired_refs before BPF_EXIT) on top of caller reference_state before returning (at which point the caller and callback state will match anyway, so no need to copy it back to caller).
--- include/linux/bpf_verifier.h | 11 ++++++++++ kernel/bpf/verifier.c | 42 ++++++++++++++++++++++++++++-------- 2 files changed, 44 insertions(+), 9 deletions(-)
include/linux/bpf_verifier.h +11 -0
@@ -212,6 +212,17 @@ struct bpf_reference_state {* is used purely to inform the user of a reference leak. */ int insn_idx; +/* There can be a case like: +* main (frame 0) +* cb (frame 1) +* func (frame 3) +* cb (frame 4) +* Hence for frame 4, if callback_ref just stored boolean, it would be +* impossible to distinguish nested callback refs. Hence store the +* frameno and compare that to callback_ref in check_reference_leak when +* exiting a callback function. +*/ +int callback_ref; };/* state of the program:
kernel/bpf/verifier.c +33 -9
84 lines not on this page · raw message
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 208/717 wifi: cfg80211: get correct AP link chandef
In reply to Greg Kroah-HartmanFrom: Shaul Triebitz <[email protected]>
[ Upstream commit bc1857619cc7612117d2ee1ed05b5bfeb638614b ]
When checking for channel regulatory validity, use the AP link chandef (and not mesh's chandef).
--- net/wireless/reg.c | 4 ++++ 1 file changed, 4 insertions(+)
net/wireless/reg.c +4 -0
@@ -2389,6 +2389,10 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)switch (iftype) {case NL80211_IFTYPE_AP :case NL80211_IFTYPE_P2P_GO : +if (!wdev->links[link].ap.beacon_interval) +continue ; + chandef = wdev->links[link].ap.chandef; +break ;case NL80211_IFTYPE_MESH_POINT :if (!wdev->u.mesh.beacon_interval)continue ;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 209/717 wifi: mac80211: allow bw change during channel switch in mesh
In reply to Greg Kroah-HartmanFrom: Hari Chandrakanthan <[email protected]>
[ Upstream commit 6b75f133fe05c36c52d691ff21545d5757fff721 ]
Quoted 1 line
From 'IEEE Std 802.11-2020 section 11.8.8.4.1':
The mesh channel switch may be triggered by the need to avoid interference to a detected radar signal, or to reassign mesh STA channels to ensure the MBSS connectivity.
A 20/40 MHz MBSS may be changed to a 20 MHz MBSS and a 20 MHz MBSS may be changed to a 20/40 MHz MBSS.
Since the standard allows the change of bandwidth during the channel switch in mesh, remove the bandwidth check present in ieee80211_set_csa_beacon.
--- net/mac80211/cfg.c | 3 --- 1 file changed, 3 deletions(-)
net/mac80211/cfg.c +0 -3
@@ -3545,9 +3545,6 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,case NL80211_IFTYPE_MESH_POINT : {struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; -if (params->chandef.width != sdata->vif.bss_conf.chandef.width) -return -EINVAL ; -/* changes into another band are not supported */ if (sdata->vif.bss_conf.chandef.chan->band != params->chandef.chan->band)
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 210/717 bpftool: Fix a wrong type cast in btf_dumper_int
In reply to Greg Kroah-HartmanFrom: Lam Thai <[email protected]>
[ Upstream commit 7184aef9c0f7a81db8fd18d183ee42481d89bf35 ]
When data points to a boolean value, casting it to int * is problematic and could lead to a wrong value being passed to jsonw_bool. Change the cast to bool * instead.
--- tools/bpf/bpftool/btf_dumper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/bpf/bpftool/btf_dumper.c +1 -1
@@ -426,7 +426,7 @@ static int btf_dumper_int(const struct btf_type *t, __u8 bit_offset, *(char *)data);break ;case BTF_INT_BOOL : -jsonw_bool (jw, *(int *)data); +jsonw_bool (jw, *(bool *)data);break ;default :/* shouldn't happen */
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 211/717 audit: explicitly check audit_context->context enum value
In reply to Greg Kroah-HartmanFrom: Richard Guy Briggs <[email protected]>
[ Upstream commit 3ed66951f952ed8f1a5d03e171722bf2631e8d58 ]
Be explicit in checking the struct audit_context "context" member enum value rather than assuming the order of context enum values.
--- kernel/auditsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/auditsc.c +1 -1
@@ -2094,7 +2094,7 @@ void __audit_syscall_exit(int success, long return_code)/* run through both filters to ensure we set the filterkey properly */ audit_filter_syscall (current, context);audit_filter_inodes (current, context); -if (context->current_state <AUDIT_STATE_RECORD ) +if (context->current_state !=AUDIT_STATE_RECORD ) goto out;audit_log_exit ();
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 212/717 audit: free audit_proctitle only on task exit
In reply to Greg Kroah-HartmanFrom: Richard Guy Briggs <[email protected]>
[ Upstream commit c3f3ea8af44d0c5fba79fe8b198087342d0c7e04 ]
Since audit_proctitle is generated at syscall exit time, its value is used immediately and cached for the next syscall. Since this is the case, then only clear it at task exit time. Otherwise, there is no point in caching the value OR bearing the overhead of regenerating it.
--- kernel/auditsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/auditsc.c +1 -1
@@ -1016,7 +1016,6 @@ static void audit_reset_context(struct audit_context *ctx)WARN_ON (!list_empty (&ctx->killed_trees));audit_free_module (ctx); ctx->fds[0 ] =-1 ; -audit_proctitle_free (ctx); ctx->type =0 ;/* reset last for audit_free_*() */ }
@@ -1102,6 +1101,7 @@ static inline void audit_free_context(struct audit_context *context) {/* resetting is extra work, but it is likely just noise */ audit_reset_context (context); +audit_proctitle_free (context);free_tree_refs (context);kfree (context->filterkey);kfree (context);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 213/717 esp: choose the correct inner protocol for GSO on inter address family tunnels
In reply to Greg Kroah-HartmanFrom: Sabrina Dubroca <[email protected]>
[ Upstream commit 26dbd66eab8080be51759e48280da04015221e22 ]
Commit 23c7f8d7989e ("net: Fix esp GSO on inter address family tunnels.") is incomplete. It passes to skb_eth_gso_segment the protocol for the outer IP version, instead of the inner IP version, so we end up calling inet_gso_segment on an inner IPv6 packet and ipv6_gso_segment on an inner IPv4 packet and the packets are dropped.
This patch completes the fix by selecting the correct protocol based on the inner mode's family.
--- net/ipv4/esp4_offload.c | 5 ++++- net/ipv6/esp6_offload.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-)
net/ipv4/esp4_offload.c +4 -1
@@ -110,7 +110,10 @@ static struct sk_buff *xfrm4_tunnel_gso_segment(struct xfrm_state *x, struct sk_buff *skb, netdev_features_t features) { - return skb_eth_gso_segment(skb, features, htons(ETH_P_IP)); +__be16 type = x->inner_mode.family ==AF_INET6 ?htons (ETH_P_IPV6 ) + :htons (ETH_P_IP ); + +return skb_eth_gso_segment (skb, features, type); } static struct sk_buff *xfrm4_transport_gso_segment(struct xfrm_state *x,
net/ipv6/esp6_offload.c +4 -1
@@ -145,7 +145,10 @@ static struct sk_buff *xfrm6_tunnel_gso_segment(struct xfrm_state *x, struct sk_buff *skb, netdev_features_t features) { - return skb_eth_gso_segment(skb, features, htons(ETH_P_IPV6)); +__be16 type = x->inner_mode.family ==AF_INET ?htons (ETH_P_IP ) + :htons (ETH_P_IPV6 ); + +return skb_eth_gso_segment (skb, features, type); } static struct sk_buff *xfrm6_transport_gso_segment(struct xfrm_state *x,
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 214/717 spi: mt7621: Fix an error message in mt7621_spi_probe()
In reply to Greg Kroah-HartmanFrom: Christophe JAILLET <[email protected]>
[ Upstream commit 2b2bf6b7faa9010fae10dc7de76627a3fdb525b3 ]
'status' is known to be 0 at this point. The expected error code is PTR_ERR(clk).
Switch to dev_err_probe() in order to display the expected error code (in a human readable way).
This also filters -EPROBE_DEFER cases, should it happen.
--- drivers/spi/spi-mt7621.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
drivers/spi/spi-mt7621.c +3 -5
@@ -340,11 +340,9 @@ static int mt7621_spi_probe(struct platform_device *pdev)return PTR_ERR (base); clk =devm_clk_get (&pdev->dev,NULL ); -if (IS_ERR (clk)) { -dev_err (&pdev->dev,"unable to get SYS clock, err=%d\n" , - status); -return PTR_ERR (clk); - } +if (IS_ERR (clk)) +return dev_err_probe (&pdev->dev,PTR_ERR (clk), +"unable to get SYS clock\n" ); status =clk_prepare_enable (clk);if (status)
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 215/717 x86/resctrl: Fix to restore to original value when re-enabling hardware prefetch register
In reply to Greg Kroah-HartmanFrom: Kohei Tarumizu <[email protected]>
[ Upstream commit 499c8bb4693d1c8d8f3d6dd38e5bdde3ff5bd906 ]
The current pseudo_lock.c code overwrites the value of the MSR_MISC_FEATURE_CONTROL to 0 even if the original value is not 0. Therefore, modify it to save and restore the original values.
--- arch/x86/kernel/cpu/resctrl/pseudo_lock.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
arch/x86/kernel/cpu/resctrl/pseudo_lock.c +9 -3
@@ -420,6 +420,7 @@ static int pseudo_lock_fn(void *_rdtgrp)struct pseudo_lock_region *plr = rdtgrp->plr;u32 rmid_p, closid_p;unsigned long i; +u64 saved_msr;#ifdef CONFIG_KASAN /* * The registers used for local register variables are also used
@@ -463,6 +464,7 @@ static int pseudo_lock_fn(void *_rdtgrp)* the buffer and evict pseudo-locked memory read earlier from the * cache. */ + saved_msr =__rdmsr (MSR_MISC_FEATURE_CONTROL );__wrmsr (MSR_MISC_FEATURE_CONTROL , prefetch_disable_bits,0x0 ); closid_p =this_cpu_read (pqr_state.cur_closid); rmid_p =this_cpu_read (pqr_state.cur_rmid);
@@ -514,7 +516,7 @@ static int pseudo_lock_fn(void *_rdtgrp)__wrmsr (IA32_PQR_ASSOC , rmid_p, closid_p);/* Re-enable the hardware prefetcher(s) */ -wrmsr (MSR_MISC_FEATURE_CONTROL ,0x0 ,0x0 ); +wrmsrl (MSR_MISC_FEATURE_CONTROL , saved_msr);local_irq_enable (); plr->thread_done =1 ;
@@ -871,6 +873,7 @@ bool rdtgroup_pseudo_locked_in_hierarchy(struct rdt_domain *d)static int measure_cycles_lat_fn (void *_plr) {struct pseudo_lock_region *plr = _plr; +u32 saved_low, saved_high;unsigned long i;u64 start, end;void *mem_r;
@@ -879,6 +882,7 @@ static int measure_cycles_lat_fn(void *_plr)/* * Disable hardware prefetchers. */ +rdmsr (MSR_MISC_FEATURE_CONTROL , saved_low, saved_high);wrmsr (MSR_MISC_FEATURE_CONTROL , prefetch_disable_bits,0x0 ); mem_r =READ_ONCE (plr->kmem);/*
@@ -895,7 +899,7 @@ static int measure_cycles_lat_fn(void *_plr) end =rdtsc_ordered ();trace_pseudo_lock_mem_latency ((u32)(end - start)); } -wrmsr (MSR_MISC_FEATURE_CONTROL ,0x0 ,0x0 ); +wrmsr (MSR_MISC_FEATURE_CONTROL , saved_low, saved_high);local_irq_enable (); plr->thread_done =1 ;wake_up_interruptible (&plr->lock_thread_wq);
@@ -940,6 +944,7 @@ static int measure_residency_fn(struct perf_event_attr *miss_attr,u64 hits_before =0 , hits_after =0 , miss_before =0 , miss_after =0 ;struct perf_event *miss_event, *hit_event;int hit_pmcnum, miss_pmcnum; +u32 saved_low, saved_high;unsigned int line_size;unsigned int size;unsigned long i;
@@ -973,6 +978,7 @@ static int measure_residency_fn(struct perf_event_attr *miss_attr,/* * Disable hardware prefetchers. */ +rdmsr (MSR_MISC_FEATURE_CONTROL , saved_low, saved_high);wrmsr (MSR_MISC_FEATURE_CONTROL , prefetch_disable_bits,0x0 );/* Initialize rest of local variables */
@@ -1031,7 +1037,7 @@ static int measure_residency_fn(struct perf_event_attr *miss_attr,*/ rmb ();/* Re-enable hardware prefetchers */ -wrmsr (MSR_MISC_FEATURE_CONTROL ,0x0 ,0x0 ); +wrmsr (MSR_MISC_FEATURE_CONTROL , saved_low, saved_high);local_irq_enable (); out_hit:perf_event_release_kernel (hit_event);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 216/717 xsk: Fix backpressure mechanism on Tx
In reply to Greg Kroah-HartmanFrom: Maciej Fijalkowski <[email protected]>
[ Upstream commit c00c4461689e15ac2cc3b9a595a54e4d8afd3d77 ]
Commit d678cbd2f867 ("xsk: Fix handling of invalid descriptors in XSK TX batching API") fixed batch API usage against set of descriptors with invalid ones but introduced a problem when AF_XDP SW rings are smaller than HW ones. Mismatch of reported Tx'ed frames between HW generator and user space app was observed. It turned out that backpressure mechanism became a bottleneck when the amount of produced descriptors to CQ is lower than what we grabbed from XSK Tx ring.
Say that 512 entries had been taken from XSK Tx ring but we had only 490 free entries in CQ. Then callsite (ZC driver) will produce only 490 entries onto HW Tx ring but 512 entries will be released from Tx ring and this is what will be seen by the user space.
In order to fix this case, mix XSK Tx/CQ ring interractions by moving around internal functions and changing call order:
* pull out xskq_prod_nb_free() from xskq_prod_reserve_addr_batch() up to xsk_tx_peek_release_desc_batch();
** move xskq_cons_release_n() into xskq_cons_read_desc_batch()
After doing so, algorithm can be described as follows:
1. lookup Tx entries
2. use value from 1. to reserve space in CQ (*)
3. Read from Tx ring as much descriptors as value from 2 3a. release descriptors from XSK Tx ring (**)
4. Finally produce addresses to CQ
--- net/xdp/xsk.c | 22 +++++++++++----------- net/xdp/xsk_queue.h | 22 ++++++++++------------ 2 files changed, 21 insertions(+), 23 deletions(-)
net/xdp/xsk.c +11 -11
@@ -355,16 +355,15 @@ static u32 xsk_tx_peek_release_fallback(struct xsk_buff_pool *pool, u32 max_entrreturn nb_pkts; } -u32 xsk_tx_peek_release_desc_batch (struct xsk_buff_pool *pool,u32 max_entries) +u32 xsk_tx_peek_release_desc_batch (struct xsk_buff_pool *pool,u32 nb_pkts) {struct xdp_sock *xs; -u32 nb_pkts;rcu_read_lock ();if (!list_is_singular (&pool->xsk_tx_list)) {/* Fallback to the non-batched version */ rcu_read_unlock (); -return xsk_tx_peek_release_fallback (pool, max_entries); +return xsk_tx_peek_release_fallback (pool, nb_pkts); } xs = list_first_or_null_rcu(&pool->xsk_tx_list, struct xdp_sock, tx_list);
@@ -373,12 +372,7 @@ u32 xsk_tx_peek_release_desc_batch(struct xsk_buff_pool *pool, u32 max_entries) goto out; } - max_entries =xskq_cons_nb_entries (xs->tx, max_entries); - nb_pkts =xskq_cons_read_desc_batch (xs->tx, pool, max_entries); -if (!nb_pkts) { - xs->tx->queue_empty_descs++; - goto out; - } + nb_pkts =xskq_cons_nb_entries (xs->tx, nb_pkts);/* This is the backpressure mechanism for the Tx path. Try to * reserve space in the completion queue for all packets, but
@@ -386,12 +380,18 @@ u32 xsk_tx_peek_release_desc_batch(struct xsk_buff_pool *pool, u32 max_entries)* packets. This avoids having to implement any buffering in * the Tx path. */ - nb_pkts =xskq_prod_reserve_addr_batch (pool->cq, pool->tx_descs, nb_pkts); + nb_pkts =xskq_prod_nb_free (pool->cq, nb_pkts);if (!nb_pkts) goto out; -xskq_cons_release_n (xs->tx, max_entries); + nb_pkts =xskq_cons_read_desc_batch (xs->tx, pool, nb_pkts); +if (!nb_pkts) { + xs->tx->queue_empty_descs++; + goto out; + } +__xskq_cons_release (xs->tx); +xskq_prod_write_addr_batch (pool->cq, pool->tx_descs, nb_pkts); xs->sk.sk_write_space (&xs->sk); out:
net/xdp/xsk_queue.h +10 -12
@@ -205,6 +205,11 @@ static inline bool xskq_cons_read_desc(struct xsk_queue *q,return false; } +static inline void xskq_cons_release_n (struct xsk_queue *q,u32 cnt) +{ + q->cached_cons += cnt; +} +static inline u32 xskq_cons_read_desc_batch (struct xsk_queue *q,struct xsk_buff_pool *pool,u32 max) {
@@ -226,6 +231,8 @@ static inline u32 xskq_cons_read_desc_batch(struct xsk_queue *q, struct xsk_buff cached_cons++; } +/* Release valid plus any invalid entries */ +xskq_cons_release_n (q, cached_cons - q->cached_cons);return nb_entries; }
@@ -291,11 +298,6 @@ static inline void xskq_cons_release(struct xsk_queue *q) q->cached_cons++; } -static inline void xskq_cons_release_n (struct xsk_queue *q,u32 cnt) -{ - q->cached_cons += cnt; -} -static inline u32 xskq_cons_present_entries (struct xsk_queue *q) {/* No barriers needed since data is not accessed */
@@ -350,21 +352,17 @@ static inline int xskq_prod_reserve_addr(struct xsk_queue *q, u64 addr)return 0 ; } -static inline u32 xskq_prod_reserve_addr_batch (struct xsk_queue *q,struct xdp_desc *descs, -u32 max) +static inline void xskq_prod_write_addr_batch (struct xsk_queue *q,struct xdp_desc *descs, +u32 nb_entries) {struct xdp_umem_ring *ring = (struct xdp_umem_ring *)q->ring; -u32 nb_entries, i, cached_prod; - - nb_entries =xskq_prod_nb_free (q, max); +u32 i, cached_prod;/* A, matches D */ cached_prod = q->cached_prod;for (i =0 ; i < nb_entries; i++) ring->desc[cached_prod++ & q->ring_mask] = descs[i].addr; q->cached_prod = cached_prod; - -return nb_entries; } static inline int xskq_prod_reserve_desc(struct xsk_queue *q,
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 217/717 selftests/xsk: Add missing close() on netns fd
In reply to Greg Kroah-HartmanFrom: Maciej Fijalkowski <[email protected]>
[ Upstream commit 8a7d61bdc2fac2c460a2f32a062f5c6dbd21a764 ]
Commit 1034b03e54ac ("selftests: xsk: Simplify cleanup of ifobjects") removed close on netns fd, which is not correct, so let us restore it.
--- tools/testing/selftests/bpf/xdpxceiver.c | 4 ++++ 1 file changed, 4 insertions(+)
tools/testing/selftests/bpf/xdpxceiver.c +4 -0
@@ -1589,6 +1589,8 @@ static struct ifobject *ifobject_create(void)if (!ifobj->umem) goto out_umem; + ifobj->ns_fd =-1 ; +return ifobj; out_umem:
@@ -1600,6 +1602,8 @@ static struct ifobject *ifobject_create(void)static void ifobject_delete (struct ifobject *ifobj) { +if (ifobj->ns_fd !=-1 ) +close (ifobj->ns_fd);free (ifobj->umem);free (ifobj->xsk_arr);free (ifobj);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 218/717 bpf: Disable preemption when increasing per-cpu map_locked
In reply to Greg Kroah-HartmanFrom: Hou Tao <[email protected]>
[ Upstream commit 2775da21628738ce073a3a6a806adcbaada0f091 ]
Per-cpu htab->map_locked is used to prohibit the concurrent accesses from both NMI and non-NMI contexts. But since commit 74d862b682f5 ("sched: Make migrate_disable/enable() independent of RT"), migrate_disable() is also preemptible under CONFIG_PREEMPT case, so now map_locked also disallows concurrent updates from normal contexts (e.g. userspace processes) unexpectedly as shown below:
process A process B
htab_map_update_elem()
htab_lock_bucket()
migrate_disable()
/* return 1 */
__this_cpu_inc_return()
/* preempted by B */
htab_map_update_elem()
/* the same bucket as A */
htab_lock_bucket()
migrate_disable()
/* return 2, so lock fails */
__this_cpu_inc_return()
return -EBUSYA fix that seems feasible is using in_nmi() in htab_lock_bucket() and only checking the value of map_locked for nmi context. But it will re-introduce dead-lock on bucket lock if htab_lock_bucket() is re-entered through non-tracing program (e.g. fentry program).
One cannot use preempt_disable() to fix this issue as htab_use_raw_lock being false causes the bucket lock to be a spin lock which can sleep and does not work with preempt_disable().
Therefore, use migrate_disable() when using the spinlock instead of preempt_disable() and defer fixing concurrent updates to when the kernel has its own BPF memory allocator.
--- kernel/bpf/hashtab.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-)
kernel/bpf/hashtab.c +18 -5
@@ -162,17 +162,25 @@ static inline int htab_lock_bucket(const struct bpf_htab *htab, unsigned long *pflags) {unsigned long flags; +bool use_raw_lock; hash = hash &HASHTAB_MAP_LOCK_MASK ; -migrate_disable (); + use_raw_lock =htab_use_raw_lock (htab); +if (use_raw_lock) +preempt_disable (); +else +migrate_disable ();if (unlikely (__this_cpu_inc_return (*(htab->map_locked[hash])) !=1 )) {__this_cpu_dec (*(htab->map_locked[hash])); -migrate_enable (); +if (use_raw_lock) +preempt_enable (); +else +migrate_enable ();return -EBUSY ; } -if (htab_use_raw_lock (htab)) +if (use_raw_lock)raw_spin_lock_irqsave (&b->raw_lock, flags);else spin_lock_irqsave (&b->lock, flags);
@@ -185,13 +193,18 @@ static inline void htab_unlock_bucket(const struct bpf_htab *htab, struct bucket *b, u32 hash, unsigned long flags) { + bool use_raw_lock = htab_use_raw_lock(htab); + hash = hash &HASHTAB_MAP_LOCK_MASK ; -if (htab_use_raw_lock (htab)) +if (use_raw_lock)raw_spin_unlock_irqrestore (&b->raw_lock, flags);else spin_unlock_irqrestore (&b->lock, flags);__this_cpu_dec (*(htab->map_locked[hash])); -migrate_enable (); +if (use_raw_lock) +preempt_enable (); +else +migrate_enable (); }static bool htab_lru_map_delete_node (void *arg,struct bpf_lru_node *node);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 219/717 bpf: Propagate error from htab_lock_bucket() to userspace
In reply to Greg Kroah-HartmanFrom: Hou Tao <[email protected]>
[ Upstream commit 66a7a92e4d0d091e79148a4c6ec15d1da65f4280 ]
In __htab_map_lookup_and_delete_batch() if htab_lock_bucket() returns -EBUSY, it will go to next bucket. Going to next bucket may not only skip the elements in current bucket silently, but also incur out-of-bound memory access or expose kernel memory to userspace if current bucket_cnt is greater than bucket_size or zero.
Fixing it by stopping batch operation and returning -EBUSY when htab_lock_bucket() fails, and the application can retry or skip the busy batch as needed.
--- kernel/bpf/hashtab.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
kernel/bpf/hashtab.c +5 -2
@@ -1704,8 +1704,11 @@ __htab_map_lookup_and_delete_batch(struct bpf_map *map,/* do not grab the lock unless need it (bucket_cnt > 0). */ if (locked) { ret =htab_lock_bucket (htab, b, batch, &flags); -if (ret) - goto next_batch; +if (ret) { +rcu_read_unlock (); +bpf_enable_instrumentation (); + goto after_loop; + } } bucket_cnt =0 ;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 220/717 wifi: ath11k: Fix incorrect QMI message ID mappings
In reply to Greg Kroah-HartmanFrom: Manikanta Pubbisetty <[email protected]>
[ Upstream commit b3ca32308e46b6384fdcb7e64b3fca4f61aff14b ]
QMI message IDs for some of the QMI messages were incorrectly defined in the original implementation. These have to be corrected to enable cold boot support on WCN6750. These corrections are applicable for all chipsets and will not impact them. Refactor the code accordingly.
Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.1.0.1-00887-QCAMSLSWPLZ-1
--- drivers/net/wireless/ath/ath11k/qmi.c | 38 ++++++++++++++++++++++++--- drivers/net/wireless/ath/ath11k/qmi.h | 10 +++++-- 2 files changed, 43 insertions(+), 5 deletions(-)
drivers/net/wireless/ath/ath11k/qmi.c +35 -3
@@ -1696,6 +1696,13 @@ static struct qmi_elem_info qmi_wlanfw_wlan_ini_resp_msg_v01_ei[] = { }, }; +static struct qmi_elem_info qmi_wlfw_fw_init_done_ind_msg_v01_ei[] = { + { + .data_type =QMI_EOTI , + .array_type =NO_ARRAY , + }, +}; +static int ath11k_qmi_host_cap_send (struct ath11k_base *ab) {struct qmi_wlanfw_host_cap_req_msg_v01 req;
@@ -3006,6 +3013,10 @@ static void ath11k_qmi_msg_fw_ready_cb(struct qmi_handle *qmi_hdl,struct ath11k_base *ab = qmi->ab;ath11k_dbg (ab,ATH11K_DBG_QMI ,"qmi firmware ready\n" ); + + ab->qmi.cal_done =1 ; +wake_up (&ab->qmi.cold_boot_waitq); +ath11k_qmi_driver_event_post (qmi,ATH11K_QMI_EVENT_FW_READY ,NULL ); }
@@ -3018,11 +3029,22 @@ static void ath11k_qmi_msg_cold_boot_cal_done_cb(struct qmi_handle *qmi_hdl, struct ath11k_qmi, handle);struct ath11k_base *ab = qmi->ab; - ab->qmi.cal_done =1 ; -wake_up (&ab->qmi.cold_boot_waitq);ath11k_dbg (ab,ATH11K_DBG_QMI ,"qmi cold boot calibration done\n" ); } +static void ath11k_qmi_msg_fw_init_done_cb (struct qmi_handle *qmi_hdl, +struct sockaddr_qrtr *sq, +struct qmi_txn *txn, +const void *decoded) +{ +struct ath11k_qmi *qmi =container_of (qmi_hdl, + struct ath11k_qmi, handle); +struct ath11k_base *ab = qmi->ab; + +ath11k_qmi_driver_event_post (qmi,ATH11K_QMI_EVENT_FW_INIT_DONE ,NULL ); +ath11k_dbg (ab,ATH11K_DBG_QMI ,"qmi firmware init done\n" ); +} +static const struct qmi_msg_handler ath11k_qmi_msg_handlers[] = { { .type =QMI_INDICATION ,
@@ -3053,6 +3075,14 @@ static const struct qmi_msg_handler ath11k_qmi_msg_handlers[] = { sizeof(struct qmi_wlanfw_fw_cold_cal_done_ind_msg_v01), .fn = ath11k_qmi_msg_cold_boot_cal_done_cb, }, + { + .type = QMI_INDICATION, + .msg_id = QMI_WLFW_FW_INIT_DONE_IND_V01, + .ei = qmi_wlfw_fw_init_done_ind_msg_v01_ei, + .decoded_size = + sizeof(struct qmi_wlfw_fw_init_done_ind_msg_v01), + .fn = ath11k_qmi_msg_fw_init_done_cb, + }, }; static int ath11k_qmi_ops_new_server(struct qmi_handle *qmi_hdl,
@@ -3145,7 +3175,7 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work) }break ; -case ATH11K_QMI_EVENT_FW_READY : +case ATH11K_QMI_EVENT_FW_INIT_DONE :clear_bit (ATH11K_FLAG_QMI_FAIL , &ab->dev_flags);if (test_bit (ATH11K_FLAG_REGISTERED , &ab->dev_flags)) {ath11k_hal_dump_srng_stats (ab);
@@ -3168,6 +3198,8 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work)set_bit (ATH11K_FLAG_REGISTERED , &ab->dev_flags); } +break ; +case ATH11K_QMI_EVENT_FW_READY :break ;case ATH11K_QMI_EVENT_COLD_BOOT_CAL_DONE :break ;
drivers/net/wireless/ath/ath11k/qmi.h +8 -2
@@ -31,8 +31,9 @@#define QMI_WLFW_REQUEST_MEM_IND_V01 0x0035#define QMI_WLFW_FW_MEM_READY_IND_V01 0x0037 -#define QMI_WLFW_COLD_BOOT_CAL_DONE_IND_V01 0x0021 -#define QMI_WLFW_FW_READY_IND_V01 0x0038 +#define QMI_WLFW_COLD_BOOT_CAL_DONE_IND_V01 0x003E +#define QMI_WLFW_FW_READY_IND_V01 0x0021 +#define QMI_WLFW_FW_INIT_DONE_IND_V01 0x0038#define QMI_WLANFW_MAX_DATA_SIZE_V01 6144#define ATH11K_FIRMWARE_MODE_OFF 4
@@ -69,6 +70,7 @@ enum ath11k_qmi_event_type {ATH11K_QMI_EVENT_FORCE_FW_ASSERT ,ATH11K_QMI_EVENT_POWER_UP ,ATH11K_QMI_EVENT_POWER_DOWN , +ATH11K_QMI_EVENT_FW_INIT_DONE , ATH11K_QMI_EVENT_MAX, };
@@ -291,6 +293,10 @@ struct qmi_wlanfw_fw_cold_cal_done_ind_msg_v01 {char placeholder; }; +struct qmi_wlfw_fw_init_done_ind_msg_v01 { +char placeholder; +}; +#define QMI_WLANFW_CAP_REQ_MSG_V01_MAX_LEN 0#define QMI_WLANFW_CAP_RESP_MSG_V01_MAX_LEN 235#define QMI_WLANFW_CAP_REQ_V01 0x0024
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 221/717 bpf: Use this_cpu_{inc|dec|inc_return} for bpf_task_storage_busy
In reply to Greg Kroah-HartmanFrom: Hou Tao <[email protected]>
[ Upstream commit 197827a05e13808c60f52632e9887eede63f1c16 ]
Now migrate_disable() does not disable preemption and under some architectures (e.g. arm64) __this_cpu_{inc|dec|inc_return} are neither preemption-safe nor IRQ-safe, so for fully preemptible kernel concurrent lookups or updates on the same task local storage and on the same CPU may make bpf_task_storage_busy be imbalanced, and bpf_task_storage_trylock() on the specific cpu will always fail.
Fixing it by using this_cpu_{inc|dec|inc_return} when manipulating bpf_task_storage_busy.
--- kernel/bpf/bpf_local_storage.c | 4 ++-- kernel/bpf/bpf_task_storage.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-)
kernel/bpf/bpf_local_storage.c +2 -2
@@ -555,11 +555,11 @@ void bpf_local_storage_map_free(struct bpf_local_storage_map *smap, struct bpf_local_storage_elem, map_node))) {if (busy_counter) {migrate_disable (); -__this_cpu_inc (*busy_counter); +this_cpu_inc (*busy_counter); }bpf_selem_unlink (selem, false);if (busy_counter) { -__this_cpu_dec (*busy_counter); +this_cpu_dec (*busy_counter);migrate_enable (); }cond_resched_rcu ();
kernel/bpf/bpf_task_storage.c +4 -4
@@ -26,20 +26,20 @@ static DEFINE_PER_CPU(int, bpf_task_storage_busy);static void bpf_task_storage_lock (void ) {migrate_disable (); -__this_cpu_inc (bpf_task_storage_busy); +this_cpu_inc (bpf_task_storage_busy); }static void bpf_task_storage_unlock (void ) { -__this_cpu_dec (bpf_task_storage_busy); +this_cpu_dec (bpf_task_storage_busy);migrate_enable (); }static bool bpf_task_storage_trylock (void ) {migrate_disable (); -if (unlikely (__this_cpu_inc_return (bpf_task_storage_busy) !=1 )) { -__this_cpu_dec (bpf_task_storage_busy); +if (unlikely (this_cpu_inc_return (bpf_task_storage_busy) !=1 )) { +this_cpu_dec (bpf_task_storage_busy);migrate_enable ();return false; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 222/717 bpf: Use this_cpu_{inc_return|dec} for prog->active
In reply to Greg Kroah-HartmanFrom: Hou Tao <[email protected]>
[ Upstream commit c89e843a11f1075d27684f6b42256213e4592383 ]
Both __this_cpu_inc_return() and __this_cpu_dec() are not preemption safe and now migrate_disable() doesn't disable preemption, so the update of prog-active is not atomic and in theory under fully preemptible kernel recurisve prevention may do not work.
Fixing by using the preemption-safe and IRQ-safe variants.
--- kernel/bpf/trampoline.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
kernel/bpf/trampoline.c +4 -4
@@ -585,7 +585,7 @@ u64 notrace __bpf_prog_enter(struct bpf_prog *prog, struct bpf_tramp_run_ctx *ru run_ctx->saved_run_ctx =bpf_set_run_ctx (&run_ctx->run_ctx); -if (unlikely (__this_cpu_inc_return (*(prog->active)) !=1 )) { +if (unlikely (this_cpu_inc_return (*(prog->active)) !=1 )) {inc_misses_counter (prog);return 0 ; }
@@ -620,7 +620,7 @@ void notrace __bpf_prog_exit(struct bpf_prog *prog, u64 start, struct bpf_tramp_bpf_reset_run_ctx (run_ctx->saved_run_ctx);update_prog_stats (prog, start); -__this_cpu_dec (*(prog->active)); +this_cpu_dec (*(prog->active));migrate_enable ();rcu_read_unlock (); }
@@ -631,7 +631,7 @@ u64 notrace __bpf_prog_enter_sleepable(struct bpf_prog *prog, struct bpf_tramp_rmigrate_disable ();might_fault (); -if (unlikely (__this_cpu_inc_return (*(prog->active)) !=1 )) { +if (unlikely (this_cpu_inc_return (*(prog->active)) !=1 )) {inc_misses_counter (prog);return 0 ; }
@@ -647,7 +647,7 @@ void notrace __bpf_prog_exit_sleepable(struct bpf_prog *prog, u64 start,bpf_reset_run_ctx (run_ctx->saved_run_ctx);update_prog_stats (prog, start); -__this_cpu_dec (*(prog->active)); +this_cpu_dec (*(prog->active));migrate_enable ();rcu_read_unlock_trace (); }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 223/717 Bluetooth: btusb: mediatek: fix WMT failure during runtime suspend
In reply to Greg Kroah-HartmanFrom: Sean Wang <[email protected]>
[ Upstream commit fd3f106677bac70437dc12e76c827294ed495a44 ]
WMT cmd/event doesn't follow up the generic HCI cmd/event handling, it needs constantly polling control pipe until the host received the WMT event, thus, we should require to specifically acquire PM counter on the USB to prevent the interface from entering auto suspended while WMT cmd/event in progress.
--- drivers/bluetooth/btusb.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
drivers/bluetooth/btusb.c +14 -0
@@ -2451,15 +2451,29 @@ static int btusb_mtk_hci_wmt_sync(struct hci_dev *hdev,set_bit (BTUSB_TX_WAIT_VND_EVT , &data->flags); +/* WMT cmd/event doesn't follow up the generic HCI cmd/event handling, +* it needs constantly polling control pipe until the host received the +* WMT event, thus, we should require to specifically acquire PM counter +* on the USB to prevent the interface from entering auto suspended +* while WMT cmd/event in progress. +*/ + err =usb_autopm_get_interface (data->intf); +if (err <0 ) + goto err_free_wc; + err =__hci_cmd_send (hdev,0xfc6f , hlen, wc);if (err <0 ) {clear_bit (BTUSB_TX_WAIT_VND_EVT , &data->flags); +usb_autopm_put_interface (data->intf); goto err_free_wc; }/* Submit control IN URB on demand to process the WMT event */ err =btusb_mtk_submit_wmt_recv_urb (hdev); + +usb_autopm_put_interface (data->intf); +if (err <0 ) goto err_free_wc;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 224/717 wifi: rtw89: pci: fix interrupt stuck after leaving low power mode
In reply to Greg Kroah-HartmanFrom: Ping-Ke Shih <[email protected]>
[ Upstream commit b7e715d3dcd2e9fa3a689ba0dd7ab85f8aaf6e9a ]
We turn off interrupt in ISR, and re-enable interrupt in threadfn or napi_poll according to the mode it stays. If we are turning off interrupt, rtwpci->running flag is unset and interrupt handler stop processing even if it was called, so disallow to re-enable interrupt in this situation. Or, wifi chip doesn't trigger interrupt events anymore because interrupt status (ISR) isn't clear by interrupt handler anymore.
--- drivers/net/wireless/realtek/rtw89/pci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/wireless/realtek/rtw89/pci.c +2 -1
@@ -756,7 +756,8 @@ static irqreturn_t rtw89_pci_interrupt_threadfn(int irq, void *dev) enable_intr:spin_lock_irqsave (&rtwpci->irq_lock, flags); -rtw89_chip_enable_intr (rtwdev, rtwpci); +if (likely (rtwpci->running)) +rtw89_chip_enable_intr (rtwdev, rtwpci);spin_unlock_irqrestore (&rtwpci->irq_lock, flags);return IRQ_HANDLED ; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 225/717 wifi: rtw89: pci: correct TX resource checking in low power mode
In reply to Greg Kroah-HartmanFrom: Ping-Ke Shih <[email protected]>
[ Upstream commit 4a29213cd775cabcbe395229d175903accedbb9d ]
Number of TX resource must be minimum of TX_BD and TX_WD. Only considering TX_BD could drop TX packets pulled from mac80211 if TX_WD is unavailable.
--- drivers/net/wireless/realtek/rtw89/pci.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/wireless/realtek/rtw89/pci.c +2 -0
@@ -922,10 +922,12 @@ u32 __rtw89_pci_check_and_reclaim_tx_resource_noio(struct rtw89_dev *rtwdev, {struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;struct rtw89_pci_tx_ring *tx_ring = &rtwpci->tx_rings[txch]; +struct rtw89_pci_tx_wd_ring *wd_ring = &tx_ring->wd_ring;u32 cnt;spin_lock_bh (&rtwpci->trx_lock); cnt =rtw89_pci_get_avail_txbd_num (tx_ring); + cnt =min (cnt, wd_ring->curr_num);spin_unlock_bh (&rtwpci->trx_lock);return cnt;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 226/717 wifi: rtl8xxxu: tighten bounds checking in rtl8xxxu_read_efuse()
In reply to Greg Kroah-HartmanFrom: Dan Carpenter <[email protected]>
[ Upstream commit 620d5eaeb9059636864bda83ca1c68c20ede34a5 ]
There some bounds checking to ensure that "map_addr" is not out of bounds before the start of the loop. But the checking needs to be done as we iterate through the loop because "map_addr" gets larger as we iterate.
--- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +7 -7
@@ -1878,13 +1878,6 @@ static int rtl8xxxu_read_efuse(struct rtl8xxxu_priv *priv)/* We have 8 bits to indicate validity */ map_addr = offset *8 ; -if (map_addr >=EFUSE_MAP_LEN ) { -dev_warn (dev,"%s: Illegal map_addr (%04x), " -"efuse corrupt!\n" , - __func__, map_addr); - ret = -EINVAL ; - goto exit; - }for (i =0 ; i <EFUSE_MAX_WORD_UNIT ; i++) {/* Check word enable condition in the section */ if (word_mask &BIT (i)) {
@@ -1895,6 +1888,13 @@ static int rtl8xxxu_read_efuse(struct rtl8xxxu_priv *priv) ret =rtl8xxxu_read_efuse8 (priv, efuse_addr++, &val8);if (ret) goto exit; +if (map_addr >=EFUSE_MAP_LEN -1 ) { +dev_warn (dev,"%s: Illegal map_addr (%04x), " +"efuse corrupt!\n" , + __func__, map_addr); + ret = -EINVAL ; + goto exit; + } priv->efuse_wifi.raw[map_addr++] = val8; ret =rtl8xxxu_read_efuse8 (priv, efuse_addr++, &val8);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 227/717 wifi: wfx: prevent underflow in wfx_send_pds()
In reply to Greg Kroah-HartmanFrom: Dan Carpenter <[email protected]>
[ Upstream commit f97c81f5b7f8047810b0d79a8f759a83951210a0 ]
This does a "chunk_len - 4" subtraction later when it calls:
ret = wfx_hif_configuration(wdev, buf + 4, chunk_len - 4);
so check for "chunk_len" is less than 4.
--- drivers/net/wireless/silabs/wfx/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/silabs/wfx/main.c +1 -1
@@ -181,7 +181,7 @@ int wfx_send_pds(struct wfx_dev *wdev, u8 *buf, size_t len)while (len >0 ) { chunk_type =get_unaligned_le16 (buf +0 ); chunk_len =get_unaligned_le16 (buf +2 ); -if (chunk_len > len) { +if (chunk_len <4 || chunk_len > len) {dev_err (wdev->dev,"PDS:%d: corrupted file\n" , chunk_num);return -EINVAL ; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 228/717 wifi: rtw88: add missing destroy_workqueue() on error path in rtw_core_init()
In reply to Greg Kroah-HartmanFrom: Yang Yingliang <[email protected]>
[ Upstream commit b0ea758b30bbdf7c4323c78b7c50c05d2e1224d5 ]
Add the missing destroy_workqueue() before return from rtw_core_init() in error path.
--- drivers/net/wireless/realtek/rtw88/main.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/net/wireless/realtek/rtw88/main.c +6 -2
@@ -2037,7 +2037,7 @@ int rtw_core_init(struct rtw_dev *rtwdev) ret =rtw_load_firmware (rtwdev,RTW_NORMAL_FW );if (ret) {rtw_warn (rtwdev,"no firmware loaded\n" ); -return ret; + goto out; }if (chip->wow_fw_name) {
@@ -2047,11 +2047,15 @@ int rtw_core_init(struct rtw_dev *rtwdev)wait_for_completion (&rtwdev->fw.completion);if (rtwdev->fw.firmware)release_firmware (rtwdev->fw.firmware); -return ret; + goto out; } }return 0 ; + +out: +destroy_workqueue (rtwdev->tx_wq); +return ret; }EXPORT_SYMBOL (rtw_core_init);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 229/717 selftests/xsk: Avoid use-after-free on ctx
In reply to Greg Kroah-HartmanFrom: Ian Rogers <[email protected]>
[ Upstream commit af515a5587b8f45f19e11657746e0c89411b0380 ]
The put lowers the reference count to 0 and frees ctx, reading it afterwards is invalid. Move the put after the uses and determine the last use by the reference count being 1.
--- tools/lib/bpf/xsk.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
tools/lib/bpf/xsk.c +3 -3
@@ -1228,15 +1228,15 @@ void xsk_socket__delete(struct xsk_socket *xsk) ctx = xsk->ctx; umem = ctx->umem; -xsk_put_ctx (ctx, true); - -if (!ctx->refcount) { +if (ctx->refcount ==1 ) {xsk_delete_bpf_maps (xsk);close (ctx->prog_fd);if (ctx->has_bpf_link)close (ctx->link_fd); } +xsk_put_ctx (ctx, true); + err =xsk_get_mmap_offsets (xsk->fd, &off);if (!err) {if (xsk->rx) {
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 230/717 spi: qup: add missing clk_disable_unprepare on error in spi_qup_resume()
In reply to Greg Kroah-HartmanFrom: Xu Qiang <[email protected]>
[ Upstream commit 70034320fdc597b8f58b4a43bb547f17c4c5557a ]
Add the missing clk_disable_unprepare() before return from spi_qup_resume() in the error handling case.
--- drivers/spi/spi-qup.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-)
drivers/spi/spi-qup.c +14 -3
@@ -1245,14 +1245,25 @@ static int spi_qup_resume(struct device *device)return ret; ret =clk_prepare_enable (controller->cclk); -if (ret) +if (ret) { +clk_disable_unprepare (controller->iclk);return ret; + } ret =spi_qup_set_state (controller,QUP_STATE_RESET );if (ret) -return ret; + goto disable_clk; + + ret =spi_master_resume (master); +if (ret) + goto disable_clk; - return spi_master_resume(master); +return 0 ; + +disable_clk: +clk_disable_unprepare (controller->cclk); +clk_disable_unprepare (controller->iclk); + return ret; }#endif /* CONFIG_PM_SLEEP */
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 231/717 spi: qup: add missing clk_disable_unprepare on error in spi_qup_pm_resume_runtime()
In reply to Greg Kroah-HartmanFrom: Xu Qiang <[email protected]>
[ Upstream commit 494a22765ce479c9f8ad181c5d24cffda9f534bb ]
Add the missing clk_disable_unprepare() before return from spi_qup_pm_resume_runtime() in the error handling case.
--- drivers/spi/spi-qup.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/spi/spi-qup.c +3 -1
@@ -1198,8 +1198,10 @@ static int spi_qup_pm_resume_runtime(struct device *device)return ret; ret =clk_prepare_enable (controller->cclk); -if (ret) +if (ret) { +clk_disable_unprepare (controller->iclk);return ret; + }/* Disable clocks auto gaiting */ config =readl_relaxed (controller->base +QUP_CONFIG );
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 232/717 wifi: rtl8xxxu: Fix skb misuse in TX queue selection
In reply to Greg Kroah-HartmanFrom: Bitterblue Smith <[email protected]>
[ Upstream commit edd5747aa12ed61a5ecbfa58d3908623fddbf1e8 ]
rtl8xxxu_queue_select() selects the wrong TX queues because it's reading memory from the wrong address. It expects to find ieee80211_hdr at skb->data, but that's not the case after skb_push(). Move the call to rtl8xxxu_queue_select() before the call to skb_push().
--- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +2 -1
@@ -5062,6 +5062,8 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw,if (control && control->sta) sta = control->sta; + queue =rtl8xxxu_queue_select (hw, skb); + tx_desc =skb_push (skb, tx_desc_size);memset (tx_desc,0 , tx_desc_size);
@@ -5074,7 +5076,6 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw, is_broadcast_ether_addr(ieee80211_get_DA(hdr))) tx_desc->txdw0 |= TXDESC_BROADMULTICAST; - queue =rtl8xxxu_queue_select (hw, skb); tx_desc->txdw1 =cpu_to_le32 (queue <<TXDESC_QUEUE_SHIFT );if (tx_info->control.hw_key) {
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 233/717 spi: meson-spicc: do not rely on busy flag in pow2 clk ops
In reply to Greg Kroah-HartmanFrom: Neil Armstrong <[email protected]>
[ Upstream commit 36acf80fc0c4b5ebe6fa010b524d442ee7f08fd3 ]
Since [1], controller's busy flag isn't set anymore when the __spi_transfer_message_noqueue() is used instead of the __spi_pump_transfer_message() logic for spi_sync transfers.
Since the pow2 clock ops were limited to only be available when a transfer is ongoing (between prepare_transfer_hardware and unprepare_transfer_hardware callbacks), the only way to track this down is to check for the controller cur_msg.
[1] ae7d2346dc89 ("spi: Don't use the message queue if possible in spi_sync")
--- drivers/spi/spi-meson-spicc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/spi/spi-meson-spicc.c +3 -3
@@ -537,7 +537,7 @@ static unsigned long meson_spicc_pow2_recalc_rate(struct clk_hw *hw,struct clk_divider *divider =to_clk_divider (hw);struct meson_spicc_device *spicc =pow2_clk_to_spicc (divider); -if (!spicc->master->cur_msg || !spicc->master->busy) +if (!spicc->master->cur_msg)return 0 ;return clk_divider_ops.recalc_rate (hw, parent_rate);
@@ -549,7 +549,7 @@ static int meson_spicc_pow2_determine_rate(struct clk_hw *hw,struct clk_divider *divider =to_clk_divider (hw);struct meson_spicc_device *spicc =pow2_clk_to_spicc (divider); -if (!spicc->master->cur_msg || !spicc->master->busy) +if (!spicc->master->cur_msg)return -EINVAL ;return clk_divider_ops.determine_rate (hw, req);
@@ -561,7 +561,7 @@ static int meson_spicc_pow2_set_rate(struct clk_hw *hw, unsigned long rate,struct clk_divider *divider =to_clk_divider (hw);struct meson_spicc_device *spicc =pow2_clk_to_spicc (divider); -if (!spicc->master->cur_msg || !spicc->master->busy) +if (!spicc->master->cur_msg)return -EINVAL ;return clk_divider_ops.set_rate (hw, rate, parent_rate);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 234/717 bpf: btf: fix truncated last_member_type_id in btf_struct_resolve
In reply to Greg Kroah-HartmanFrom: Lorenz Bauer <[email protected]>
[ Upstream commit a37a32583e282d8d815e22add29bc1e91e19951a ]
When trying to finish resolving a struct member, btf_struct_resolve saves the member type id in a u16 temporary variable. This truncates the 32 bit type id value if it exceeds UINT16_MAX.
As a result, structs that have members with type ids > UINT16_MAX and which need resolution will fail with a message like this:
[67414] STRUCT ff_device size=120 vlen=12
effect_owners type_id=67434 bits_offset=960 Member exceeds struct_size
Fix this by changing the type of last_member_type_id to u32.
--- kernel/bpf/btf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/bpf/btf.c +1 -1
@@ -3120,7 +3120,7 @@ static int btf_struct_resolve(struct btf_verifier_env *env,if (v->next_member) {const struct btf_type *last_member_type;const struct btf_member *last_member; -u16 last_member_type_id; +u32 last_member_type_id; last_member =btf_type_member (v->t) + v->next_member -1 ; last_member_type_id = last_member->type;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 235/717 wifi: rtl8xxxu: gen2: Fix mistake in path B IQ calibration
In reply to Greg Kroah-HartmanFrom: Bitterblue Smith <[email protected]>
[ Upstream commit e963a19c64ac0d2f8785d36a27391abd91ac77aa ]
Found by comparing with the vendor driver. Currently this affects only the RTL8192EU, which is the only gen2 chip with 2 TX paths supported by this driver. It's unclear what kind of effect the mistake had in practice, since I don't have any RTL8192EU devices to test it.
--- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +2 -2
@@ -2929,12 +2929,12 @@ bool rtl8xxxu_gen2_simularity_compare(struct rtl8xxxu_priv *priv, }if (!(simubitmap &0x30 ) && priv->tx_paths >1 ) { -/* path B RX OK */ +/* path B TX OK */ for (i =4 ; i <6 ; i++) result[3 ][i] = result[c1][i]; } -if (!(simubitmap &0x30 ) && priv->tx_paths >1 ) { +if (!(simubitmap &0xc0 ) && priv->tx_paths >1 ) {/* path B RX OK */ for (i =6 ; i <8 ; i++) result[3 ][i] = result[c1][i];
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 236/717 wifi: rtl8xxxu: Remove copy-paste leftover in gen2_update_rate_mask
In reply to Greg Kroah-HartmanFrom: Bitterblue Smith <[email protected]>
[ Upstream commit d5350756c03cdf18696295c6b11d7acc4dbf825c ]
It looks like a leftover from copying rtl8xxxu_update_rate_mask, which is used with the gen1 chips.
It wasn't causing any problems for my RTL8188FU test device, but it's clearly a mistake, so remove it.
--- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +2 -3
@@ -4353,15 +4353,14 @@ void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv, h2c.b_macid_cfg.ramask2 = (ramask >>16 ) &0xff ; h2c.b_macid_cfg.ramask3 = (ramask >>24 ) &0xff ; - h2c.ramask.arg =0x80 ; h2c.b_macid_cfg.data1 = rateid;if (sgi) h2c.b_macid_cfg.data1 |=BIT (7 ); h2c.b_macid_cfg.data2 = bw; -dev_dbg (&priv->udev->dev,"%s: rate mask %08x, arg %02x, size %zi\n" , - __func__, ramask, h2c.ramask.arg,sizeof (h2c.b_macid_cfg)); +dev_dbg (&priv->udev->dev,"%s: rate mask %08x, rateid %02x, sgi %d, size %zi\n" , + __func__, ramask, rateid, sgi,sizeof (h2c.b_macid_cfg));rtl8xxxu_gen2_h2c_cmd (priv, &h2c,sizeof (h2c.b_macid_cfg)); }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 237/717 wifi: mt76: mt7921e: fix race issue between reset and suspend/resume
In reply to Greg Kroah-HartmanFrom: Sean Wang <[email protected]>
[ Upstream commit ff6c4a6449793e9718ef2e9ad46864b63022648e ]
It is unexpected that the reset work is running simultaneously with the suspend or resume context and it is possible that reset work is still running even after mt7921 is suspended if we don't fix the race issue.
Thus, the suspend procedure should be waiting until the reset is completed at the beginning and ignore the subsequent the reset requests.
In case there is an error that happens during either suspend or resume handler, we will schedule a reset task to recover the error before returning the error code to ensure we can immediately fix the error there.
--- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 5 +++++ drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 13 +++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7921/mac.c +5 -0
@@ -1215,6 +1215,7 @@ void mt7921_mac_reset_work(struct work_struct *work)void mt7921_reset (struct mt76_dev *mdev) { struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); +struct mt76_connac_pm *pm = &dev->pm;if (!dev->hw_init_done)return ;
@@ -1222,8 +1223,12 @@ void mt7921_reset(struct mt76_dev *mdev)if (dev->hw_full_reset)return ; +if (pm->suspended) +return ; +queue_work (dev->mt76.wq, &dev->reset_work); } +EXPORT_SYMBOL_GPL (mt7921_reset);void mt7921_mac_update_mib_stats (struct mt7921_phy *phy) {
drivers/net/wireless/mediatek/mt76/mt7921/pci.c +9 -4
@@ -368,6 +368,7 @@ static int mt7921_pci_suspend(struct pci_dev *pdev, pm_message_t state)int i, err; pm->suspended = true; +flush_work (&dev->reset_work);cancel_delayed_work_sync (&pm->ps_work);cancel_work_sync (&pm->wake_work);
@@ -433,6 +434,9 @@ static int mt7921_pci_suspend(struct pci_dev *pdev, pm_message_t state) restore_suspend: pm->suspended = false; +if (err <0 ) +mt7921_reset (&dev->mt76); +return err; }
@@ -451,7 +455,7 @@ static int mt7921_pci_resume(struct pci_dev *pdev) err =mt7921_mcu_drv_pmctrl (dev);if (err <0 ) -return err; + goto failed;mt7921_wpdma_reinit_cond (dev);
@@ -481,11 +485,12 @@ static int mt7921_pci_resume(struct pci_dev *pdev)mt76_connac_mcu_set_deep_sleep (&dev->mt76, false); err =mt76_connac_mcu_set_hif_suspend (mdev, false); -if (err) -return err; - +failed: pm->suspended = false; +if (err <0 ) +mt7921_reset (&dev->mt76); + return err; }#endif /* CONFIG_PM */
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 238/717 wifi: mt76: mt7921s: fix race issue between reset and suspend/resume
In reply to Greg Kroah-HartmanFrom: Sean Wang <[email protected]>
[ Upstream commit e86f10e6809add9132ecc2c6b3184ed59db7ca71 ]
It is unexpected that the reset work is running simultaneously with the suspend or resume context and it is possible that reset work is still running even after mt7921 is suspended if we don't fix the race issue.
Thus, the suspend procedure should be waiting until the reset is completed at the beginning and ignore the subsequent the reset requests.
In case there is an error that happens during either suspend or resume handler, we will schedule a reset task to recover the error before returning the error code to ensure we can immediately fix the error there.
--- drivers/net/wireless/mediatek/mt76/mt7921/sdio.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7921/sdio.c +9 -4
@@ -206,6 +206,7 @@ static int mt7921s_suspend(struct device *__dev) pm->suspended = true;set_bit (MT76_STATE_SUSPEND , &mdev->phy.state); +flush_work (&dev->reset_work);cancel_delayed_work_sync (&pm->ps_work);cancel_work_sync (&pm->wake_work);
@@ -261,6 +262,9 @@ static int mt7921s_suspend(struct device *__dev)clear_bit (MT76_STATE_SUSPEND , &mdev->phy.state); pm->suspended = false; +if (err <0 ) +mt7921_reset (&dev->mt76); +return err; }
@@ -276,7 +280,7 @@ static int mt7921s_resume(struct device *__dev) err =mt7921_mcu_drv_pmctrl (dev);if (err <0 ) -return err; + goto failed;mt76_worker_enable (&mdev->tx_worker);mt76_worker_enable (&mdev->sdio.txrx_worker);
@@ -288,11 +292,12 @@ static int mt7921s_resume(struct device *__dev)mt76_connac_mcu_set_deep_sleep (mdev, false); err =mt76_connac_mcu_set_hif_suspend (mdev, false); -if (err) -return err; - +failed: pm->suspended = false; +if (err <0 ) +mt7921_reset (&dev->mt76); +return err; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 239/717 wifi: mt76: mt7921u: fix race issue between reset and suspend/resume
In reply to Greg Kroah-HartmanFrom: Sean Wang <[email protected]>
[ Upstream commit 86f15d043ba7f13211d5c3e41961c3381fb12880 ]
It is unexpected that the reset work is running simultaneously with the suspend or resume context and it is possible that reset work is still running even after mt7921 is suspended if we don't fix the race issue.
Thus, the suspend procedure should be waiting until the reset is completed at the beginning and ignore the subsequent the reset requests.
In case there is an error that happens during either suspend or resume handler, we will schedule a reset task to recover the error before returning the error code to ensure we can immediately fix the error there.
--- .../net/wireless/mediatek/mt76/mt7921/usb.c | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7921/usb.c +24 -4
@@ -292,11 +292,15 @@ static void mt7921u_disconnect(struct usb_interface *usb_intf)static int mt7921u_suspend (struct usb_interface *intf,pm_message_t state) {struct mt7921_dev *dev =usb_get_intfdata (intf); +struct mt76_connac_pm *pm = &dev->pm;int err; + pm->suspended = true; +flush_work (&dev->reset_work); + err =mt76_connac_mcu_set_hif_suspend (&dev->mt76, true);if (err) -return err; + goto failed;mt76u_stop_rx (&dev->mt76);mt76u_stop_tx (&dev->mt76);
@@ -304,11 +308,20 @@ static int mt7921u_suspend(struct usb_interface *intf, pm_message_t state)set_bit (MT76_STATE_SUSPEND , &dev->mphy.state);return 0 ; + +failed: + pm->suspended = false; + +if (err <0 ) +mt7921_reset (&dev->mt76); + +return err; }static int mt7921u_resume (struct usb_interface *intf) {struct mt7921_dev *dev =usb_get_intfdata (intf); +struct mt76_connac_pm *pm = &dev->pm;bool reinit = true;int err, i;
@@ -330,16 +343,23 @@ static int mt7921u_resume(struct usb_interface *intf)if (reinit ||mt7921_dma_need_reinit (dev)) { err =mt7921u_dma_init (dev, true);if (err) -return err; + goto failed; }clear_bit (MT76_STATE_SUSPEND , &dev->mphy.state); err =mt76u_resume_rx (&dev->mt76);if (err <0 ) -return err; + goto failed; + + err =mt76_connac_mcu_set_hif_suspend (&dev->mt76, false); +failed: + pm->suspended = false; + +if (err <0 ) +mt7921_reset (&dev->mt76); - return mt76_connac_mcu_set_hif_suspend(&dev->mt76, false); + return err; }#endif /* CONFIG_PM */
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 240/717 wifi: mt76: sdio: fix the deadlock caused by sdio->stat_work
In reply to Greg Kroah-HartmanFrom: Sean Wang <[email protected]>
[ Upstream commit e5d78fd998be94fb459a3d625df7367849b997b8 ]
Because wake_work and sdio->stat_work share the same workqueue mt76->wq, if sdio->stat_work cannot acquire the mutex lock such as that was possibly held up by [mt7615, mt7921]_mutex_acquire. Additionally, if [mt7615, mt7921]_mutex_acquire was called by sdio->stat_work self, the wake would be blocked by itself. Thus, we move the stat_work into ieee80211_workqueue instead to break the deadlock.
--- drivers/net/wireless/mediatek/mt76/sdio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/sdio.c +2 -2
@@ -483,7 +483,7 @@ static void mt76s_status_worker(struct mt76_worker *w)if (dev->drv->tx_status_data && !test_and_set_bit (MT76_READING_STATS , &dev->phy.state) && !test_bit (MT76_STATE_SUSPEND , &dev->phy.state)) -queue_work (dev->wq, &dev->sdio.stat_work); +ieee80211_queue_work (dev->hw, &dev->sdio.stat_work); }while (nframes >0 );if (resched)
@@ -510,7 +510,7 @@ static void mt76s_tx_status_data(struct work_struct *work) }if (count &&test_bit (MT76_STATE_RUNNING , &dev->phy.state)) -queue_work (dev->wq, &sdio->stat_work); +ieee80211_queue_work (dev->hw, &sdio->stat_work);else clear_bit (MT76_READING_STATS , &dev->phy.state); }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 241/717 wifi: mt76: sdio: poll sta stat when device transmits data
In reply to Greg Kroah-HartmanFrom: Sean Wang <[email protected]>
[ Upstream commit a323e5f041dd11af5e3de19ed7ea95a97d588c11 ]
It is not meaningful to poll sta stat when there is no data traffic. So polling sta stat when the device has transmitted data instead to save CPU power.
That implies that it is unallowed the stat_work to work while MCU is being initialized in the really early stage to fix the possible time to time MCU initialization failure.
--- drivers/net/wireless/mediatek/mt76/sdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/sdio.c +1 -1
@@ -480,7 +480,7 @@ static void mt76s_status_worker(struct mt76_worker *w)if (ndata_frames >0 ) resched = true; -if (dev->drv->tx_status_data && +if (dev->drv->tx_status_data && ndata_frames >0 && !test_and_set_bit (MT76_READING_STATS , &dev->phy.state) && !test_bit (MT76_STATE_SUSPEND , &dev->phy.state))ieee80211_queue_work (dev->hw, &dev->sdio.stat_work);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 242/717 wifi: mt76: sdio: fix transmitting packet hangs
In reply to Greg Kroah-HartmanFrom: YN Chen <[email protected]>
[ Upstream commit 250b1827205846ff346a76044955cb79d4963f70 ]
Fix transmitting packets hangs with continuing to pull the pending packet from mac80211 queues when receiving Tx status notification from the device.
--- drivers/net/wireless/mediatek/mt76/sdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/sdio.c +1 -1
@@ -487,7 +487,7 @@ static void mt76s_status_worker(struct mt76_worker *w) }while (nframes >0 );if (resched) -mt76_worker_schedule (&dev->sdio.txrx_worker); +mt76_worker_schedule (&dev->tx_worker); }static void mt76s_tx_status_data (struct work_struct *work)
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 243/717 wifi: mt76: mt7615: add mt7615_mutex_acquire/release in mt7615_sta_set_decap_offload
In reply to Greg Kroah-HartmanFrom: Lorenzo Bianconi <[email protected]>
[ Upstream commit 765c69d477a44c088e5d19e7758dfa4db418e3ba ]
Similar to mt7921 driver, introduce mt7615_mutex_acquire/release in mt7615_sta_set_decap_offload in order to avoid sending mcu commands while the device is in low-power state.
--- drivers/net/wireless/mediatek/mt76/mt7615/main.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/net/wireless/mediatek/mt76/mt7615/main.c +4 -0
@@ -1194,12 +1194,16 @@ static void mt7615_sta_set_decap_offload(struct ieee80211_hw *hw,struct mt7615_dev *dev =mt7615_hw_dev (hw);struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; +mt7615_mutex_acquire (dev); +if (enabled)set_bit (MT_WCID_FLAG_HDR_TRANS , &msta->wcid.flags);else clear_bit (MT_WCID_FLAG_HDR_TRANS , &msta->wcid.flags);mt7615_mcu_set_sta_decap_offload (dev, vif, sta); + +mt7615_mutex_release (dev); }#ifdef CONFIG_PM
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 244/717 wifi: mt76: mt7915: fix possible unaligned access in mt7915_mac_add_twt_setup
In reply to Greg Kroah-HartmanFrom: Lorenzo Bianconi <[email protected]>
[ Upstream commit 3d9aa54355d863e5412a7e08180f50a8f1827b7f ]
Fix possible unaligned pointer in mt7915_mac_add_twt_setup routine.
--- drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +6 -4
@@ -2536,8 +2536,9 @@ void mt7915_mac_add_twt_setup(struct ieee80211_hw *hw, } flowid =ffs (~msta->twt.flowid_mask) -1 ; -le16p_replace_bits (&twt_agrt->req_type, flowid, -IEEE80211_TWT_REQTYPE_FLOWID ); + twt_agrt->req_type &= ~cpu_to_le16 (IEEE80211_TWT_REQTYPE_FLOWID ); + twt_agrt->req_type |=le16_encode_bits (flowid, +IEEE80211_TWT_REQTYPE_FLOWID ); table_id =ffs (~dev->twt.table_mask) -1 ; exp =FIELD_GET (IEEE80211_TWT_REQTYPE_WAKE_INT_EXP , req_type);
@@ -2587,8 +2588,9 @@ void mt7915_mac_add_twt_setup(struct ieee80211_hw *hw, unlock:mutex_unlock (&dev->mt76.mutex); out: -le16p_replace_bits (&twt_agrt->req_type, setup_cmd, -IEEE80211_TWT_REQTYPE_SETUP_CMD ); + twt_agrt->req_type &= ~cpu_to_le16 (IEEE80211_TWT_REQTYPE_SETUP_CMD ); + twt_agrt->req_type |= +le16_encode_bits (setup_cmd,IEEE80211_TWT_REQTYPE_SETUP_CMD ); twt->control = (twt->control &IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT ) | (twt->control &IEEE80211_TWT_CONTROL_RX_DISABLED ); }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 245/717 wifi: mt76: connac: fix possible unaligned access in mt76_connac_mcu_add_nested_tlv
In reply to Greg Kroah-HartmanFrom: Lorenzo Bianconi <[email protected]>
[ Upstream commit 0a4860f627f1f2b2b777f54f993de1638a79da9f ]
Fix possible unaligned pointer in mt76_connac_mcu_add_nested_tlv routine.
--- drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +4 -2
@@ -258,8 +258,10 @@ mt76_connac_mcu_add_nested_tlv(struct sk_buff *skb, int tag, int len, ntlv =le16_to_cpu (ntlv_hdr->tlv_num); ntlv_hdr->tlv_num =cpu_to_le16 (ntlv +1 ); -if (sta_hdr) -le16_add_cpu (&sta_hdr->len, len); +if (sta_hdr) { + len +=le16_to_cpu (sta_hdr->len); + sta_hdr->len =cpu_to_le16 (len); + }return ptlv; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 246/717 wifi: mt76: mt7921: add mt7921_mutex_acquire at mt7921_[start, stop]_ap
In reply to Greg Kroah-HartmanFrom: Sean Wang <[email protected]>
[ Upstream commit 52b44015f031f629f1ce1d73415a2017593c7ade ]
Add mt7921_mutex_acquire at mt7921_[start, stop]_ap to fix the race with the context holding dev->muxtex and the driver might access the device in low power state.
--- .../net/wireless/mediatek/mt76/mt7921/main.c | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7921/main.c +16 -5
@@ -1499,17 +1499,23 @@ mt7921_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)struct mt7921_dev *dev =mt7921_hw_dev (hw);int err; +mt7921_mutex_acquire (dev); + err =mt76_connac_mcu_uni_add_bss (phy->mt76, vif, &mvif->sta.wcid, true);if (err) -return err; + goto out; err =mt7921_mcu_set_bss_pm (dev, vif, true);if (err) -return err; + goto out; + + err =mt7921_mcu_sta_update (dev,NULL , vif, true, +MT76_STA_INFO_STATE_NONE ); +out: +mt7921_mutex_release (dev); -return mt7921_mcu_sta_update (dev,NULL , vif, true, -MT76_STA_INFO_STATE_NONE ); +return err; } static void
@@ -1520,11 +1526,16 @@ mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)struct mt7921_dev *dev =mt7921_hw_dev (hw);int err; +mt7921_mutex_acquire (dev); + err =mt7921_mcu_set_bss_pm (dev, vif, false);if (err) -return ; + goto out;mt76_connac_mcu_uni_add_bss (phy->mt76, vif, &mvif->sta.wcid, false); + +out: +mt7921_mutex_release (dev); }const struct ieee80211_ops mt7921_ops = {
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 247/717 wifi: mt76: mt7921: add mt7921_mutex_acquire at mt7921_sta_set_decap_offload
In reply to Greg Kroah-HartmanFrom: Sean Wang <[email protected]>
[ Upstream commit 59c20b91786d5f140ee7be2f24c242b5f8986046 ]
Add mt7921_mutex_acquire at mt7921_[start, stop]_ap to fix the race with the context holding dev->muxtex and the driver might access the device in low power state.
--- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/net/wireless/mediatek/mt76/mt7921/main.c +4 -0
@@ -1390,6 +1390,8 @@ static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw,struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv;struct mt7921_dev *dev =mt7921_hw_dev (hw); +mt7921_mutex_acquire (dev); +if (enabled)set_bit (MT_WCID_FLAG_HDR_TRANS , &msta->wcid.flags);else
@@ -1397,6 +1399,8 @@ static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw,mt76_connac_mcu_sta_update_hdr_trans (&dev->mt76, vif, &msta->wcid,MCU_UNI_CMD (STA_REC_UPDATE )); + +mt7921_mutex_release (dev); }#if IS_ENABLED (CONFIG_IPV6 )
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 248/717 wifi: mt76: mt7915: fix mcs value in ht mode
In reply to Greg Kroah-HartmanFrom: Howard Hsu <[email protected]>
[ Upstream commit c6d3e16ad4362502e804a6ca01e955612f3b8222 ]
Fix the error that mcs will be reduced to a range of 0 to 7 in ht mode.
--- drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +6 -4
@@ -1460,7 +1460,7 @@ mt7915_mcu_add_rate_ctrl_fixed(struct mt7915_dev *dev,struct sta_phy phy = {};int ret, nrates =0 ; -#define __sta_phy_bitrate_mask_check (_mcs, _gi, _he) \ +#define __sta_phy_bitrate_mask_check (_mcs, _gi, _ht, _he) \ do { \ u8 i, gi = mask->control[band]._gi; \ gi = (_he) ? gi : gi == NL80211_TXRATE_FORCE_SGI; \
@@ -1473,15 +1473,17 @@ mt7915_mcu_add_rate_ctrl_fixed(struct mt7915_dev *dev,continue ; \ nrates +=hweight16 (mask->control[band]._mcs[i]); \ phy.mcs =ffs (mask->control[band]._mcs[i]) -1 ; \ +if (_ht) \ + phy.mcs +=8 * i; \ } \ }while (0 )if (sta->deflink.he_cap.has_he) { -__sta_phy_bitrate_mask_check (he_mcs, he_gi,1 ); +__sta_phy_bitrate_mask_check (he_mcs, he_gi,0 ,1 ); }else if (sta->deflink.vht_cap.vht_supported) { -__sta_phy_bitrate_mask_check (vht_mcs, gi,0 ); +__sta_phy_bitrate_mask_check (vht_mcs, gi,0 ,0 ); }else if (sta->deflink.ht_cap.ht_supported) { -__sta_phy_bitrate_mask_check (ht_mcs, gi,0 ); +__sta_phy_bitrate_mask_check (ht_mcs, gi,1 ,0 ); }else { nrates =hweight32 (mask->control[band].legacy); phy.mcs =ffs (mask->control[band].legacy) -1 ;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 249/717 wifi: mt76: mt7915: do not check state before configuring implicit beamform
In reply to Greg Kroah-HartmanFrom: Howard Hsu <[email protected]>
[ Upstream commit d2b5bb6dfab29fe32bedefaade88dcd182c03a00 ]
Do not need to check running state before configuring implicit Tx beamform. It is okay to configure implicit Tx beamform in run time. Noted that the existing connected stations will be applied for new configuration only if they reconnected to the interface.
--- drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +3 -3
@@ -23,9 +23,9 @@ mt7915_implicit_txbf_set(void *data, u64 val) {struct mt7915_dev *dev = data; -if (test_bit (MT76_STATE_RUNNING , &dev->mphy.state)) -return -EBUSY ; - +/* The existing connected stations shall reconnect to apply +* new implicit txbf configuration. +*/ dev->ibf = !!val;return mt7915_mcu_set_txbf (dev,MT_BF_TYPE_UPDATE );
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 250/717 wifi: mt76: mt7921e: fix rmmod crash in driver reload test
In reply to Greg Kroah-HartmanFrom: Deren Wu <[email protected]>
[ Upstream commit b5a62d612b7baf6e09884e4de94decb6391d6a9d ]
In insmod/rmmod stress test, the following crash dump shows up immediately. The problem is caused by missing mt76_dev in mt7921_pci_remove(). We should make sure the drvdata is ready before probe() finished.
[168.862789] ================================================================== [168.862797] BUG: KASAN: user-memory-access in try_to_grab_pending+0x59/0x480 [168.862805] Write of size 8 at addr 0000000000006df0 by task rmmod/5361 [168.862812] CPU: 7 PID: 5361 Comm: rmmod Tainted: G OE 5.19.0-rc6 #1 [168.862816] Hardware name: Intel(R) Client Systems NUC8i7BEH/NUC8BEB, 05/04/2020 [168.862820] Call Trace: [168.862822] <TASK> [168.862825] dump_stack_lvl+0x49/0x63 [168.862832] print_report.cold+0x493/0x6b7 [168.862845] kasan_report+0xa7/0x120 [168.862857] kasan_check_range+0x163/0x200 [168.862861] __kasan_check_write+0x14/0x20 [168.862866] try_to_grab_pending+0x59/0x480 [168.862870] __cancel_work_timer+0xbb/0x340 [168.862898] cancel_work_sync+0x10/0x20 [168.862902] mt7921_pci_remove+0x61/0x1c0 [mt7921e] [168.862909] pci_device_remove+0xa3/0x1d0 [168.862914] device_remove+0xc4/0x170 [168.862920] device_release_driver_internal+0x163/0x300 [168.862925] driver_detach+0xc7/0x1a0 [168.862930] bus_remove_driver+0xeb/0x2d0 [168.862935] driver_unregister+0x71/0xb0 [168.862939] pci_unregister_driver+0x30/0x230 [168.862944] mt7921_pci_driver_exit+0x10/0x1b [mt7921e] [168.862949] __x64_sys_delete_module+0x2f9/0x4b0 [168.862968] do_syscall_64+0x38/0x90 [168.862973] entry_SYSCALL_64_after_hwframe+0x63/0xcd
Test steps:
1. insmode
2. do not ifup
3. rmmod quickly (within 1 second)
--- drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/wireless/mediatek/mt76/mt7921/pci.c +2 -0
@@ -289,6 +289,8 @@ static int mt7921_pci_probe(struct pci_dev *pdev, goto err_free_pci_vec; } +pci_set_drvdata (pdev, mdev); + dev = container_of(mdev, struct mt7921_dev, mt76); dev->hif_ops = &mt7921_pcie_ops;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 251/717 Bluetooth: RFCOMM: Fix possible deadlock on socket shutdown/release
In reply to Greg Kroah-HartmanFrom: Luiz Augusto von Dentz <[email protected]>
[ Upstream commit 812e92b824c1db16c9519f8624d48a9901a0d38f ]
Due to change to switch to use lock_sock inside rfcomm_sk_state_change the socket shutdown/release procedure can cause a deadlock:
rfcomm_sock_shutdown():
lock_sock();
__rfcomm_sock_close():
rfcomm_dlc_close():
__rfcomm_dlc_close():
rfcomm_dlc_lock();
rfcomm_sk_state_change():
lock_sock();To fix this when the call __rfcomm_sock_close is now done without holding the lock_sock since rfcomm_dlc_lock exists to protect the dlc data there is no need to use lock_sock in that code path.
--- net/bluetooth/rfcomm/sock.c | 3 +++ 1 file changed, 3 insertions(+)
net/bluetooth/rfcomm/sock.c +3 -0
@@ -902,7 +902,10 @@ static int rfcomm_sock_shutdown(struct socket *sock, int how)lock_sock (sk);if (!sk->sk_shutdown) { sk->sk_shutdown =SHUTDOWN_MASK ; + +release_sock (sk);__rfcomm_sock_close (sk); +lock_sock (sk);if (sock_flag (sk,SOCK_LINGER ) && sk->sk_lingertime && !(current->flags &PF_EXITING ))
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 252/717 net: fs_enet: Fix wrong check in do_pd_setup
In reply to Greg Kroah-HartmanFrom: Zheng Yongjun <[email protected]>
[ Upstream commit ec3f06b542a960806a81345042e4eee3f8c5dec4 ]
Should check of_iomap return value 'fep->fec.fecp' instead of 'fep->fcc.fccp'
--- drivers/net/ethernet/freescale/fs_enet/mac-fec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/freescale/fs_enet/mac-fec.c +1 -1
@@ -98,7 +98,7 @@ static int do_pd_setup(struct fs_enet_private *fep)return -EINVAL ; fep->fec.fecp =of_iomap (ofdev->dev.of_node,0 ); -if (!fep->fcc.fccp) +if (!fep->fec.fecp)return -EINVAL ;return 0 ;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 253/717 bpf: Ensure correct locking around vulnerable function find_vpid()
In reply to Greg Kroah-HartmanFrom: Lee Jones <[email protected]>
[ Upstream commit 83c10cc362d91c0d8d25e60779ee52fdbbf3894d ]
The documentation for find_vpid() clearly states:
"Must be called with the tasklist_lock or rcu_read_lock() held."
Presently we do neither for find_vpid() instance in bpf_task_fd_query(). Add proper rcu_read_lock/unlock() to fix the issue.
--- kernel/bpf/syscall.c | 2 ++ 1 file changed, 2 insertions(+)
kernel/bpf/syscall.c +2 -0
@@ -4361,7 +4361,9 @@ static int bpf_task_fd_query(const union bpf_attr *attr,if (attr->task_fd_query.flags !=0 )return -EINVAL ; +rcu_read_lock (); task =get_pid_task (find_vpid (pid),PIDTYPE_PID ); +rcu_read_unlock ();if (!task)return -ENOENT ;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 254/717 wifi: ath11k: Include STA_KEEPALIVE_ARP_RESPONSE TLV header by default
In reply to Greg Kroah-HartmanFrom: Baochen Qiang <[email protected]>
[ Upstream commit b7b6f86149a7e06269d61a7a5206360f5b642f80 ]
In current code STA_KEEPALIVE_ARP_RESPONSE TLV header is included only when ARP method is used, this causes firmware always to crash when wowlan is enabled because firmware needs it to be present no matter ARP method is used or not.
Fix this issue by including STA_KEEPALIVE_ARP_RESPONSE TLV header by default.
Also fix below typo:
s/WMI_TAG_STA_KEEPALVE_ARP_RESPONSE/WMI_TAG_STA_KEEPALIVE_ARP_RESPONSE/
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3
--- drivers/net/wireless/ath/ath11k/wmi.c | 9 +++++---- drivers/net/wireless/ath/ath11k/wmi.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-)
drivers/net/wireless/ath/ath11k/wmi.c +5 -4
@@ -9003,12 +9003,13 @@ int ath11k_wmi_sta_keepalive(struct ath11k *ar, cmd->interval = arg->interval; cmd->method = arg->method; + arp = (struct wmi_sta_keepalive_arp_resp *)(cmd +1 ); + arp->tlv_header =FIELD_PREP (WMI_TLV_TAG , +WMI_TAG_STA_KEEPALIVE_ARP_RESPONSE ) | +FIELD_PREP (WMI_TLV_LEN ,sizeof (*arp) -TLV_HDR_SIZE ); +if (arg->method ==WMI_STA_KEEPALIVE_METHOD_UNSOLICITED_ARP_RESPONSE || arg->method ==WMI_STA_KEEPALIVE_METHOD_GRATUITOUS_ARP_REQUEST ) { - arp = (struct wmi_sta_keepalive_arp_resp *)(cmd +1 ); - arp->tlv_header =FIELD_PREP (WMI_TLV_TAG , -WMI_TAG_STA_KEEPALVE_ARP_RESPONSE ) | -FIELD_PREP (WMI_TLV_LEN ,sizeof (*arp) -TLV_HDR_SIZE ); arp->src_ip4_addr = arg->src_ip4_addr; arp->dest_ip4_addr = arg->dest_ip4_addr;ether_addr_copy (arp->dest_mac_addr.addr, arg->dest_mac_addr);
drivers/net/wireless/ath/ath11k/wmi.h +1 -1
@@ -1214,7 +1214,7 @@ enum wmi_tlv_tag {WMI_TAG_NS_OFFLOAD_TUPLE ,WMI_TAG_FTM_INTG_CMD ,WMI_TAG_STA_KEEPALIVE_CMD , -WMI_TAG_STA_KEEPALVE_ARP_RESPONSE , +WMI_TAG_STA_KEEPALIVE_ARP_RESPONSE ,WMI_TAG_P2P_SET_VENDOR_IE_DATA_CMD ,WMI_TAG_AP_PS_PEER_CMD , WMI_TAG_PEER_RATE_RETRY_SCHED_CMD,
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 255/717 Bluetooth: hci_{ldisc,serdev}: check percpu_init_rwsem() failure
In reply to Greg Kroah-HartmanFrom: Tetsuo Handa <[email protected]>
[ Upstream commit 3124d320c22f3f4388d9ac5c8f37eaad0cefd6b1 ]
syzbot is reporting NULL pointer dereference at hci_uart_tty_close() [1], for rcu_sync_enter() is called without rcu_sync_init() due to hci_uart_tty_open() ignoring percpu_init_rwsem() failure.
While we are at it, fix that hci_uart_register_device() ignores percpu_init_rwsem() failure and hci_uart_unregister_device() does not call percpu_free_rwsem().
--- drivers/bluetooth/hci_ldisc.c | 7 +++++-- drivers/bluetooth/hci_serdev.c | 10 +++++++--- 2 files changed, 12 insertions(+), 5 deletions(-)
drivers/bluetooth/hci_ldisc.c +5 -2
@@ -493,6 +493,11 @@ static int hci_uart_tty_open(struct tty_struct *tty)BT_ERR ("Can't allocate control structure" );return -ENFILE ; } +if (percpu_init_rwsem (&hu->proto_lock)) { +BT_ERR ("Can't allocate semaphore structure" ); +kfree (hu); +return -ENOMEM ; + } tty->disc_data = hu; hu->tty = tty;
@@ -505,8 +510,6 @@ static int hci_uart_tty_open(struct tty_struct *tty)INIT_WORK (&hu->init_ready, hci_uart_init_work);INIT_WORK (&hu->write_work, hci_uart_write_work); -percpu_init_rwsem (&hu->proto_lock); -/* Flush any pending characters in the driver */ tty_driver_flush_buffer (tty);
drivers/bluetooth/hci_serdev.c +7 -3
@@ -310,11 +310,12 @@ int hci_uart_register_device(struct hci_uart *hu,serdev_device_set_client_ops (hu->serdev, &hci_serdev_client_ops); +if (percpu_init_rwsem (&hu->proto_lock)) +return -ENOMEM ; + err =serdev_device_open (hu->serdev);if (err) -return err; - -percpu_init_rwsem (&hu->proto_lock); + goto err_rwsem; err = p->open (hu);if (err)
@@ -389,6 +390,8 @@ int hci_uart_register_device(struct hci_uart *hu, p->close (hu); err_open:serdev_device_close (hu->serdev); +err_rwsem: +percpu_free_rwsem (&hu->proto_lock);return err; }EXPORT_SYMBOL_GPL (hci_uart_register_device);
@@ -410,5 +413,6 @@ void hci_uart_unregister_device(struct hci_uart *hu)clear_bit (HCI_UART_PROTO_READY , &hu->flags);serdev_device_close (hu->serdev); } +percpu_free_rwsem (&hu->proto_lock); }EXPORT_SYMBOL_GPL (hci_uart_unregister_device);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 256/717 netfilter: conntrack: fix the gc rescheduling delay
In reply to Greg Kroah-HartmanFrom: Antoine Tenart <[email protected]>
[ Upstream commit 95eabdd207024312876d0ebed90b4c977e050e85 ]
Commit 2cfadb761d3d ("netfilter: conntrack: revisit gc autotuning") changed the eviction rescheduling to the use average expiry of scanned entries (within 1-60s) by doing:
for (...) {
expires = clamp(nf_ct_expires(tmp), ...);
next_run += expires;
next_run /= 2;
}The issue is the above will make the average ('next_run' here) more dependent on the last expiration values than the firsts (for sets > 2). Depending on the expiration values used to compute the average, the result can be quite different than what's expected. To fix this we can do the following:
for (...) {
expires = clamp(nf_ct_expires(tmp), ...);
next_run += (expires - next_run) / ++count;
}--- net/netfilter/nf_conntrack_core.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
net/netfilter/nf_conntrack_core.c +8 -2
@@ -67,6 +67,7 @@ struct conntrack_gc_work {struct delayed_work dwork;u32 next_bucket;u32 avg_timeout; +u32 count;u32 start_time;bool exiting;bool early_drop;
@@ -1468,6 +1469,7 @@ static void gc_worker(struct work_struct *work)unsigned int expired_count =0 ;unsigned long next_run;s32 delta_time; +long count; gc_work = container_of(work, struct conntrack_gc_work, dwork.work);
@@ -1477,10 +1479,12 @@ static void gc_worker(struct work_struct *work)if (i ==0 ) { gc_work->avg_timeout =GC_SCAN_INTERVAL_INIT ; + gc_work->count =1 ; gc_work->start_time = start_time; } next_run = gc_work->avg_timeout; + count = gc_work->count; end_time = start_time +GC_SCAN_MAX_DURATION ;
@@ -1500,8 +1504,8 @@ static void gc_worker(struct work_struct *work)hlist_nulls_for_each_entry_rcu (h, n, &ct_hash[i], hnnode) {struct nf_conntrack_net *cnet; -unsigned long expires;struct net *net; +long expires; tmp =nf_ct_tuplehash_to_ctrack (h);
@@ -1515,6 +1519,7 @@ static void gc_worker(struct work_struct *work) gc_work->next_bucket = i; gc_work->avg_timeout = next_run; + gc_work->count = count; delta_time = nfct_time_stamp - gc_work->start_time;
@@ -1530,8 +1535,8 @@ static void gc_worker(struct work_struct *work) } expires =clamp (nf_ct_expires (tmp),GC_SCAN_INTERVAL_MIN ,GC_SCAN_INTERVAL_CLAMP ); + expires = (expires - (long )next_run) / ++count; next_run += expires; - next_run /=2u ;if (nf_conntrack_max95 ==0 ||gc_worker_skip_ct (tmp))continue ;
@@ -1572,6 +1577,7 @@ static void gc_worker(struct work_struct *work) delta_time = nfct_time_stamp - end_time;if (delta_time >0 && i < hashsz) { gc_work->avg_timeout = next_run; + gc_work->count = count; gc_work->next_bucket = i; next_run =0 ; goto early_exit;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 257/717 netfilter: conntrack: revisit the gc initial rescheduling bias
In reply to Greg Kroah-HartmanFrom: Antoine Tenart <[email protected]>
[ Upstream commit 2aa192757005f130b2dd3547dda6e462e761199f ]
The previous commit changed the way the rescheduling delay is computed which has a side effect: the bias is now represented as much as the other entries in the rescheduling delay which makes the logic to kick in only with very large sets, as the initial interval is very large (INT_MAX).
Revisit the GC initial bias to allow more frequent GC for smaller sets while still avoiding wakeups when a machine is mostly idle. We're moving from a large initial value to pretending we have 100 entries expiring at the upper bound. This way only a few entries having a small timeout won't impact much the rescheduling delay and non-idle machines will have enough entries to lower the delay when needed. This also improves readability as the initial bias is now linked to what is computed instead of being an arbitrary large value.
--- net/netfilter/nf_conntrack_core.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
net/netfilter/nf_conntrack_core.c +6 -4
@@ -86,10 +86,12 @@ static DEFINE_MUTEX(nf_conntrack_mutex);/* clamp timeouts to this value (TCP unacked) */ #define GC_SCAN_INTERVAL_CLAMP (300ul * HZ) -/* large initial bias so that we don't scan often just because we have -* three entries with a 1s timeout. +/* Initial bias pretending we have 100 entries at the upper bound so we don't +* wakeup often just because we have three entries with a 1s timeout while still +* allowing non-idle machines to wakeup more often when needed. */ -#define GC_SCAN_INTERVAL_INIT INT_MAX +#define GC_SCAN_INITIAL_COUNT 100 +#define GC_SCAN_INTERVAL_INIT GC_SCAN_INTERVAL_MAX#define GC_SCAN_MAX_DURATION msecs_to_jiffies(10)#define GC_SCAN_EXPIRED_MAX (64000u / HZ)
@@ -1479,7 +1481,7 @@ static void gc_worker(struct work_struct *work)if (i ==0 ) { gc_work->avg_timeout =GC_SCAN_INTERVAL_INIT ; - gc_work->count =1 ; + gc_work->count =GC_SCAN_INITIAL_COUNT ; gc_work->start_time = start_time; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 258/717 flow_dissector: Do not count vlan tags inside tunnel payload
In reply to Greg Kroah-HartmanFrom: Qingqing Yang <[email protected]>
[ Upstream commit 9f87eb4246994e32a4e4ea88476b20ab3b412840 ]
We've met the problem that when there is a vlan tag inside GRE encapsulation, the match of num_of_vlans fails. It is caused by the vlan tag inside GRE payload has been counted into num_of_vlans, which is not expected.
One example packet is like this:
Ethernet II, Src: Broadcom_68:56:07 (00:10:18:68:56:07)
Dst: Broadcom_68:56:08 (00:10:18:68:56:08)
802.1Q Virtual LAN, PRI: 0, DEI: 0, ID: 100
Internet Protocol Version 4, Src: 192.168.1.4, Dst: 192.168.1.200 Generic Routing Encapsulation (Transparent Ethernet bridging) Ethernet II, Src: Broadcom_68:58:07 (00:10:18:68:58:07)
Dst: Broadcom_68:58:08 (00:10:18:68:58:08)
802.1Q Virtual LAN, PRI: 0, DEI: 0, ID: 200
...
It should match the (num_of_vlans 1) rule, but it matches the (num_of_vlans 2) rule.
The vlan tags inside the GRE or other tunnel encapsulated payload should not be taken into num_of_vlans.
The fix is to stop counting the vlan number when the encapsulation bit is set.
--- net/core/flow_dissector.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/core/flow_dissector.c +2 -2
@@ -1168,8 +1168,8 @@ bool __skb_flow_dissect(const struct net *net, nhoff +=sizeof (*vlan); } -if (dissector_uses_key (flow_dissector, -FLOW_DISSECTOR_KEY_NUM_OF_VLANS )) { +if (dissector_uses_key (flow_dissector,FLOW_DISSECTOR_KEY_NUM_OF_VLANS ) && + !(key_control->flags &FLOW_DIS_ENCAPSULATION )) {struct flow_dissector_key_num_of_vlans *key_nvs; key_nvs = skb_flow_dissector_target(flow_dissector,
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 259/717 wifi: ath11k: fix failed to find the peer with peer_id 0 when disconnected
In reply to Greg Kroah-HartmanFrom: Wen Gong <[email protected]>
[ Upstream commit a20ed60bb357776301c2dad7b4a4f0db97e143e9 ]
It has a fail log which is ath11k_dbg in ath11k_dp_rx_process_mon_status(), as below, it will not print when debug_mask is not set ATH11K_DBG_DATA.
ath11k_dbg(ab, ATH11K_DBG_DATA, "failed to find the peer with peer_id %d\n", ppdu_info.peer_id);
When run scan with station disconnected, the peer_id is 0 for case HAL_RX_MPDU_START in ath11k_hal_rx_parse_mon_status_tlv() which called from ath11k_dp_rx_process_mon_status(), and the peer_id of ppdu_info is reset to 0 in the while loop, so it does not match condition of the check "if (ppdu_info->peer_id == HAL_INVALID_PEERID" in the loop, and then the log "failed to find the peer with peer_id 0" print after the check in the loop, it is below call stack when debug_mask is set ATH11K_DBG_DATA.
The reason is this commit 01d2f285e3e5 ("ath11k: decode HE status tlv") add "memset(ppdu_info, 0, sizeof(struct hal_rx_mon_ppdu_info))" in ath11k_dp_rx_process_mon_status(), but the commit does not initialize the peer_id to HAL_INVALID_PEERID, then lead the check mis-match.
Callstack of the failed log:
[12335.689072] RIP: 0010:ath11k_dp_rx_process_mon_status+0x9ea/0x1020 [ath11k] [12335.689157] Code: 89 ff e8 f9 10 00 00 be 01 00 00 00 4c 89 f7 e8 dc 4b 4e de 48 8b 85 38 ff ff ff c7 80 e4 07 00 00 01 00 00 00 e9 20 f8 ff ff <0f> 0b 41 0f b7 96 be 06 00 00 48 c7 c6 b8 50 44 c1 4c 89 ff e8 fd [12335.689180] RSP: 0018:ffffb874001a4ca0 EFLAGS: 00010246 [12335.689210] RAX: 0000000000000000 RBX: ffff995642cbd100 RCX: 0000000000000000 [12335.689229] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff99564212cd18 [12335.689248] RBP: ffffb874001a4dc0 R08: 0000000000000001 R09: 0000000000000000 [12335.689268] R10: 0000000000000220 R11: ffffb874001a48e8 R12: ffff995642473d40 [12335.689286] R13: ffff99564212c5b8 R14: ffff9956424736a0 R15: ffff995642120000 [12335.689303] FS: 0000000000000000(0000) GS:ffff995739000000(0000) knlGS:0000000000000000 [12335.689323] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [12335.689341] CR2: 00007f43c5d5e039 CR3: 000000011c012005 CR4: 00000000000606e0 [12335.689360] Call Trace: [12335.689377] <IRQ> [12335.689418] ? rcu_read_lock_held_common+0x12/0x50 [12335.689447] ? rcu_read_lock_sched_held+0x25/0x80 [12335.689471] ? rcu_read_lock_held_common+0x12/0x50 [12335.689504] ath11k_dp_rx_process_mon_rings+0x8d/0x4f0 [ath11k] [12335.689578] ? ath11k_dp_rx_process_mon_rings+0x8d/0x4f0 [ath11k] [12335.689653] ? lock_acquire+0xef/0x360 [12335.689681] ? rcu_read_lock_sched_held+0x25/0x80 [12335.689713] ath11k_dp_service_mon_ring+0x38/0x60 [ath11k] [12335.689784] ? ath11k_dp_rx_process_mon_rings+0x4f0/0x4f0 [ath11k] [12335.689860] call_timer_fn+0xb2/0x2f0 [12335.689897] ? ath11k_dp_rx_process_mon_rings+0x4f0/0x4f0 [ath11k] [12335.689970] run_timer_softirq+0x21f/0x540 [12335.689999] ? ktime_get+0xad/0x160 [12335.690025] ? lapic_next_deadline+0x2c/0x40 [12335.690053] ? clockevents_program_event+0x82/0x100 [12335.690093] __do_softirq+0x151/0x4a8 [12335.690135] irq_exit_rcu+0xc9/0x100 [12335.690165] sysvec_apic_timer_interrupt+0xa8/0xd0 [12335.690189] </IRQ> [12335.690204] <TASK> [12335.690225] asm_sysvec_apic_timer_interrupt+0x12/0x20
Reset the default value to HAL_INVALID_PEERID each time after memset of ppdu_info as well as others memset which existed in function ath11k_dp_rx_process_mon_status(), then the failed log disappeared.
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3
--- drivers/net/wireless/ath/ath11k/dp_rx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/wireless/ath/ath11k/dp_rx.c +2 -1
@@ -5194,7 +5194,8 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,if (log_type !=ATH11K_PKTLOG_TYPE_INVALID )trace_ath11k_htt_rxdesc (ar, skb->data, log_type, rx_buf_sz); -memset (ppdu_info,0 ,sizeof (struct hal_rx_mon_ppdu_info )); +memset (ppdu_info,0 ,sizeof (*ppdu_info)); + ppdu_info->peer_id =HAL_INVALID_PEERID ; hal_status =ath11k_hal_rx_parse_mon_status (ab, ppdu_info, skb); if (test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags) &&
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 260/717 wifi: ath11k: fix number of VHT beamformee spatial streams
In reply to Greg Kroah-HartmanFrom: Jesus Fernandez Manzano <[email protected]>
[ Upstream commit 55b5ee3357d7bb98ee578cf9b84a652e7a1bc199 ]
The number of spatial streams used when acting as a beamformee in VHT mode are reported by the firmware as 7 (8 sts - 1) both in IPQ6018 and IPQ8074 which respectively have 2 and 4 sts each. So the firmware should report 1 (2 - 1) and 3 (4 - 1).
Fix this by checking that the number of VHT beamformee sts reported by the firmware is not greater than the number of receiving antennas - 1. The fix is based on the same approach used in this same function for sanitizing the number of sounding dimensions reported by the firmware.
Without this change, acting as a beamformee in VHT mode is not working properly.
Tested-on: IPQ6018 hw1.0 AHB WLAN.HK.2.5.0.1-01208-QCAHKSWPL_SILICONZ-1
Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.5.0.1-01208-QCAHKSWPL_SILICONZ-1
--- drivers/net/wireless/ath/ath11k/mac.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-)
drivers/net/wireless/ath/ath11k/mac.c +20 -5
@@ -4949,6 +4949,8 @@ static int ath11k_mac_set_txbf_conf(struct ath11k_vif *arvif)if (vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE )) { nsts = vht_cap &IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK ; nsts >>=IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT ; +if (nsts > (ar->num_rx_chains -1 )) + nsts = ar->num_rx_chains -1 ; value |=SM (nsts,WMI_TXBF_STS_CAP_OFFSET ); }
@@ -4989,7 +4991,7 @@ static int ath11k_mac_set_txbf_conf(struct ath11k_vif *arvif)static void ath11k_set_vht_txbf_cap (struct ath11k *ar,u32 *vht_cap) {bool subfer, subfee; -int sound_dim =0 ; +int sound_dim =0 , nsts =0 ; subfer = !!(*vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE )); subfee = !!(*vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE ));
@@ -4999,6 +5001,11 @@ static void ath11k_set_vht_txbf_cap(struct ath11k *ar, u32 *vht_cap) subfer = false; } +if (ar->num_rx_chains <2 ) { + *vht_cap &= ~(IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE ); + subfee = false; + } +/* If SU Beaformer is not set, then disable MU Beamformer Capability */ if (!subfer) *vht_cap &= ~(IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE );
@@ -5011,7 +5018,9 @@ static void ath11k_set_vht_txbf_cap(struct ath11k *ar, u32 *vht_cap) sound_dim >>=IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT ; *vht_cap &= ~IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK ; -/* TODO: Need to check invalid STS and Sound_dim values set by FW? */ + nsts = (*vht_cap &IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK ); + nsts >>=IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT ; + *vht_cap &= ~IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK ;/* Enable Sounding Dimension Field only if SU BF is enabled */ if (subfer) {
@@ -5023,9 +5032,15 @@ static void ath11k_set_vht_txbf_cap(struct ath11k *ar, u32 *vht_cap) *vht_cap |= sound_dim; } -/* Use the STS advertised by FW unless SU Beamformee is not supported*/ -if (!subfee) - *vht_cap &= ~(IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK ); +/* Enable Beamformee STS Field only if SU BF is enabled */ +if (subfee) { +if (nsts > (ar->num_rx_chains -1 )) + nsts = ar->num_rx_chains -1 ; + + nsts <<=IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT ; + nsts &=IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK ; + *vht_cap |= nsts; + } } static struct ieee80211_sta_vht_cap
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 261/717 mips: dts: ralink: mt7621: fix external phy on GB-PC2
In reply to Greg Kroah-HartmanFrom: Arınç ÜNAL <[email protected]>
[ Upstream commit 247825f991b34440f9b9d4fe607502435a42ac7b ]
The address of the external phy on the mdio bus is 5. Update the devicetree for GB-PC2 accordingly.
--- arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc2.dts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc2.dts +3 -3
@@ -83,12 +83,12 @@ &gmac1 { status = "okay"; - phy-handle = <ðphy7>; + phy-handle = <ðphy5>; }; &mdio { - ethphy7: ethernet-phy@7 { - reg = <7>; + ethphy5: ethernet-phy@5 { + reg = <5>; phy-mode = "rgmii-rxid"; }; };
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 262/717 x86/microcode/AMD: Track patch allocation size explicitly
In reply to Greg Kroah-HartmanFrom: Kees Cook <[email protected]>
[ Upstream commit 712f210a457d9c32414df246a72781550bc23ef6 ]
In preparation for reducing the use of ksize(), record the actual allocation size for later memcpy(). This avoids copying extra (uninitialized!) bytes into the patch buffer when the requested allocation size isn't exactly the size of a kmalloc bucket. Additionally, fix potential future issues where runtime bounds checking will notice that the buffer was allocated to a smaller value than returned by ksize().
--- arch/x86/include/asm/microcode.h | 1 + arch/x86/kernel/cpu/microcode/amd.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-)
arch/x86/include/asm/microcode.h +1 -0
@@ -9,6 +9,7 @@struct ucode_patch {struct list_head plist;void *data;/* Intel uses only this one */ +unsigned int size;u32 patch_id;u16 equiv_cpu; };
arch/x86/kernel/cpu/microcode/amd.c +2 -1
@@ -788,6 +788,7 @@ static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover,kfree (patch);return -EINVAL ; } + patch->size = *patch_size; mc_hdr = (struct microcode_header_amd *)(fw +SECTION_HDR_SIZE ); proc_id = mc_hdr->processor_rev_id;
@@ -869,7 +870,7 @@ load_microcode_amd(bool save, u8 family, const u8 *data, size_t size)return ret;memset (amd_ucode_patch,0 ,PATCH_MAX_SIZE ); -memcpy (amd_ucode_patch, p->data,min_t (u32,ksize (p->data),PATCH_MAX_SIZE )); +memcpy (amd_ucode_patch, p->data,min_t (u32, p->size,PATCH_MAX_SIZE ));return ret; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 263/717 wifi: ath11k: fix peer addition/deletion error on sta band migration
In reply to Greg Kroah-HartmanFrom: Christian 'Ansuel' Marangi <[email protected]>
[ Upstream commit d673cb6fe6c03b2be157cc6c5db40481828d282d ]
This patch try to fix the following error.
Wed Jun 1 22:19:30 2022 kern.warn kernel: [ 119.561227] ath11k c000000.wifi: peer already added vdev id 0 req, vdev id 1 present Wed Jun 1 22:19:30 2022 kern.warn kernel: [ 119.561282] ath11k c000000.wifi: Failed to add peer: 28:c2:1f:xx:xx:xx for VDEV: 0 Wed Jun 1 22:19:30 2022 kern.warn kernel: [ 119.568053] ath11k c000000.wifi: Failed to add station: 28:c2:1f:xx:xx:xx for VDEV: 0 Wed Jun 1 22:19:31 2022 daemon.notice hostapd: wlan2: STA 28:c2:1f:xx:xx:xx IEEE 802.11: Could not add STA to kernel driver Wed Jun 1 22:19:31 2022 daemon.notice hostapd: wlan2: STA 28:c2:1f:xx:xx:xx IEEE 802.11: did not acknowledge authentication response Wed Jun 1 22:19:31 2022 daemon.notice hostapd: wlan1: AP-STA-DISCONNECTED 28:c2:1f:xx:xx:xx Wed Jun 1 22:19:31 2022 daemon.info hostapd: wlan1: STA 28:c2:1f:xx:xx:xx IEEE 802.11: disassociated due to inactivity Wed Jun 1 22:19:32 2022 daemon.info hostapd: wlan1: STA 28:c2:1f:xx:xx:xx IEEE 802.11: deauthenticated due to inactivity (timer DEAUTH/REMOVE)
To repro this:
- Have 2 Wifi with the same bssid and pass on different band (2.4 and 5GHz)
- Enable 802.11r Fast Transaction with same mobility domain
- FT Protocol: FT over the Air
Quoted 1 line
From a openwrt system issue the command (with the correct mac)
ubus call hostapd.wlan1 wnm_disassoc_imminent '{"addr":"28:C2:1F:xx:xx:xx"}' Notice the log printing the errors.
The cause of this error has been investigated and we found that this is related to the WiFi Fast Transaction feature. We observed that this is triggered when the router tells the device to change band. In this case the device first auth to the other band and then the disconnect path from the prev band is triggered.
This is problematic with the current rhash implementation since the addrs is used as key and the logic of "adding first, delete later" conflicts with the rhash logic.
In fact peer addition will fail since the peer is already added and with that fixed a peer deletion will cause unitended effect by removing the peer just added.
Current solution to this is to add additional logic to the peer delete, make sure we are deleting the correct peer taken from the rhash table (and fallback to the peer list) and for the peer add logic delete the peer entry for the rhash list before adding the new one (counting as an error only when a peer with the same vlan_id is asked to be added).
With this change, a sta can correctly transition from 2.4GHz and 5GHZ with no drop and no error are printed.
Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.5.0.1-01208-QCAHKSWPL_SILICONZ-1
--- drivers/net/wireless/ath/ath11k/peer.c | 30 ++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-)
drivers/net/wireless/ath/ath11k/peer.c +26 -4
@@ -302,6 +302,21 @@ static int __ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, const u8 *addr)spin_lock_bh (&ab->base_lock); peer =ath11k_peer_find_by_addr (ab, addr); +/* Check if the found peer is what we want to remove. +* While the sta is transitioning to another band we may +* have 2 peer with the same addr assigned to different +* vdev_id. Make sure we are deleting the correct peer. +*/ +if (peer && peer->vdev_id == vdev_id) +ath11k_peer_rhash_delete (ab, peer); + +/* Fallback to peer list search if the correct peer can't be found. +* Skip the deletion of the peer from the rhash since it has already +* been deleted in peer add. +*/ +if (!peer) + peer =ath11k_peer_find (ab, vdev_id, addr); +if (!peer) {spin_unlock_bh (&ab->base_lock);mutex_unlock (&ab->tbl_mtx_lock);
@@ -312,8 +327,6 @@ static int __ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, const u8 *addr)return -EINVAL ; } -ath11k_peer_rhash_delete (ab, peer); -spin_unlock_bh (&ab->base_lock);mutex_unlock (&ab->tbl_mtx_lock);
@@ -372,8 +385,17 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,spin_lock_bh (&ar->ab->base_lock); peer =ath11k_peer_find_by_addr (ar->ab, param->peer_addr);if (peer) { -spin_unlock_bh (&ar->ab->base_lock); -return -EINVAL ; +if (peer->vdev_id == param->vdev_id) { +spin_unlock_bh (&ar->ab->base_lock); +return -EINVAL ; + } + +/* Assume sta is transitioning to another band. +* Remove here the peer from rhash. +*/ +mutex_lock (&ar->ab->tbl_mtx_lock); +ath11k_peer_rhash_delete (ar->ab, peer); +mutex_unlock (&ar->ab->tbl_mtx_lock); }spin_unlock_bh (&ar->ab->base_lock);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 264/717 x86/cpu: Include the header of init_ia32_feat_ctl()s prototype
In reply to Greg Kroah-HartmanFrom: Luciano Leão <[email protected]>
[ Upstream commit 30ea703a38ef76ca119673cd8bdd05c6e068e2ac ]
Include the header containing the prototype of init_ia32_feat_ctl(), solving the following warning:
$ make W=1 arch/x86/kernel/cpu/feat_ctl.o
arch/x86/kernel/cpu/feat_ctl.c:112:6: warning: no previous prototype for ‘init_ia32_feat_ctl’ [-Wmissing-prototypes]
112 | void init_ia32_feat_ctl(struct cpuinfo_x86 *c)This warning appeared after commit
5d5103595e9e5 ("x86/cpu: Reinitialize IA32_FEAT_CTL MSR on BSP during wakeup")
had moved the function init_ia32_feat_ctl()'s prototype from arch/x86/kernel/cpu/cpu.h to arch/x86/include/asm/cpu.h.
Note that, before the commit mentioned above, the header include "cpu.h" (arch/x86/kernel/cpu/cpu.h) was added by commit
0e79ad863df43 ("x86/cpu: Fix a -Wmissing-prototypes warning for init_ia32_feat_ctl()")
solely to fix init_ia32_feat_ctl()'s missing prototype. So, the header include "cpu.h" is no longer necessary.
[ bp: Massage commit message. ]
--- arch/x86/kernel/cpu/feat_ctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kernel/cpu/feat_ctl.c +1 -1
@@ -1,11 +1,11 @@// SPDX-License-Identifier: GPL-2.0 #include <linux/tboot.h> +#include <asm/cpu.h> #include <asm/cpufeature.h> #include <asm/msr-index.h> #include <asm/processor.h> #include <asm/vmx.h> -#include "cpu.h" #undef pr_fmt#define pr_fmt (fmt) "x86/cpu: " fmt
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 265/717 spi: cadence-quadspi: Fix PM disable depth imbalance in cqspi_probe
In reply to Greg Kroah-HartmanFrom: Zhang Qilong <[email protected]>
[ Upstream commit 4d0ef0a1c35189a6e8377d8ee8310ea5ef22c5f3 ]
The pm_runtime_enable will increase power disable depth. Thus a pairing decrement is needed on the error handling path to keep it balanced according to context.
--- drivers/spi/spi-cadence-quadspi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/spi-cadence-quadspi.c +2 -1
@@ -1619,7 +1619,7 @@ static int cqspi_probe(struct platform_device *pdev)pm_runtime_enable (dev); ret =pm_runtime_resume_and_get (dev);if (ret <0 ) -return ret; + goto probe_pm_failed; ret =clk_prepare_enable (cqspi->clk);if (ret) {
@@ -1712,6 +1712,7 @@ static int cqspi_probe(struct platform_device *pdev)clk_disable_unprepare (cqspi->clk); probe_clk_failed:pm_runtime_put_sync (dev); +probe_pm_failed:pm_runtime_disable (dev);return ret; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 266/717 spi: dw: Fix PM disable depth imbalance in dw_spi_bt1_probe
In reply to Greg Kroah-HartmanFrom: Zhang Qilong <[email protected]>
[ Upstream commit 618d815fc93477b1675878f3c04ff32657cc18b4 ]
The pm_runtime_enable will increase power disable depth. Thus a pairing decrement is needed on the error handling path to keep it balanced according to context.
--- drivers/spi/spi-dw-bt1.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/spi/spi-dw-bt1.c +3 -1
@@ -293,8 +293,10 @@ static int dw_spi_bt1_probe(struct platform_device *pdev)pm_runtime_enable (&pdev->dev); ret =dw_spi_add_host (&pdev->dev, dws); -if (ret) +if (ret) { +pm_runtime_disable (&pdev->dev); goto err_disable_clk; + }platform_set_drvdata (pdev, dwsbt1);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 267/717 spi/omap100k:Fix PM disable depth imbalance in omap1_spi100k_probe
In reply to Greg Kroah-HartmanFrom: Zhang Qilong <[email protected]>
[ Upstream commit 29f65f2171c85a9633daa380df14009a365f42f2 ]
The pm_runtime_enable will increase power disable depth. Thus a pairing decrement is needed on the error handling path to keep it balanced according to context.
--- drivers/spi/spi-omap-100k.c | 1 + 1 file changed, 1 insertion(+)
drivers/spi/spi-omap-100k.c +1 -0
@@ -412,6 +412,7 @@ static int omap1_spi100k_probe(struct platform_device *pdev)return status; err_fck: +pm_runtime_disable (&pdev->dev);clk_disable_unprepare (spi100k->fck); err_ick:clk_disable_unprepare (spi100k->ick);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 268/717 skmsg: Schedule psock work if the cached skb exists on the psock
In reply to Greg Kroah-HartmanFrom: Liu Jian <[email protected]>
[ Upstream commit bec217197b412d74168c6a42fc0f76d0cc9cad00 ]
In sk_psock_backlog function, for ingress direction skb, if no new data packet arrives after the skb is cached, the cached skb does not have a chance to be added to the receive queue of psock. As a result, the cached skb cannot be received by the upper-layer application. Fix this by reschedule the psock work to dispose the cached skb in sk_msg_recvmsg function.
--- net/core/skmsg.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
net/core/skmsg.c +8 -4
@@ -435,8 +435,10 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,if (copied + copy > len) copy = len - copied; copy =copy_page_to_iter (page, sge->offset, copy, iter); -if (!copy) -return copied ? copied : -EFAULT ; +if (!copy) { + copied = copied ? copied : -EFAULT ; + goto out; + } copied += copy;if (likely (!peek)) {
@@ -456,7 +458,7 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,* didn't copy the entire length lets just break. */ if (copy != sge->length) -return copied; + goto out;sk_msg_iter_var_next (i); }
@@ -478,7 +480,9 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg, } msg_rx =sk_psock_peek_msg (psock); } - +out: +if (psock->work_state.skb && copied >0 ) +schedule_work (&psock->work);return copied; }EXPORT_SYMBOL_GPL (sk_msg_recvmsg);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 269/717 cw1200: fix incorrect check to determine if no element is found in list
In reply to Greg Kroah-HartmanFrom: Xiaomeng Tong <[email protected]>
[ Upstream commit 86df5de5c632d3bd940f59bbb14ae912aa9cc363 ]
The bug is here: "} else if (item) {".
The list iterator value will *always* be set and non-NULL by list_for_each_entry(), so it is incorrect to assume that the iterator value will be NULL if the list is empty or no element is found in list.
Use a new value 'iter' as the list iterator, while use the old value 'item' as a dedicated pointer to point to the found element, which
1. can fix this bug, due to now 'item' is NULL only if it's not found.
2. do not need to change all the uses of 'item' after the loop.
3. can also limit the scope of the list iterator 'iter' *only inside* the traversal loop by simply declaring 'iter' inside the loop in the future, as usage of the iterator outside of the list_for_each_entry is considered harmful. https://lkml.org/lkml/2022/2/17/1032
--- drivers/net/wireless/st/cw1200/queue.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-)
drivers/net/wireless/st/cw1200/queue.c +10 -8
@@ -91,23 +91,25 @@ static void __cw1200_queue_gc(struct cw1200_queue *queue, bool unlock) {struct cw1200_queue_stats *stats = queue->stats; -struct cw1200_queue_item *item =NULL , *tmp; +struct cw1200_queue_item *item =NULL , *iter, *tmp;bool wakeup_stats = false; -list_for_each_entry_safe (item, tmp, &queue->queue, head) { -if (time_is_after_jiffies (item->queue_timestamp + queue->ttl)) +list_for_each_entry_safe (iter, tmp, &queue->queue, head) { +if (time_is_after_jiffies (iter->queue_timestamp + queue->ttl)) { + item = iter;break ; + } --queue->num_queued; - --queue->link_map_cache[item->txpriv.link_id]; + --queue->link_map_cache[iter->txpriv.link_id];spin_lock_bh (&stats->lock); --stats->num_queued; -if (!--stats->link_map_cache[item->txpriv.link_id]) +if (!--stats->link_map_cache[iter->txpriv.link_id]) wakeup_stats = true;spin_unlock_bh (&stats->lock);cw1200_debug_tx_ttl (stats->priv); -cw1200_queue_register_post_gc (head, item); - item->skb =NULL ; -list_move_tail (&item->head, &queue->free_pool); +cw1200_queue_register_post_gc (head, iter); + iter->skb =NULL ; +list_move_tail (&iter->head, &queue->free_pool); }if (wakeup_stats)
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 270/717 i2c: mlxbf: support lock mechanism
In reply to Greg Kroah-HartmanFrom: Asmaa Mnebhi <[email protected]>
[ Upstream commit 86067ccfa1424a26491542d6f6d7546d40b61a10 ]
Linux is not the only entity using the BlueField I2C busses so support a lock mechanism provided by hardware to avoid issues when multiple entities are trying to access the same bus.
The lock is acquired whenever written explicitely or the lock register is read. So make sure it is always released at the end of a successful or failed transaction.
--- drivers/i2c/busses/i2c-mlxbf.c | 44 ++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 5 deletions(-)
drivers/i2c/busses/i2c-mlxbf.c +39 -5
@@ -306,6 +306,7 @@ static u64 mlxbf_i2c_corepll_frequency;* exact. */ #define MLXBF_I2C_SMBUS_TIMEOUT (300 * 1000)/* 300ms */ +#define MLXBF_I2C_SMBUS_LOCK_POLL_TIMEOUT (300 * 1000)/* 300ms */ /* Encapsulates timing parameters. */ struct mlxbf_i2c_timings {
@@ -514,6 +515,25 @@ static bool mlxbf_smbus_master_wait_for_idle(struct mlxbf_i2c_priv *priv)return false; } +/* +* wait for the lock to be released before acquiring it. +*/ +static bool mlxbf_i2c_smbus_master_lock (struct mlxbf_i2c_priv *priv) +{ +if (mlxbf_smbus_poll (priv->smbus->io,MLXBF_I2C_SMBUS_MASTER_GW , +MLXBF_I2C_MASTER_LOCK_BIT , true, +MLXBF_I2C_SMBUS_LOCK_POLL_TIMEOUT )) +return true; + +return false; +} + +static void mlxbf_i2c_smbus_master_unlock (struct mlxbf_i2c_priv *priv) +{ +/* Clear the gw to clear the lock */ +writel (0 , priv->smbus->io +MLXBF_I2C_SMBUS_MASTER_GW ); +} +static bool mlxbf_i2c_smbus_transaction_success (u32 master_status,u32 cause_status) {
@@ -705,10 +725,19 @@ mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv, slave = request->slave &GENMASK (6 ,0 ); addr = slave <<1 ; -/* First of all, check whether the HW is idle. */ -if (WARN_ON (!mlxbf_smbus_master_wait_for_idle (priv))) +/* +* Try to acquire the smbus gw lock before any reads of the GW register since +* a read sets the lock. +*/ +if (WARN_ON (!mlxbf_i2c_smbus_master_lock (priv)))return -EBUSY ; +/* Check whether the HW is idle */ +if (WARN_ON (!mlxbf_smbus_master_wait_for_idle (priv))) { + ret = -EBUSY ; + goto out_unlock; + } +/* Set first byte. */ data_desc[data_idx++] = addr;
@@ -732,8 +761,10 @@ mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv, write_en =1 ; write_len += operation->length;if (data_idx + operation->length > -MLXBF_I2C_MASTER_DATA_DESC_SIZE ) -return -ENOBUFS ; +MLXBF_I2C_MASTER_DATA_DESC_SIZE ) { + ret = -ENOBUFS ; + goto out_unlock; + }memcpy (data_desc + data_idx, operation->buffer, operation->length); data_idx += operation->length;
@@ -765,7 +796,7 @@ mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv, ret =mlxbf_i2c_smbus_enable (priv, slave, write_len, block_en, pec_en,0 );if (ret) -return ret; + goto out_unlock; }if (read_en) {
@@ -792,6 +823,9 @@ mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv, priv->smbus->io + MLXBF_I2C_SMBUS_MASTER_FSM); } +out_unlock: +mlxbf_i2c_smbus_master_unlock (priv); +return ret; }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 271/717 Bluetooth: hci_core: Fix not handling link timeouts propertly
In reply to Greg Kroah-HartmanFrom: Luiz Augusto von Dentz <[email protected]>
[ Upstream commit 116523c8fac05d1d26f748fee7919a4ec5df67ea ]
Change that introduced the use of __check_timeout did not account for link types properly, it always assumes ACL_LINK is used thus causing hdev->acl_last_tx to be used even in case of LE_LINK and then again uses ACL_LINK with hci_link_tx_to.
To fix this __check_timeout now takes the link type as parameter and then procedure to use the right last_tx based on the link type and pass it to hci_link_tx_to.
--- net/bluetooth/hci_core.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-)
net/bluetooth/hci_core.c +23 -11
@@ -3370,15 +3370,27 @@ static inline int __get_blocks(struct hci_dev *hdev, struct sk_buff *skb)return DIV_ROUND_UP (skb->len -HCI_ACL_HDR_SIZE , hdev->block_len); } -static void __check_timeout (struct hci_dev *hdev,unsigned int cnt) +static void __check_timeout (struct hci_dev *hdev,unsigned int cnt,u8 type) { -if (!hci_dev_test_flag (hdev,HCI_UNCONFIGURED )) { -/* ACL tx timeout must be longer than maximum -* link supervision timeout (40.9 seconds) */ -if (!cnt &&time_after (jiffies, hdev->acl_last_tx + -HCI_ACL_TX_TIMEOUT )) -hci_link_tx_to (hdev,ACL_LINK ); +unsigned long last_tx; + +if (hci_dev_test_flag (hdev,HCI_UNCONFIGURED )) +return ; + +switch (type) { +case LE_LINK : + last_tx = hdev->le_last_tx; +break ; +default : + last_tx = hdev->acl_last_tx; +break ; } + +/* tx timeout must be longer than maximum link supervision timeout +* (40.9 seconds) +*/ +if (!cnt &&time_after (jiffies, last_tx +HCI_ACL_TX_TIMEOUT )) +hci_link_tx_to (hdev, type); }/* Schedule SCO */
@@ -3436,7 +3448,7 @@ static void hci_sched_acl_pkt(struct hci_dev *hdev)struct sk_buff *skb;int quote; -__check_timeout (hdev, cnt); +__check_timeout (hdev, cnt,ACL_LINK );while (hdev->acl_cnt && (chan =hci_chan_sent (hdev,ACL_LINK , "e))) {
@@ -3479,8 +3491,6 @@ static void hci_sched_acl_blk(struct hci_dev *hdev)int quote;u8 type; -__check_timeout (hdev, cnt); -BT_DBG ("%s" , hdev->name);if (hdev->dev_type ==HCI_AMP )
@@ -3488,6 +3498,8 @@ static void hci_sched_acl_blk(struct hci_dev *hdev)else type =ACL_LINK ; +__check_timeout (hdev, cnt, type); +while (hdev->block_cnt >0 && (chan =hci_chan_sent (hdev, type, "e))) {u32 priority = (skb_peek (&chan->data_q))->priority;
@@ -3561,7 +3573,7 @@ static void hci_sched_le(struct hci_dev *hdev) cnt = hdev->le_pkts ? hdev->le_cnt : hdev->acl_cnt; -__check_timeout (hdev, cnt); +__check_timeout (hdev, cnt,LE_LINK ); tmp = cnt;while (cnt && (chan =hci_chan_sent (hdev,LE_LINK , "e))) {
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 272/717 xfrm: Reinject transport-mode packets through workqueue
In reply to Greg Kroah-HartmanFrom: Liu Jian <[email protected]>
[ Upstream commit 4f4920669d21e1060b7243e5118dc3b71ced1276 ]
The following warning is displayed when the tcp6-multi-diffip11 stress test case of the LTP test suite is tested:
watchdog: BUG: soft lockup - CPU#0 stuck for 22s! [ns-tcpserver:48198] CPU: 0 PID: 48198 Comm: ns-tcpserver Kdump: loaded Not tainted 6.0.0-rc6+ #39 Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0 02/06/2015 pstate: 80400005 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : des3_ede_encrypt+0x27c/0x460 [libdes] lr : 0x3f
sp : ffff80000ceaa1b0
x29: ffff80000ceaa1b0 x28: ffff0000df056100 x27: ffff0000e51e5280
x26: ffff80004df75030 x25: ffff0000e51e4600 x24: 000000000000003b
x23: 0000000000802080 x22: 000000000000003d x21: 0000000000000038
x20: 0000000080000020 x19: 000000000000000a x18: 0000000000000033
x17: ffff0000e51e4780 x16: ffff80004e2d1448 x15: ffff80004e2d1248
x14: ffff0000e51e4680 x13: ffff80004e2d1348 x12: ffff80004e2d1548
x11: ffff80004e2d1848 x10: ffff80004e2d1648 x9 : ffff80004e2d1748 x8 : ffff80004e2d1948 x7 : 000000000bcaf83d x6 : 000000000000001b x5 : ffff80004e2d1048 x4 : 00000000761bf3bf x3 : 000000007f1dd0a3 x2 : ffff0000e51e4780 x1 : ffff0000e3b9a2f8 x0 : 00000000db44e872
Call trace: des3_ede_encrypt+0x27c/0x460 [libdes] crypto_des3_ede_encrypt+0x1c/0x30 [des_generic] crypto_cbc_encrypt+0x148/0x190 crypto_skcipher_encrypt+0x2c/0x40 crypto_authenc_encrypt+0xc8/0xfc [authenc] crypto_aead_encrypt+0x2c/0x40 echainiv_encrypt+0x144/0x1a0 [echainiv] crypto_aead_encrypt+0x2c/0x40 esp6_output_tail+0x1c8/0x5d0 [esp6] esp6_output+0x120/0x278 [esp6] xfrm_output_one+0x458/0x4ec xfrm_output_resume+0x6c/0x1f0 xfrm_output+0xac/0x4ac __xfrm6_output+0x130/0x270 xfrm6_output+0x60/0xec ip6_xmit+0x2ec/0x5bc inet6_csk_xmit+0xbc/0x10c __tcp_transmit_skb+0x460/0x8c0 tcp_write_xmit+0x348/0x890 __tcp_push_pending_frames+0x44/0x110 tcp_rcv_established+0x3c8/0x720 tcp_v6_do_rcv+0xdc/0x4a0 tcp_v6_rcv+0xc24/0xcb0 ip6_protocol_deliver_rcu+0xf0/0x574 ip6_input_finish+0x48/0x7c ip6_input+0x48/0xc0 ip6_rcv_finish+0x80/0x9c xfrm_trans_reinject+0xb0/0xf4 tasklet_action_common.constprop.0+0xf8/0x134 tasklet_action+0x30/0x3c __do_softirq+0x128/0x368 do_softirq+0xb4/0xc0 __local_bh_enable_ip+0xb0/0xb4 put_cpu_fpsimd_context+0x40/0x70 kernel_neon_end+0x20/0x40 sha1_base_do_update.constprop.0.isra.0+0x11c/0x140 [sha1_ce] sha1_ce_finup+0x94/0x110 [sha1_ce] crypto_shash_finup+0x34/0xc0 hmac_finup+0x48/0xe0 crypto_shash_finup+0x34/0xc0 shash_digest_unaligned+0x74/0x90 crypto_shash_digest+0x4c/0x9c shash_ahash_digest+0xc8/0xf0 shash_async_digest+0x28/0x34 crypto_ahash_digest+0x48/0xcc crypto_authenc_genicv+0x88/0xcc [authenc] crypto_authenc_encrypt+0xd8/0xfc [authenc] crypto_aead_encrypt+0x2c/0x40 echainiv_encrypt+0x144/0x1a0 [echainiv] crypto_aead_encrypt+0x2c/0x40 esp6_output_tail+0x1c8/0x5d0 [esp6] esp6_output+0x120/0x278 [esp6] xfrm_output_one+0x458/0x4ec xfrm_output_resume+0x6c/0x1f0 xfrm_output+0xac/0x4ac __xfrm6_output+0x130/0x270 xfrm6_output+0x60/0xec ip6_xmit+0x2ec/0x5bc inet6_csk_xmit+0xbc/0x10c __tcp_transmit_skb+0x460/0x8c0 tcp_write_xmit+0x348/0x890 __tcp_push_pending_frames+0x44/0x110 tcp_push+0xb4/0x14c tcp_sendmsg_locked+0x71c/0xb64 tcp_sendmsg+0x40/0x6c inet6_sendmsg+0x4c/0x80 sock_sendmsg+0x5c/0x6c __sys_sendto+0x128/0x15c __arm64_sys_sendto+0x30/0x40 invoke_syscall+0x50/0x120 el0_svc_common.constprop.0+0x170/0x194 do_el0_svc+0x38/0x4c el0_svc+0x28/0xe0 el0t_64_sync_handler+0xbc/0x13c el0t_64_sync+0x180/0x184
Get softirq info by bcc tool:
./softirqs -NT 10
Tracing soft irq event time... Hit Ctrl-C to end.
15:34:34
SOFTIRQ TOTAL_nsecs
block 158990
timer 20030920
sched 46577080net_rx 676746820
tasklet 9906067650
15:34:45
SOFTIRQ TOTAL_nsecs
block 86100
sched 38849790net_rx 676532470
timer 1163848790
tasklet 9409019620
15:34:55
SOFTIRQ TOTAL_nsecs
sched 58078450net_rx 475156720
timer 533832410
tasklet 9431333300
The tasklet software interrupt takes too much time. Therefore, the xfrm_trans_reinject executor is changed from tasklet to workqueue. Add add spin lock to protect the queue. This reduces the processing flow of the tcp_sendmsg function in this scenario.
--- net/xfrm/xfrm_input.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-)
net/xfrm/xfrm_input.c +13 -5
@@ -24,7 +24,8 @@#include "xfrm_inout.h" struct xfrm_trans_tasklet { -struct tasklet_struct tasklet; +struct work_struct work; +spinlock_t queue_lock;struct sk_buff_head queue; };
@@ -760,18 +761,22 @@ int xfrm_input_resume(struct sk_buff *skb, int nexthdr) }EXPORT_SYMBOL (xfrm_input_resume); -static void xfrm_trans_reinject (struct tasklet_struct *t) +static void xfrm_trans_reinject (struct work_struct *work) { -struct xfrm_trans_tasklet *trans =from_tasklet (trans, t, tasklet); + struct xfrm_trans_tasklet *trans = container_of(work, struct xfrm_trans_tasklet, work);struct sk_buff_head queue;struct sk_buff *skb;__skb_queue_head_init (&queue); +spin_lock_bh (&trans->queue_lock);skb_queue_splice_init (&trans->queue, &queue); +spin_unlock_bh (&trans->queue_lock); +local_bh_disable ();while ((skb =__skb_dequeue (&queue)))XFRM_TRANS_SKB_CB (skb)->finish (XFRM_TRANS_SKB_CB (skb)->net,NULL , skb); +local_bh_enable (); } int xfrm_trans_queue_net(struct net *net, struct sk_buff *skb,
@@ -789,8 +794,10 @@ int xfrm_trans_queue_net(struct net *net, struct sk_buff *skb,XFRM_TRANS_SKB_CB (skb)->finish = finish;XFRM_TRANS_SKB_CB (skb)->net = net; +spin_lock_bh (&trans->queue_lock);__skb_queue_tail (&trans->queue, skb); -tasklet_schedule (&trans->tasklet); +spin_unlock_bh (&trans->queue_lock); +schedule_work (&trans->work);return 0 ; }EXPORT_SYMBOL (xfrm_trans_queue_net);
@@ -817,7 +824,8 @@ void __init xfrm_input_init(void)struct xfrm_trans_tasklet *trans; trans = &per_cpu (xfrm_trans_tasklet, i); +spin_lock_init (&trans->queue_lock);__skb_queue_head_init (&trans->queue); -tasklet_setup (&trans->tasklet, xfrm_trans_reinject); +INIT_WORK (&trans->work, xfrm_trans_reinject); } }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 273/717 netfilter: nft_fib: Fix for rpath check with VRF devices
In reply to Greg Kroah-HartmanFrom: Phil Sutter <[email protected]>
[ Upstream commit 2a8a7c0eaa8747c16aa4a48d573aa920d5c00a5c ]
Analogous to commit b575b24b8eee3 ("netfilter: Fix rpfilter dropping vrf packets by mistake") but for nftables fib expression:
Add special treatment of VRF devices so that typical reverse path filtering via 'fib saddr . iif oif' expression works as expected.
--- net/ipv4/netfilter/nft_fib_ipv4.c | 3 +++ net/ipv6/netfilter/nft_fib_ipv6.c | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-)
net/ipv4/netfilter/nft_fib_ipv4.c +3 -0
@@ -83,6 +83,9 @@ void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs,else oif =NULL ; +if (priv->flags &NFTA_FIB_F_IIF ) + fl4.flowi4_oif =l3mdev_master_ifindex_rcu (oif); +if (nft_hook (pkt) ==NF_INET_PRE_ROUTING &&nft_fib_is_loopback (pkt->skb,nft_in (pkt))) {nft_fib_store_result (dest, priv,nft_in (pkt));
net/ipv6/netfilter/nft_fib_ipv6.c +5 -1
@@ -41,6 +41,9 @@ static int nft_fib6_flowi_init(struct flowi6 *fl6, const struct nft_fib *priv,if (ipv6_addr_type (&fl6->daddr) &IPV6_ADDR_LINKLOCAL ) { lookup_flags |=RT6_LOOKUP_F_IFACE ; fl6->flowi6_oif =get_ifindex (dev ? dev : pkt->skb->dev); + }else if ((priv->flags &NFTA_FIB_F_IIF ) && + (netif_is_l3_master (dev) ||netif_is_l3_slave (dev))) { + fl6->flowi6_oif = dev->ifindex; }if (ipv6_addr_type (&fl6->saddr) &IPV6_ADDR_UNICAST )
@@ -197,7 +200,8 @@ void nft_fib6_eval(const struct nft_expr *expr, struct nft_regs *regs,if (rt->rt6i_flags & (RTF_REJECT |RTF_ANYCAST |RTF_LOCAL )) goto put_rt_err; -if (oif && oif != rt->rt6i_idev->dev) +if (oif && oif != rt->rt6i_idev->dev && +l3mdev_master_ifindex_rcu (rt->rt6i_idev->dev) != oif->ifindex) goto put_rt_err;nft_fib_store_result (dest, priv, rt->rt6i_idev->dev);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 274/717 spi: s3c64xx: Fix large transfers with DMA
In reply to Greg Kroah-HartmanFrom: Vincent Whitchurch <[email protected]>
[ Upstream commit 1224e29572f655facfcd850cf0f0a4784f36a903 ]
The COUNT_VALUE in the PACKET_CNT register is 16-bit so the maximum value is 65535. Asking the driver to transfer a larger size currently leads to the DMA transfer timing out. Implement ->max_transfer_size() and have the core split the transfer as needed.
--- drivers/spi/spi-s3c64xx.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/spi/spi-s3c64xx.c +9 -0
@@ -83,6 +83,7 @@#define S3C64XX_SPI_ST_TX_FIFORDY (1<<0)#define S3C64XX_SPI_PACKET_CNT_EN (1<<16) +#define S3C64XX_SPI_PACKET_CNT_MASK GENMASK(15, 0)#define S3C64XX_SPI_PND_TX_UNDERRUN_CLR (1<<4)#define S3C64XX_SPI_PND_TX_OVERRUN_CLR (1<<3)
@@ -663,6 +664,13 @@ static int s3c64xx_spi_prepare_message(struct spi_master *master,return 0 ; } +static size_t s3c64xx_spi_max_transfer_size (struct spi_device *spi) +{ +struct spi_controller *ctlr = spi->controller; + +return ctlr->can_dma ?S3C64XX_SPI_PACKET_CNT_MASK :SIZE_MAX ; +} +static int s3c64xx_spi_transfer_one (struct spi_master *master,struct spi_device *spi,struct spi_transfer *xfer)
@@ -1100,6 +1108,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer; master->prepare_message = s3c64xx_spi_prepare_message; master->transfer_one = s3c64xx_spi_transfer_one; + master->max_transfer_size = s3c64xx_spi_max_transfer_size; master->num_chipselect = sci->num_cs; master->use_gpio_descriptors = true; master->dma_alignment =8 ;
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 275/717 wifi: rtl8xxxu: gen2: Enable 40 MHz channel width
In reply to Greg Kroah-HartmanFrom: Bitterblue Smith <[email protected]>
[ Upstream commit a8b5aef2cca15b7fa533421d462e4e0a3429bd6f ]
The module parameter ht40_2g was supposed to enable 40 MHz operation, but it didn't.
Tell the firmware about the channel width when updating the rate mask. This makes it work with my gen 2 chip RTL8188FU.
I'm not sure if anything needs to be done for the gen 1 chips, if 40 MHz channel width already works or not. They update the rate mask with a different structure which doesn't have a field for the channel width.
Also set the channel width correctly for sta_statistics.
--- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 6 +++--- .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 21 +++++++++++++------ 2 files changed, 18 insertions(+), 9 deletions(-)
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +3 -3
@@ -1425,7 +1425,7 @@ struct rtl8xxxu_fileops {void (*set_tx_power) (struct rtl8xxxu_priv *priv,int channel,bool ht40);void (*update_rate_mask) (struct rtl8xxxu_priv *priv, -u32 ramask,u8 rateid,int sgi); +u32 ramask,u8 rateid,int sgi,int txbw_40mhz);void (*report_connect) (struct rtl8xxxu_priv *priv,u8 macid,bool connect); void (*fill_txdesc) (struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
@@ -1511,9 +1511,9 @@ void rtl8xxxu_gen2_config_channel(struct ieee80211_hw *hw);void rtl8xxxu_gen1_usb_quirks (struct rtl8xxxu_priv *priv);void rtl8xxxu_gen2_usb_quirks (struct rtl8xxxu_priv *priv);void rtl8xxxu_update_rate_mask (struct rtl8xxxu_priv *priv, -u32 ramask,u8 rateid,int sgi); +u32 ramask,u8 rateid,int sgi,int txbw_40mhz);void rtl8xxxu_gen2_update_rate_mask (struct rtl8xxxu_priv *priv, -u32 ramask,u8 rateid,int sgi); +u32 ramask,u8 rateid,int sgi,int txbw_40mhz);void rtl8xxxu_gen1_report_connect (struct rtl8xxxu_priv *priv,u8 macid,bool connect); void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv,
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +15 -6
@@ -4320,7 +4320,7 @@ static void rtl8xxxu_sw_scan_complete(struct ieee80211_hw *hw, }void rtl8xxxu_update_rate_mask (struct rtl8xxxu_priv *priv, -u32 ramask,u8 rateid,int sgi) +u32 ramask,u8 rateid,int sgi,int txbw_40mhz) {struct h2c_cmd h2c;
@@ -4340,10 +4340,15 @@ void rtl8xxxu_update_rate_mask(struct rtl8xxxu_priv *priv, }void rtl8xxxu_gen2_update_rate_mask (struct rtl8xxxu_priv *priv, -u32 ramask,u8 rateid,int sgi) +u32 ramask,u8 rateid,int sgi,int txbw_40mhz) {struct h2c_cmd h2c; -u8 bw =RTL8XXXU_CHANNEL_WIDTH_20 ; +u8 bw; + +if (txbw_40mhz) + bw =RTL8XXXU_CHANNEL_WIDTH_40 ; +else + bw =RTL8XXXU_CHANNEL_WIDTH_20 ;memset (&h2c,0 ,sizeof (struct h2c_cmd ));
@@ -4621,7 +4626,11 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,RATE_INFO_FLAGS_SHORT_GI ; } - rarpt->txrate.bw |=RATE_INFO_BW_20 ; +if (rtl8xxxu_ht40_2g && + (sta->deflink.ht_cap.cap &IEEE80211_HT_CAP_SUP_WIDTH_20_40 )) + rarpt->txrate.bw =RATE_INFO_BW_40 ; +else + rarpt->txrate.bw =RATE_INFO_BW_20 ; } bit_rate =cfg80211_calculate_bitrate (&rarpt->txrate); rarpt->bit_rate = bit_rate;
@@ -4630,7 +4639,7 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, priv->vif = vif; priv->rssi_level =RTL8XXXU_RATR_STA_INIT ; - priv->fops->update_rate_mask (priv, ramask,0 , sgi); + priv->fops->update_rate_mask (priv, ramask,0 , sgi, rarpt->txrate.bw ==RATE_INFO_BW_40 );rtl8xxxu_write8 (priv,REG_BCN_MAX_ERR ,0xff );
@@ -6343,7 +6352,7 @@ static void rtl8xxxu_refresh_rate_mask(struct rtl8xxxu_priv *priv, } priv->rssi_level = rssi_level; - priv->fops->update_rate_mask (priv, rate_bitmap, ratr_idx, sgi); + priv->fops->update_rate_mask (priv, rate_bitmap, ratr_idx, sgi, txbw_40mhz); } }
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 276/717 wifi: rtl8xxxu: Fix AIFS written to REG_EDCA_*_PARAM
In reply to Greg Kroah-HartmanFrom: Bitterblue Smith <[email protected]>
[ Upstream commit 5574d3290449916397f3092dcd2bac92415498e1 ]
ieee80211_tx_queue_params.aifs is not supposed to be written directly to the REG_EDCA_*_PARAM registers. Instead process it like the vendor drivers do. It's kinda hacky but it works.
This change boosts the download speed and makes it more stable.
Tested with RTL8188FU but all the other supported chips should also benefit.
--- .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+)
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +49 -0
@@ -4560,6 +4560,53 @@ rtl8xxxu_wireless_mode(struct ieee80211_hw *hw, struct ieee80211_sta *sta)return network_type; } +static void rtl8xxxu_set_aifs (struct rtl8xxxu_priv *priv,u8 slot_time) +{ +u32 reg_edca_param[IEEE80211_NUM_ACS ] = { + [IEEE80211_AC_VO ] =REG_EDCA_VO_PARAM , + [IEEE80211_AC_VI ] =REG_EDCA_VI_PARAM , + [IEEE80211_AC_BE ] =REG_EDCA_BE_PARAM , + [IEEE80211_AC_BK ] =REG_EDCA_BK_PARAM , + }; +u32 val32; +u16 wireless_mode =0 ; +u8 aifs, aifsn, sifs; +int i; + +if (priv->vif) { +struct ieee80211_sta *sta; + +rcu_read_lock (); + sta =ieee80211_find_sta (priv->vif, priv->vif->bss_conf.bssid); +if (sta) + wireless_mode =rtl8xxxu_wireless_mode (priv->hw, sta); +rcu_read_unlock (); + } + +if (priv->hw->conf.chandef.chan->band ==NL80211_BAND_5GHZ || + (wireless_mode &WIRELESS_MODE_N_24G )) + sifs =16 ; +else + sifs =10 ; + +for (i =0 ; i <IEEE80211_NUM_ACS ; i++) { + val32 =rtl8xxxu_read32 (priv, reg_edca_param[i]); + +/* It was set in conf_tx. */ + aifsn = val32 &0xff ; + +/* aifsn not set yet or already fixed */ +if (aifsn <2 || aifsn >15 ) +continue ; + + aifs = aifsn * slot_time + sifs; + + val32 &= ~0xff ; + val32 |= aifs; +rtl8xxxu_write32 (priv, reg_edca_param[i], val32); + } +} +static void rtl8xxxu_bss_info_changed (struct ieee80211_hw *hw,struct ieee80211_vif *vif,struct ieee80211_bss_conf *bss_conf,u32 changed)
@@ -4679,6 +4726,8 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,else val8 =20 ;rtl8xxxu_write8 (priv,REG_SLOT , val8); + +rtl8xxxu_set_aifs (priv, val8); }if (changed &BSS_CHANGED_BSSID ) {
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 277/717 vhost/vsock: Use kvmalloc/kvfree for larger packets.
In reply to Greg Kroah-HartmanFrom: Junichi Uekawa <[email protected]>
[ Upstream commit 0e3f72931fc47bb81686020cc643cde5d9cd0bb8 ]
When copying a large file over sftp over vsock, data size is usually 32kB, and kmalloc seems to fail to try to allocate 32 32kB regions.
vhost-5837: page allocation failure: order:4, mode:0x24040c0
Call Trace: [<ffffffffb6a0df64>] dump_stack+0x97/0xdb [<ffffffffb68d6aed>] warn_alloc_failed+0x10f/0x138 [<ffffffffb68d868a>] ? __alloc_pages_direct_compact+0x38/0xc8 [<ffffffffb664619f>] __alloc_pages_nodemask+0x84c/0x90d [<ffffffffb6646e56>] alloc_kmem_pages+0x17/0x19 [<ffffffffb6653a26>] kmalloc_order_trace+0x2b/0xdb [<ffffffffb66682f3>] __kmalloc+0x177/0x1f7 [<ffffffffb66e0d94>] ? copy_from_iter+0x8d/0x31d [<ffffffffc0689ab7>] vhost_vsock_handle_tx_kick+0x1fa/0x301 [vhost_vsock] [<ffffffffc06828d9>] vhost_worker+0xf7/0x157 [vhost] [<ffffffffb683ddce>] kthread+0xfd/0x105 [<ffffffffc06827e2>] ? vhost_dev_set_owner+0x22e/0x22e [vhost] [<ffffffffb683dcd1>] ? flush_kthread_worker+0xf3/0xf3 [<ffffffffb6eb332e>] ret_from_fork+0x4e/0x80 [<ffffffffb683dcd1>] ? flush_kthread_worker+0xf3/0xf3
Work around by doing kvmalloc instead.
--- drivers/vhost/vsock.c | 2 +- net/vmw_vsock/virtio_transport_common.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/vhost/vsock.c +1 -1
@@ -393,7 +393,7 @@ vhost_vsock_alloc_pkt(struct vhost_virtqueue *vq,return NULL ; } - pkt->buf =kmalloc (pkt->len,GFP_KERNEL ); + pkt->buf =kvmalloc (pkt->len,GFP_KERNEL );if (!pkt->buf) {kfree (pkt);return NULL ;
net/vmw_vsock/virtio_transport_common.c +1 -1
@@ -1342,7 +1342,7 @@ EXPORT_SYMBOL_GPL(virtio_transport_recv_pkt);void virtio_transport_free_pkt (struct virtio_vsock_pkt *pkt) { -kfree (pkt->buf); +kvfree (pkt->buf);kfree (pkt); }EXPORT_SYMBOL_GPL (virtio_transport_free_pkt);
Signature · 1 line
2.35.1
Greg Kroah-Hartman
maintainerPATCH 278/717 eth: alx: take rtnl_lock on resume
In reply to Greg Kroah-HartmanFrom: Jakub Kicinski <[email protected]>
[ Upstream commit 6ad1c94e1e7e374d88f0cfd77936dddb8339aaba ]
Zbynek reports that alx trips an rtnl assertion on resume:
RTNL: assertion failed at net/core/dev.c (2891)
RIP: 0010:netif_set_real_num_tx_queues+0x1ac/0x1c0 Call Trace: <TASK> __alx_open+0x230/0x570 [alx] alx_resume+0x54/0x80 [alx] ? pci_legacy_resume+0x80/0x80 dpm_run_callback+0x4a/0x150 device_resume+0x8b/0x190 async_resume+0x19/0x30 async_run_entry_fn+0x30/0x130 process_one_work+0x1e5/0x3b0
indeed the driver does not hold rtnl_lock during its internal close and re-open functions during suspend/resume. Note that this is not a huge bug as the driver implements its own locking, and does not implement changing the number of queues, but we need to silence the splat.
--- drivers/net/ethernet/atheros/alx/main.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/net/ethernet/atheros/alx/main.c +5 -0
@@ -1912,11 +1912,14 @@ static int alx_suspend(struct device *dev)if (!netif_running (alx->dev))return 0 ; + +rtnl_lock ();netif_device_detach (alx->dev);mutex_lock (&alx->mtx);__alx_stop (alx);mutex_unlock (&alx->mtx); +rtnl_unlock ();return 0 ; }
@@ -1927,6 +1930,7 @@ static int alx_resume(struct device *dev)struct alx_hw *hw = &alx->hw;int err; +rtnl_lock ();mutex_lock (&alx->mtx);alx_reset_phy (hw);
@@ -1943,6 +1947,7 @@ static int alx_resume(struct device *dev) unlock:mutex_unlock (&alx->mtx); +rtnl_unlock ();return err; }
Signature · 1 line
2.35.1